更新时间:2023-10-08 12:09:58
让我们分步看看会发生什么:
Let's see in steps what should happen:
< img>
元素。 src
属性。 src
属性需要指向有效的 http://
URL,因此不是本地磁盘文件系统路径 file://
,因为当服务器和客户端在物理上不同的机器上运行时,它永远不会工作。 http://example.com/context/images/foo.png
)或作为请求参数(例如 http://example.com/context/images?id=1
)。 / images / *
,这样你就可以了可以只在特定的URL上执行一些Java代码。 byte []
或 InputStream $获取c $ c>来自数据库, JDBC API 提供 ResultSet#getBytes()
和 ResultSet#getBinaryStream()
,以及 JPA API 提供 @Lob
。
byte []
或 InputStream
写到 OutputStream
通常的反应 Java IO 方式。还需要设置Content-Type
响应标头。你可以通过 ServletContext#getMimeType()
基于图像文件扩展名,您可以通过< mime-mapping> in web.xml
。
<img>
element. src
attribute. src
attribute needs to point to a valid http://
URL and thus not a local disk file system path file://
as that would never work when the server and client run at physically different machines.http://example.com/context/images/foo.png
) or as request parameter (e.g. http://example.com/context/images?id=1
). /images/*
, so that you can just execute some Java code on specific URL's. byte[]
or InputStream
from the DB, the JDBC API offers the ResultSet#getBytes()
and ResultSet#getBinaryStream()
for this, and JPA API offers @Lob
for this.byte[]
or InputStream
to the OutputStream
of the response the usual Java IO way.Content-Type
response header needs to be set as well. You can obtain the right one via ServletContext#getMimeType()
based on image file extension which you can extend and/or override via <mime-mapping>
in web.xml
.那应该是它。它几乎写了代码本身。让我们从HTML开始(在 JSP 中):
That should be it. It almost writes code itself. Let's start with HTML (in JSP):
<img src="${pageContext.request.contextPath}/images/foo.png">
<img src="${pageContext.request.contextPath}/images/bar.png">
<img src="${pageContext.request.contextPath}/images/baz.png">
您可以根据需要动态设置 src
使用 JSTL进行迭代时使用 EL :
You can if necessary also dynamically set src
with EL while iterating using JSTL:
<c:forEach items="${imagenames}" var="imagename">
<img src="${pageContext.request.contextPath}/images/${imagename}">
</c:forEach>
然后定义/创建 servlet 在 / images / *
的URL模式上侦听GET请求,下面的示例使用普通的vanilla JDBC来完成这项工作:
Then define/create a servlet which listens on GET requests on URL pattern of /images/*
, the below example uses plain vanilla JDBC for the job:
@WebServlet("/images/*")
public class ImageServlet extends HttpServlet {
// content=blob, name=varchar(255) UNIQUE.
private static final String SQL_FIND = "SELECT content FROM Image WHERE name = ?";
@Resource(name="jdbc/yourDB") // For Tomcat, define as <Resource> in context.xml and declare as <resource-ref> in web.xml.
private DataSource dataSource;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String imageName = request.getPathInfo().substring(1); // Returns "foo.png".
try (Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL_FIND)) {
statement.setString(1, imageName);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
byte[] content = resultSet.getBytes("content");
response.setContentType(getServletContext().getMimeType(imageName));
response.setContentLength(content.length);
response.getOutputStream().write(content);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
}
}
} catch (SQLException e) {
throw new ServletException("Something failed at SQL/DB level.", e);
}
}
}
这就是它。如果您担心HEAD和缓存标头并正确响应这些请求,请使用此静态资源servlet的抽象模板。
That's it. In case you worry about HEAD and caching headers and properly responding on those requests, use this abstract template for static resource servlet.