Java Servlet基础教程

什么是Servlet

Servlet是Java Web开发的核心技术,它是运行在Web服务器上的Java类,用于处理客户端发送到服务器的请求并返回响应。Servlet提供了一种组件化的、独立于平台的方法来构建基于Web的应用程序。

Servlet的工作原理

  1. 客户端(通常是浏览器)向服务器发送HTTP请求
  2. 服务器将请求传递给Servlet容器(如Tomcat)
  3. Servlet容器加载相应的Servlet,如果尚未加载
  4. Servlet容器创建两个对象:HttpServletRequest和HttpServletResponse
  5. 调用Servlet的service()方法(或者对应的doGet、doPost等方法)
  6. Servlet处理请求并将结果写入到HttpServletResponse中
  7. Servlet容器将响应返回给客户端

Servlet生命周期

Servlet的生命周期包含以下阶段:

  1. 加载和实例化:Servlet容器加载Servlet类并创建实例
  2. 初始化:调用init()方法,完成初始化工作
  3. 服务:调用service()方法处理客户端请求
  4. 销毁:调用destroy()方法释放资源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class HelloServlet extends HttpServlet {

@Override
public void init() throws ServletException {
System.out.println("Servlet正在初始化");
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h2>Hello Servlet!</h2>");
out.println("<p>当前时间: " + new Date() + "</p>");
out.println("</body></html>");
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

@Override
public void destroy() {
System.out.println("Servlet正在销毁");
}
}

Servlet配置

使用web.xml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.HelloServlet</servlet-class>
<init-param>
<param-name>author</param-name>
<param-value>John Doe</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>

使用注解配置(Servlet 3.0+)

1
2
3
4
5
6
@WebServlet(name = "HelloServlet", 
urlPatterns = {"/hello"},
initParams = {@WebInitParam(name = "author", value = "John Doe")})
public class HelloServlet extends HttpServlet {
// Servlet实现
}

请求和响应对象

HttpServletRequest

HttpServletRequest接口提供了访问HTTP请求信息的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 获取请求参数
String username = request.getParameter("username");

// 获取多值参数
String[] hobbies = request.getParameterValues("hobby");

// 获取请求头
String userAgent = request.getHeader("User-Agent");

// 获取cookie
Cookie[] cookies = request.getCookies();

// 获取会话
HttpSession session = request.getSession();

// 设置请求属性
request.setAttribute("user", userObj);

// 获取请求属性
User user = (User) request.getAttribute("user");

// 请求转发
RequestDispatcher dispatcher = request.getRequestDispatcher("/another-servlet");
dispatcher.forward(request, response);

HttpServletResponse

HttpServletResponse接口提供了向客户端发送响应的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 设置响应类型和字符集
response.setContentType("text/html;charset=UTF-8");

// 获取输出流
PrintWriter out = response.getWriter();
out.println("<h1>Hello World!</h1>");

// 设置状态码
response.setStatus(HttpServletResponse.SC_OK);

// 设置响应头
response.setHeader("Cache-Control", "no-cache");

// 添加cookie
Cookie cookie = new Cookie("username", "john");
cookie.setMaxAge(3600); // 1小时
response.addCookie(cookie);

// 重定向
response.sendRedirect("/another-page.jsp");

Servlet过滤器(Filter)

过滤器可以在请求到达Servlet之前或响应返回客户端之前执行预处理或后处理任务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@WebFilter("/admin/*")
public class AuthenticationFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代码
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;

HttpSession session = httpRequest.getSession(false);
boolean isLoggedIn = (session != null && session.getAttribute("user") != null);

if (isLoggedIn) {
// 用户已登录,继续处理请求
chain.doFilter(request, response);
} else {
// 用户未登录,重定向到登录页面
httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");
}
}

@Override
public void destroy() {
// 销毁代码
}
}

Servlet监听器(Listener)

监听器用于监听Servlet容器中的各种事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@WebListener
public class AppContextListener implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
context.setAttribute("startTime", System.currentTimeMillis());
System.out.println("应用程序已启动");
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("应用程序正在关闭");
}
}

Servlet会话管理

HttpSession接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 获取会话
HttpSession session = request.getSession();
// 或者如果不存在,则不创建新会话
// HttpSession session = request.getSession(false);

// 设置会话属性
session.setAttribute("user", userObj);

// 获取会话属性
User user = (User) session.getAttribute("user");

// 移除会话属性
session.removeAttribute("user");

// 使会话无效(登出)
session.invalidate();

// 设置会话超时时间(秒)
session.setMaxInactiveInterval(1800);

总结

Servlet是Java Web开发的基础,虽然现在有许多高级框架如Spring MVC可以简化Web开发,但是理解Servlet的工作原理对于掌握Java Web开发仍然非常重要。掌握Servlet的生命周期、配置方式、请求响应处理以及会话管理等核心概念,是成为一名合格的Java Web开发人员的必备知识。