Jakarta EE 编程/Servlet
Servlet 是在服务器端运行的 Java 类,它接收 HTTP 数据,并在遵循 HTTP 协议的约束条件下进行处理或执行其他操作。
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Hello
*/
@WebServlet("/Hello")
public class Hello extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Hello() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("Hello World");
} finally {
out.close();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request,response);
}
}
我们注意到这个类中有两个方法:doGet()
和 doPost()
。第一个方法通过 HTTP 响应对 GET 请求的接收,第二个方法响应对 POST 请求的接收。由于我们希望在两种情况下 Servlet 都能处理请求,因此 doPost()
会转发到 doGet()
。
- 将编译后的类及其包放入工作 Web 目录的
WEB-INF
中的classes
目录中(这里:webTest
) - 通过添加以下内容来编辑
WEB-INF
中的web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="true">
<!-- Beginning here -->
<servlet>
<servlet-name>Hello</servlet-name><!-- Class name -->
<servlet-class>servlet.Hello</servlet-class><!-- Class tree: with the package -->
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name><!-- Class name -->
<url-pattern>/Hello</url-pattern><!-- Class pattern in the URL-->
</servlet-mapping>
<!-- End here -->
<web-app>
因此 WEB-INF
包含
WEB-INF web.xml classes servlet Hello.class
https://127.0.0.1:999/webTest/Hello
浏览器中的结果
Hello World
[协议://][DNS]:[端口]/[根目录]/[Servlet 名称]
// Returns the server name
request.getServerName();
// Returns the server port
request.getServerPort();
// Returns the name of the application hosting the servlet
request.getContextPath();
// Returns the servlet path
request.getServletPath();
// Returns the type of the HTTP request used
request.getMethod();
// Returns the parameters sent in the URL
request.getQueryString();
// Returns the URL used to contact the servlet
request.getRequestURL();
// Returns the local address
request.getLocalAddr();
// Returns the local name
request.getLocalName();
// Returns the local port
request.getLocalPort();
// Returns the remote address
request.getRemoteAddr();
// Returns the remote host
request.getRemoteHost();
Servlet 中的示例
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Hello
*/
@WebServlet("/Hello")
public class Hello extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Hello() {
super();
// TODO Auto-generated constructor stub
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println(request.getServerName());
out.println("<br/>");
out.println(request.getServerPort());
out.println("<br/>");
out.println(request.getContextPath());
out.println("<br/>");
out.println(request.getServletPath());
out.println("<br/>");
out.println(request.getMethod());
out.println("<br/>");
out.println(request.getQueryString());
out.println("<br/>");
out.println(request.getRequestURL());
out.println("<br/>");
out.println(request.getLocalAddr());
out.println("<br/>");
out.println(request.getLocalName());
out.println("<br/>");
out.println(request.getLocalPort());
out.println("<br/>");
out.println(request.getRemoteAddr());
out.println("<br/>");
out.println(request.getRemoteHost());
} finally {
out.close();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
}
相关调用:https://127.0.0.1:999/webTest/Hello
localhost 999 /webTest /Hello GET null https://127.0.0.1:999/webTest/Hello 127.0.0.1 localhost 999 127.0.0.1 127.0.0.1
// Parameter retrieving by the "parameterName"
request.getParameter(parameterName);
// Returns an enumeration of all the parameters of a request
request.getParameterNames();
// Returns all the parameter values of "parameterName"
request.getParameterValues(parameterName);
// Returns an iteration of the parameter names
request.getParameterMap();
// Returns the header names
request.getHeaderNames();
// Returns the headers
request.getHeaders();
// Returns the number of bytes of the request
request.getContentLength();
// Returns the content type of the request
request.getContentType();
// Returns the default language
request.getLocale();
// Returns the list of languages
request.getLocales();
// Returns the header date
request.getDateHeader(String name);
// Returns the header specified by the "name"
request.getHeader(String name);
// Returns the headers specified by the "name"
request.getHeaders(String name);
// Store an object in the HttpServletRequest object
request.setAttribute(String name, Object o);
// Returns the stored object "name"
request.getAttribute(String name);
// Returns an enumeration of the attribute names
request.getAttributeNames();
// Remove the attribute "name" the attributes of the request
request.removeAttribute(String name);
HTTP 头信息为响应添加补充信息。
// Indicates the nature of the information put into the response
response.setContentType(String type);
// Indicates the local language
response.setLocale(Locale loc);
// Adds the header "name" with the value "value"
response.addHeader(String name, String value);
(PrintWriter)getWriter()
允许将文本传输到 HTTP 响应主体。(ServletOutputStream)getOutputStream()
允许将二进制数据传输到 HTTP 响应主体。
切勿同时使用这两种方法,否则会导致 IllegalStateException
异常。
以下是一个二进制发送的示例
package servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ReponseHttp2
*/
@WebServlet("/HttpResponse2")
public class HttpResponse2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HttpResponse2() {
super();
// TODO Auto-generated constructor stub
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendRedirect("images/toto.jpg");
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
}
在这个示例中,我们使用 processRequest(request, response)
来始终在 GET 或 POST 中获得相同的处理过程。
状态码分为 5 类
- 1XX:信息
- 2XX:成功
- 3XX:重定向
- 4XX:客户端错误
- 5XX:服务器错误
有关这些代码的详细信息,请访问 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
setStatus(int rc)
sendError(int sc, String message)
... 允许设置页面的错误状态。例如,我们将生成一个服务器错误。
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ReponseHTTP
*/
@WebServlet("/ReponseHTTP")
public class ReponseHTTP extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ReponseHTTP() {
super();
// TODO Auto-generated constructor stub
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "the server is overloaded. Please try later.");
} finally {
out.close();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
processRequest(request, response);
}
}
包含外部资源。
RequestDispatcher rd = null;
rd = getServletContext().getRequestDispatcher("/header.html");
rd.include(request, response);
Servlet 结果传输到另一个资源。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.HttpServlet;
import javax.servlet.HttpServletRequest;
import javax.servlet.HttpServletResponse;
public class Result extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
int result = 10;
RequestDispatcher rd = null;
rd = getServletContext().getRequestDispatcher("/result.jsp");
request.setAttribute("theResult", result);
rd.forward(request, response);
} finally {
out.close();
}
}
}
目标资源:result.jsp
<%@page contentType="text/html" pageEncoding="UTF-8">
<%@page import="java.text.*" %>
<html>
<body>
<%
theResult = (double) request.getAttribute("theResult");
%>
Result: <%= theResult %>
</body>
</html>
服务器通知浏览器向给定的 URL 发送 HTTP 请求。
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // For a 301 HTTP response
response.setHeader("location", "http://www.google.be"); // For a 302 HTTP response
response.sendRedirect("http://www.google.be");
过滤器在 HTTP 请求被 Servlet 接收之前或在 HTTP 响应被返回之前添加一个处理过程。
其作用包括:
- 访问控制
- 访问日志
- 数据解压缩
- 解密
- 数据转换
可以依次执行多个响应。过滤器类必须实现 javax.servlet.Filter
接口。
事件通知应用程序操作,例如对象的实例化和销毁。
- 应用程序相关事件:由 Servlet 上下文触发的事件。
- 会话相关事件:这些类必须实现
HttpSessionListener
和HttpSessionAttributeListener
接口。
这种同步避免了服务器同时使用两个线程,例如当同一个类的两个实例使用两个不同的客户端调用同一个方法时。synchronized(this){}
必须应用于关键进程,例如计数器。
public class ... {
public void method() {
out = response.getWriter();
synchronized(this) {
counter++;
}
out.println("The counter value is " + counter);
}
}