Java Web07:MVC、过滤器和监听器
MVC三层架构
Servlet和JSP都可以写Java代码,但为了易于维护和使用:Servlet专注于处理请求,以及控制视图跳转;JSP专注于显示数据
Model:
- 业务处理层(Service)
- 数据持久层(Dao)
View:
- 展示数据
- 提供链接,发起Servlet请求
Controller:
- 接受用户请求
- 交给业务层处理
- 控制视图跳转
过滤器
实现Filter接口,重写三个方法
实现过程和Servlet类似
案例一:统一设置编码
请求
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class test extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
res.getWriter().println("你好,世界");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
过滤器
import javax.servlet.*;
import java.io.IOException;
public class CharacterFilter implements Filter {
/**
* Web服务器启动时就会初始化
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
/**
* 在过滤器中统一处理乱码
*/
response.setContentType("text/html;charset=utf-8");
System.out.println("过滤器执行前");
/**
* 过滤器链
* 1、过滤器中所有代码,在过滤特定请求时都会执行
* 2、必须要执行chain对象的doFilter()方法,才能让过滤后的请求继续往下执行
*/
chain.doFilter(request, response);
System.out.println("过滤器执行后");
}
/**
* Web服务器停止时被销毁
*/
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
}
配置web.xml
<!--对指定目录下的请求进行过滤-->
<!--只有/filter/test会被过滤,而/test不会被过滤-->
<filter>
<filter-name>CharacterFilter</filter-name>
<filter-class>CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterFilter</filter-name>
<url-pattern>/filter/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>filterTest</servlet-name>
<servlet-class>test</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>filterTest</servlet-name>
<url-pattern>/filter/test</url-pattern>
</servlet-mapping>
案例二:登录才能访问
登录页面
<%--设置浏览器页面编码格式--%>
<%@page contentType="text/html; charset=utf-8"%>
<html>
<body>
<form action="./login" method="post">
<p>用户名:<input type="text" name="username"></p>
<p>密码:<input type="password" name="password"></p>
<p><input type="submit"></p>
</form>
</body>
</html>
登录请求
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Login extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
if (username.equals("admin")){
/**
* 如果用户名是admin,则记录Session的ID,跳转到登录成功的页面
*/
req.getSession().setAttribute("USER_SESSION", req.getSession().getId());
resp.sendRedirect("./login_success.jsp");
}
else {
/**
* 登陆失败跳转到500
*/
resp.sendRedirect("./error/error500.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
登录成功页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆成功</title>
</head>
<body>
<h1>登陆成功!</h1>
<%--登陆成功以后,可以注销,注销以后必须要再次登录才能访问--%>
<p><a href="./logout">注销</a></p>
</body>
</html>
注销请求
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Logout extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session = req.getSession().getAttribute("USER_SESSION");
/**
* 注销后返回登录页面
*/
if (user_session != null){
req.getSession().removeAttribute("USER_SESSION");
}
resp.sendRedirect("./login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
权限过滤
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AuthorityFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
/**
* 转换Filter接口中方法参数的类型
*/
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
/**
* 权限验证
* 如果注销以后,再访问login_success.jsp页面会报错
*/
if (req.getSession().getAttribute("USER_SESSION") == null){
resp.sendRedirect("./error/error404.jsp");
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
配置Web.xml
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>Login</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Logout</servlet-name>
<servlet-class>Logout</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Logout</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<filter>
<filter-name>AuthorityFilter</filter-name>
<filter-class>AuthorityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthorityFilter</filter-name>
<url-pattern>/login_success.jsp</url-pattern>
</filter-mapping>
监听器
实现监听器接口,不同对象接口不一样,如监听Session的接口是HttpSessionListener
重写两个方法
监听器
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class Listener implements HttpSessionListener {
/**
* 创建Session监听
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
/**
* 获取OnlineCount属性
*/
ServletContext servletContext = se.getSession().getServletContext();
/**
* 创建时输出当前Session的ID
*/
System.out.println(se.getSession().getId());
Integer num = (Integer) servletContext.getAttribute("OnlineNum");
if (num == null){
num = new Integer(1);
}
else {
int count = num.intValue();
num = new Integer(count + 1);
}
servletContext.setAttribute("OnlineNum", num);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext servletContext = se.getSession().getServletContext();
/**
* 销毁时输出当前Session的ID
*/
System.out.println(se.getSession().getId());
Integer num = (Integer) servletContext.getAttribute("OnlineNum");
if (num == null){
num = new Integer(0);
}
else {
int count = num.intValue();
num = new Integer(count - 1);
}
servletContext.setAttribute("OnlineNum", num);
}
}
JSP页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>当前在线人数为 <span style="color: red"><%=application.getAttribute("OnlineNum")%></span></h1>
</body>
</html>
配置web.xml
<!--注册监听器-->
<listener>
<listener-class>Listener</listener-class>
</listener>
<!--销毁监听器-->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南