【Java Web】Servlet
文章目录
- Servlet API
- Servlet生命周期
- Servlet配置
- 注解
- 配置文件
- 全局参数
- Servlet获得内置对象
- 升级示例3
Servlet 是一种用于构建 Java 服务器端应用程序的技术,允许开发者创建动态的 web 内容。Servlets 在 Java 平台上运行,并由 Java Servlet API 提供支持,该 API 是 Java EE(现在称为 Jakarta EE)的一部分。Servlet 的主要功能是处理客户端请求并发送响应给客户端。
主要特点
- 请求和响应处理:Servlet 可以接收来自客户端(通常是浏览器)的请求,并通过
HttpServletRequest
对象获取请求信息。生成响应时,Servlet 使用HttpServletResponse
对象,可以向客户端返回 HTML、JSON、XML 等格式的数据。 - 生命周期:Servlet 的生命周期由服务器控制,主要包括加载、初始化、处理请求、销毁四个阶段。初始化时,Servlet 会调用
init()
方法;处理请求时,调用service()
方法;销毁时,调用destroy()
方法。 - 多线程支持:Servlet 能够处理多个请求,通常在多线程环境下运行。每个请求会在独立的线程中处理,这样可以提高并发处理能力。
- 跨平台:由于基于 Java,Servlet 可以在任何支持 Java 的服务器上运行,实现了良好的跨平台能力。
- 集成与扩展:Servlet 可以与 JSP(JavaServer Pages)、过滤器、监听器等技术结合使用,以实现更复杂的 web 应用。
创建 Servlet 有三种常见的方式:
- 实现
javax.servlet.Servlet
接口 - 继承
javax.servlet.GenericServlet
类 - 继承
javax.servlet.http.HttpServlet
类
Servlet API
javax.servlet.Servlet核心接口
- 定义了
init()
,service()
, 和destroy()
方法,这些方法分别对应于 Servlet 的初始化、服务处理和销毁阶段。
init() // Servlet的初始化方法,仅仅会执行一次
service() // 处理请求和生成响应
destroy() // 在服务器停止并且程序中的 Servlet 对象不再使用的时候调用,只执行一次
javax.servlet.GenericServlet抽象类:
- 实现了
Servlet
接口,并提供了一些默认实现。提供了对init(ServletConfig config)
和getServletConfig()
方法的支持。 - 通常不直接使用,而是作为更具体的
HttpServlet
类的基础。
javax.servlet.http.HttpServlet类:
- 继承自
GenericServlet
,专门为 HTTP 协议设计。提供了doGet()
,doPost()
,doPut()
,doDelete()
等方法来处理不同的 HTTP 请求类型。 - 开发者通常继承这个类来创建自己的 Servlet
// 处理 GET 请求
doGet(HttpServletRequest req, HttpServletResponse res)
// 处理 POST 请求
doPost(HttpServletRequest req, HttpServletResponse res)
javax.servlet.ServletRequest接口
- 表示客户端请求的对象,包含有关请求的信息。
HttpServletRequest
是ServletRequest
的子接口,专为 HTTP 请求提供额外的方法,如获取查询参数、请求头等信息。
// 获取请求参数
getParameter(String name)
// 获取请求头信息
getHeader(String name)
// 获取请求的方法类型(GET, POST等)
getMethod()
// 获取请求的 URI
getRequestURI()
javax.servlet.ServletResponse接口
- 表示服务器响应的对象,用于构建和发送响应到客户端。
HttpServletResponse
是ServletResponse
的子接口,提供了发送状态码、设置响应头、写入响应体等与 HTTP 相关的方法。
// 设置响应内容的类型(如 text/html)
setContentType(String type)
// 获取用于发送字符数据的输出流
getWriter()
// 重定向到指定的 URL
sendRedirect(String location)
ServletConfig
- 代表 Servlet 的配置信息。可以通过它从 web.xml 文件获取初始化参数以及 ServletContext 对象。
// 获取初始化参数
getInitParameter(String name)
// 获取 Servlet 上下文
getServletContext()
Servlet生命周期
生命周期 | 谁来做 | 何时做 |
---|---|---|
实例化 | Servlet 容器 | 当Servlet容器启动或者容器检测到客户端请求时 |
初始化 | Servlet 容器 | 实例化后,容器调用Servlet的init()初始化对象 |
处理请求 | Servlet 容器 | 得到客户端请求并做出处理时 |
销毁 | Servlet 容器 | 当程序中的Servlet对象不再使用的时候,或者Web服务器停止运行的时候 |
执行顺序
- MyServlet():构造方法 实例化
- init():初始化方法
- service():req.getMethod() 判断请求类型是 get || post
- 加载 get || post
- destroy():销毁方法
Servlet配置
注解
@WebServlet
注解用于将一个 Servlet 类与一个或多个 URL 模式进行映射,并且可以配置一些初始化参数。
// 单个 URL 映射
@WebServlet("/user/login")
// 多个 URL 映射
@WebServlet({"/user/login", "/user/signin"})
// 高级设置 设置 Servlet 名称和启动加载顺序
@WebServlet(name = "loginServlet", value = "/user/login", loadOnStartup = 1)
name
属性指定了 Servlet 的名称,可以用于在web.xml
中引用。value
属性指定了 Servlet 的 URL 映射。loadOnStartup
属性指定了 Servlet 的启动加载顺序。值为 1 表示在应用启动时立即加载该 Servlet。值越大,加载顺序越靠后。
还可以使用 @WebInitParam
注解来设置初始化参数
@WebServlet(name = "loginServlet",
value = "/user/login",
loadOnStartup = 1,
initParams = {
@WebInitParam(name = "maxAge", value = "3600"),
@WebInitParam(name = "allowedMethods", value = "GET,POST")
})
配置文件
在web.xml
文件中配置 Servlet 元素及其初始化参数
1. 配置 Servlet 元素
在web.xml
中定义 Servlet 本身。通过<servlet>
标签及其子标签来完成。
<servlet>
<!-- Servlet的名称,可自定义,用于在web.xml内部标识该Servlet -->
<servlet-name>indexServlet</servlet-name>
<!-- Servlet的完整类名,包括包名 -->
<servlet-class>com.example.IndexServlet</servlet-class>
</servlet>
2. 配置 Servlet 映射
配置完 Servlet 后将其与特定的 URL 模式进行映射,以便当客户端请求特定的 URL 时,Web 容器能知道应该调用哪个 Servlet 来处理请求。通过<servlet-mapping>
标签来完成。
<servlet-mapping>
<!-- 这里的servlet-name要和前面定义Servlet时设置的名称一致 -->
<servlet-name>indexServlet</servlet-name>
<!-- 定义该Servlet处理的URL模式,可以是精确匹配的具体URL,也可以是通配符模式 -->
<url-pattern>/user/index</url-pattern>
</servlet-mapping>
3. 配置 Servlet 初始化参数
为 Servlet 配置初始化参数。在<servlet>
标签内添加<init-param>
子标签来实现。
<servlet>
<servlet-name>indexServlet</servlet-name>
<servlet-class>com.example.IndexServlet</servlet-class>
<!-- 开始配置初始化参数 -->
<init-param>
<!-- 参数名称,可自定义 -->
<param-name>charSetContent</param-name>
<!-- 参数值,根据实际需求设置 -->
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>anotherParamKey</param-name>
<param-value>anotherParamValue</param-value>
</init-param>
<!-- 结束配置初始化参数 -->
<!-- 指定 Servlet 的加载顺序 越小越靠前 -->
<load-on-startup>1</load-on-startup>
</servlet>
4. 获取初始化参数
假设上述配置的MyServletClass
继承自HttpServlet
(通常处理 HTTP 请求的 Servlet 会这么做),在MyServletClass
的init()
方法中可以这样获取初始化参数
public class IndexServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
// 获取名为charSetContent的初始化参数值
String initParam = config.getInitParameter("charSetContent");
System.out.println("charSetContent的值为: " + initParam);
// 获取名为anotherParamKey的初始化参数值
String anotherParamKeyValue = config.getInitParameter("anotherParamKey");
System.out.println("anotherParamKey的值为: " + anotherParamKeyValue);
}
}
在浏览器 URL 地址栏输入 http://localhost:8888/user/index
(具体端口号看自己 Tomcat 设置)
全局参数
<context-param>
元素定义上下文参数,这些参数在整个 Web 应用程序中都可用。
可以在 Servlet 中通过 ServletContext
对象来访问全局参数。
<!-- 定义上下文参数 -->
<context-param>
<param-name>charSetContent</param-name>
<param-value>utf-8</param-value>
</context-param>
<!-- 配置 Servlet -->
<servlet>
...
</servlet>
<!-- 映射 Servlet 到 URL -->
<servlet-mapping>
...
</servlet-mapping>
@Override
public void init(ServletConfig config) throws ServletException {
// super.init(config);
// 获取 ServletContext 对象
ServletContext context = config.getServletContext();
// 获取上下文参数
String charSetContent = context.getInitParameter("charSetContent");
System.out.println("Character Set Content: " + charSetContent);
}
Servlet获得内置对象
1、获取 PageContext
对象
JspFactory jspFactory = JspFactory.getDefaultFactory();
PageContext pageContext = jspFactory.getPageContext(this, request, response, null, true, 8192, true);
// 使用 PageContext 对象
pageContext.getOut().print("<h1 style='color:red'>这是doGET</h1>");
// 释放 PageContext 对象
pageContext.forward("/index.jsp"); // 或者 pageContext.include("/index.jsp");
pageContext.release();
2、获取 out
对象
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.print("<h1 style='color:red'>这是doGET</h1>");
3、获取 session
对象
HttpSession session = request.getSession();
session.setAttribute("username", "liming");
response.getWriter().println("Session ID: " + session.getId());
4、获取 application
对象
ServletContext context = this.getServletContext();
context.setAttribute("appAttribute", "Application Value");
response.getWriter().println("Application Context: " + context.getRealPath("/"));
升级示例3
将 doxxx.jsp
中的逻辑处理步骤移动到 Servlet 中处理。
首先,在 web.xml
文件中设置全局参数
<!-- 定义上下文参数 -->
<context-param>
<param-name>charSetContent</param-name>
<param-value>utf-8</param-value>
</context-param>
在 Servlet 中获取并使用 charSetContent 参数
@WebServlet("/user/login")
public class UserLoginServlet extends HttpServlet {
String charSetContent = "";
@Override
public void init(ServletConfig config) throws ServletException {
// 获取 ServletContext 对象 获取上下文参数
charSetContent = config.getServletContext().getInitParameter("charSetContent");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding(charSetContent);
HttpSession session = request.getSession();
// 接收参数
String uname = request.getParameter("uname");
String upwd = request.getParameter("upwd");
boolean jzpwd = "on".equals(request.getParameter("jzpwd"));
// 调用 Java 方法 登录
SmbmsUserDao smbmsUserDao = new SmbmsUserDaoImpl();
SmbmsUser smbmsUser = smbmsUserDao.login(uname,upwd);
// 判断登录是否成功
if (smbmsUser != null) {
// session 存储登录信息
session.setAttribute("smbmsUser",smbmsUser);
Cookie cookieUname = null;
Cookie cookieUpwd = null;
Cookie cookieJzpwd = null;
// 如果用户选择了“记住密码”,则将保存到 Cookie 中
if (jzpwd) {
cookieUname = new Cookie("uname", URLEncoder.encode(uname, "UTF-8"));
cookieUpwd = new Cookie("upwd", upwd);
cookieJzpwd = new Cookie("jzpwd", "on");
// 设置 Cookie 的有效期为 2 小时
setCookie(response,cookieUname,60 * 60 * 2);
setCookie(response,cookieUpwd,60 * 60 * 2);
setCookie(response,cookieJzpwd,60 * 60 * 2);
} else {
// 如果用户没有选择“记住密码”,则删除相关的 Cookie
cookieUname = new Cookie("uname", "");
cookieUpwd = new Cookie("upwd", "");
cookieJzpwd = new Cookie("jzpwd", "");
setCookie(response,cookieUname,0);
setCookie(response,cookieUpwd,0);
setCookie(response,cookieJzpwd,0);
}
// 转发
request.getRequestDispatcher("/index").forward(request,response);
// 重定向
// response.sendRedirect("/doindex.jsp");
} else {
// 登录失败则重定向回登录界面
response.sendRedirect("/login.jsp");
}
}
private void setCookie(HttpServletResponse response,Cookie cookie, int maxAge) {
// 设置 Cookie 的有效期
cookie.setMaxAge(maxAge);
// 设置 Cookie 的路径为根路径
cookie.setPath("/");
// 将 Cookie 添加到响应中
response.addCookie(cookie);
}
}
对应 doindex.jsp
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 调用 Java 方法 获取供应商列表信息
SmbmsProviderDao smbmsProviderDao = new SmbmsProviderDaoImpl();
List<SmbmsProvider> providerList = smbmsProviderDao.findAll();
// setAttribute 存储供应商信息
request.setAttribute("providerList",providerList);
// 转发
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
对应 logout.jsp
@WebServlet("/user/logout")
public class UserLogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
// 清除所有 session
session.invalidate();
// 重定向回首页
response.sendRedirect("/login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}