1. 过滤器(Filter)
1.1 介绍
Filter即为过滤,用于在Servlet之外对request和response进行修改。
主要用于对用户请求进行预处理,或者对HttpServletResponse进行后处理。
使用Filter的流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后再对服务器响应进行后处理。多个Filter合起来称之为一个Filter链。
若是一个过滤器链,则请求时先配置先执行,响应时以相反的顺序执行。
1.2 实现
- 编写java类实现Filter接口,并实现其doFilter方法;doFilter方法中需要设置放行,否则请求无法到达资源(
filterChain.doFilter(servletRequest,servletResponse)
) - 通过@WebFilter注解设置其所能拦截的资源。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.xml.crypto.dsig.spec.XPathType;
import java.io.IOException;
@WebFilter("/*")
//@WebFilter("/s01")
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() {
//System.out.println("filter01 destroy...");
}
}
乱码问题:(Tomcat8及以上版本GET请求不会出现乱码,不需要处理)
GET请求:
new String(request.getParameter("参数名").getBytes(StandardCharsets.UTF_8));
POST请求:
request.setCharacterEncoding("UTF-8");
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.nio.charset.StandardCharsets;
@WebFilter("/s01")
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 拦截请求...");
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 versionStr=serverInfo.substring(serverInfo.indexOf("/")+1,serverInfo.indexOf("."));
if(Integer.parseInt(versionStr)<8){
HttpServletRequest myRequest=new MyWapper(request);
filterChain.doFilter(myRequest,response);
return;
}
}
filterChain.doFilter(servletRequest,servletResponse);//放行资源
//放行后做响应拦截
System.out.println("filter02 处理响应...");
}
@Override
public void destroy() {
System.out.println("filter02 destroy...");
}
}
class MyWapper extends HttpServletRequestWrapper {
//定义成员变量,提升构造器中request对象的范围
private HttpServletRequest request;
public MyWapper(HttpServletRequest request){
super(request);
this.request=request;
}
/**
* 重写getParamter()方法
*/
@Override
public String getParameter(String name) {
String value=request.getParameter(name);
if(value!=null||"".equals(value.trim())){
value=new String(value.getBytes(StandardCharsets.UTF_8));
}
return value;
}
}
1.3 用户非法访问拦截实例
login.jsp(登录页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login.jsp</title>
</head>
<body>
<h2>欢迎</h2>
<from action="login" id="loginForm">
<ul>
<li>姓名:<input type="text" id="uname" name="uname"/></li>
<li>密码:<input type="password" id="upd" name="upd"/></li>
<button type="button" id="sub" onclick="login()">登录</button>
<button type="reset" id="reset">重置</button>
</ul>
</from>
<script src="js/user.js" type="text/javascript"></script>
</body>
</html>
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>index</title>
</head>
<body>
<h2>欢迎${uname}登录</h2>
</body>
</html>
user.js(外部js校验)
function login(){
//判断不为空则提交
var uname=document.getElementById("uname").value;
if(uname!=null&&uname.trim()!=""){
document.getElementById("loginForm").onsubmit;
}
}
LoginAccessFilter.java(过滤器)
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 非法访问拦截
* 拦截所有资源 /*
* 需要放行的资源
* 放行指定页面(无需登录即可访问的页面,如登录注册等)
* 放行静态资源(img、js、css等)
* 放行指定操作(无需登录即可进行的操作,如登录操作)
* 登录状态放行(判断session中用户信息是否为空)
*/
@WebFilter("/*")
public class LoginAccessFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//基于HTTP请求
HttpServletRequest request=(HttpServletRequest) servletRequest;
HttpServletResponse response=(HttpServletResponse) servletResponse;
//获取请求的路径
String url=request.getRequestURI();
//放行指定页面
if(url.contains("/login.jsp")){
filterChain.doFilter(request,response);
return;
}
//放行静态资源
if(url.contains("/js")||url.contains("/img")||url.contains("/css")){
filterChain.doFilter(request,response);
return;
}
//放行指定操作
if(url.contains("/login")){
filterChain.doFilter(request,response);
return;
}
//登录状态放行(判断session中用户信息是否为空)
String uname=(String)request.getSession().getAttribute("user");
if(uname!=null)
{
filterChain.doFilter(request,response);
return;
}
response.sendRedirect("login.jsp");
//用户未登录时,拦截请求跳转到登录页面
}
}
LoginServlet.java
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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("用户登录...");
String uname=req.getParameter("uname");
System.out.println(uname);
if("admin".equals(uname)){
req.getSession().setAttribute("user",uname);
//跳转到首页
resp.sendRedirect("index.jsp");
}else{
req.getRequestDispatcher("login.jsp").forward(req,resp);
}
}
}
2. 监听器
2.1 介绍
Web监听器是Servlet中一种特殊的类,能够监听web中的特定事件,比如ServletContext、HttpSession、ServletRequest的创建和销毁;变量的创建、销毁、修改等。
2.2 实现
监听器有三类8种:
- 监听生命周期:
ServletRequestListener
HttpSessionListener
ServletContextListener - 监听值变化:
ServletRequestAttributeListener
HttpServletAttributeListener
ServletContextAttributeListener - 针对session中的对象:
监听session中的java对象(JavaBean),是JavaBean直接实现监听器的接口
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class Listener01 implements HttpSessionListener {
//session被创建时执行,服务器自动调用,
//(有Servlet创建session时:HttpSession session=req.getSession();)
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("session is created...");
}
//session被销毁时执行,服务器自动调用
//(有Servlet销毁session时:req.getSession().invalidate();)
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session is destroyed...");
}
}
2.3 在线人数统计实例
OnlineListener.java
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* 在线人数统计:
* 初始化为0
* 当有session创建时+1
* 当有session销毁时-1
*/
@WebListener
public class OnlineListener implements HttpSessionListener {
private Integer onlineNum=0;
@Override
public void sessionCreated(HttpSessionEvent se) {
onlineNum++;
se.getSession().getServletContext().setAttribute("onlineNumber",onlineNum);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
onlineNum--;
se.getSession().getServletContext().setAttribute("onlineNumber",onlineNum);
}
}
OnlineServlet.java
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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/online")
public class OnlineServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session=req.getSession();
String key=req.getParameter("key");
if("logout".equals(key)){
session.invalidate();
return;
}
/*进入登录操作*/
Integer onlineN=(Integer) session.getServletContext().getAttribute("onlineNumber");
//System.out.println(onlineN);
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("<h2>当前在线人数:"+onlineN+"</h2><a href='online?key=logout'>退出</a>");
}
}