过滤器
-
Filter即过滤,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理;
-
使用Filter的完整流程,Filter
对用户请求进行预处理
,接着将请求交给Servlet进行处理并生成响应,最后Fliter再对服务器响应进行后处理
,在一个web应用中,可以开发编写多个Filter,这些Fliter组合起来称之为一个Fliter链; -
Filter通过
java.servlet.Filter
的接口来实现,主要步骤如下所示:- 首先创建Java类,实现Filter接口;
- 然后通过
@WebFilter注解
,设置它所能拦截的资源;
-
案例代码,创建
Servlet01
,Servlet02
,Filter01
,Filter02
,代码如下: -
Servlet01
文件
package com.sf.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/servlet01")
public class Servlet01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet01...");
}
}
-
Servlet02
文件
package com.sf.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/servlet02")
public class Servlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet02...");
}
}
-
Filter01
文件
package com.sf.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//通过注解指定拦截servlet01资源
@WebFilter("/servlet01")
//拦截所有的资源
//@WebFilter("/*")
public class Filter01 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter01 init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter01 正在拦截...");
//放行资源
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Filter01 正在处理响应...");
}
@Override
public void destroy() {
}
}
-
Filter02
文件
package com.sf.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//通过注解指定拦截servlet01资源
@WebFilter("/servlet01")
public class Filter02 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter02 init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter02 正在拦截...");
//放行资源
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("Filter02 正在处理响应...");
}
@Override
public void destroy() {
}
}
- Filter01与Filter02都拦截了Servlet01,结果如下所示:
- Filter拦截请求的顺序与拦截响应的顺序是相反的;
-
@WebFilter("/*")
可拦截所有的资源; -
filterChain.doFilter()
是放行资源,如果不放行则会出现资源拦截,无法执行servlet的service方法;
请求乱码的处理
- 在 Servlet 文章中关于请求乱码的情况有详细的阐述,下面我们来实现拦截所有请求,进行请求乱码的统一处理;
- 创建
AEncodingFilter
过滤器,代码入下:
package com.sf.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@WebFilter("/")
public class AEncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("AEncodingFilter...");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//基于HTTP
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
//处理POST请求的乱码问题
request.setCharacterEncoding("UTF-8");
//处理GET请求的乱码问题
String method = request.getMethod();
if ("GET".equalsIgnoreCase(method)) {
//获取服务器信息
String serverInfo = request.getServletContext().getServerInfo();
//获取具体版本号
String version = serverInfo.substring(serverInfo.indexOf("/")+1,serverInfo.indexOf("."));
if (Integer.parseInt(version) < 8) {
//自定义内部类MyWapper 重写getParameter方法
HttpServletRequest myRequest = new MyWapper(request);
filterChain.doFilter(myRequest,response);
return;
}
}
//放行资源
filterChain.doFilter(request,response);
}
@Override
public void destroy() {
}
class MyWapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
public MyWapper(HttpServletRequest request) {
super(request);
this.request = request;
}
/**
* 重写getParameter方法
* @param name
* @return
*/
@Override
public String getParameter(String name) {
String value = request.getParameter(name);
if (value != null && !"".equals(value)) {
try {
value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return value;
}
}
}
用户非法访问拦截
- 下面实现当用户在未登录的情况下,不能访问需要登录的页面,也就是说用户在访问资源时,进行资源拦截,
- 无需登录的页面,放行页面;
- 放行静态资源;
- 放行指定操作 无需登录就可执行的操作 登录操作,注册操作;
- 登录状态 需要放行 判断session信息;
- 当用户未登录时,拦截请求跳转到登录页面;
- 创建过滤器
LoginAccessFilter
文件,代码如下:
package com.sf.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/*")
public class LoginAccessFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LoginAccessFilter init");
}
//只要是 资源 路径 请求 操作 都会被拦截
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("LoginAccessFilter doFilter...");
//当用户未登录时,拦截请求跳转到登录页
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//放行资源
//1.放行指定页面 无需登录的页面
String url = request.getRequestURI();
if (url.contains("/login.jsp")) {
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//2.放行静态资源
if (url.contains("/js") || url.contains("/image") || url.contains("css")) {
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//3.放行指定操作 无需登录就可执行的操作 登录操作,注册操作
if (url.contains("/login")) {
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//4.登录状态 需要放行 判断session信息
String name = (String) request.getSession().getAttribute("name");
if (name != null) {
filterChain.doFilter(servletRequest,servletResponse);
return;
}
//当用户未登录时,拦截请求跳转到登录页面
response.sendRedirect("login.jsp");
}
@Override
public void destroy() {
}
}
- 创建登录逻辑处理文件
LoginServlet
,代码如下:
package com.sf.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LoginServlet...");
String name = req.getParameter("name");
if ("admin".equals(name)) {
req.getSession().setAttribute("name",name);
resp.sendRedirect("index.jsp");
} else {
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
}
- 创建前台登录页面
login.jsp
文件;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<form action="login" id="loginForm">
姓名: <input type="text" name="name" id="name">
<button type="button" onclick="login()">登录</button>
</form>
<script src="js/user.js" type="text/javascript">
</script>
</body>
</html>
- 创建进行登录的js文件
user.js
;
function login() {
var name = document.getElementById("name").value;
if (name != null && name.trim() != "") {
document.getElementById("loginForm").submit();
}
}
- 创建登录成功的首页文件
index.jsp
;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h2>欢迎${name}登录!!!</h2>
</body>
</html>
监听器
- web监听器是Servlet中一种特殊的类,能帮助开发者监听web中的特定事件,例如ServletContext,HttpSession,ServletRequest的创建与销毁,变量的创建,销毁和修改等等,可以在某些动作前后增加处理,实现监控;
- 监听器分为三类8种;
- 监听生命周期:ServletRequestListener,HttpSessionListener,ServletContextListener;
- 监听值的变化:ServletRequestAttributeListener,HttpSessionAttributeListener,ServletContextAttributeListener;
- 监听session中Java对象;
- 案例代码:创建Java类
Listener01
package com.sf.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class Listener01 implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("Session对象 被创建");
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("Session对象 被销毁");
}
}
监听器 -- 在线人数统计
- 创建监听器类
OnLineListener
,代码如下:
package com.sf.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnLineListener implements HttpSessionListener {
//统计在线人数
private Integer onlineNumber;
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
onlineNumber++;
//将人数存入session作用域中
httpSessionEvent.getSession().setAttribute("onlineNumber",onlineNumber);
//将人数存入application作用域中
httpSessionEvent.getSession().getServletContext().setAttribute("onlineNumber",onlineNumber);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
onlineNumber--;
//将人数存入session作用域中
httpSessionEvent.getSession().setAttribute("onlineNumber",onlineNumber);
//将人数存入application作用域中
httpSessionEvent.getSession().getServletContext().setAttribute("onlineNumber",onlineNumber);
}
}
- 创建Servlet类
OnlineServlet
,代码如下:
package com.sf.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebFilter("/onlineServlet")
public class OnlineServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建session对象
HttpSession session = req.getSession();
String key = req.getParameter("key");
if (key != null && "logout".equals(key)) {
session.invalidate();
return;
}
//获取当前人数
Integer onlineNumber = (Integer) session.getServletContext().getAttribute("onlineNumber");
resp.setContentType("text/html;charset=UTF-8");
//返回给客户端
resp.getWriter().write("<h2>当前在线人数: "+onlineNumber+"</h2> <a href='online?key=logout'>退出</a>");
}
}
网友评论