一、JSP过滤器概念
JSP 和 Servlet 中的过滤器都是 Java 类。
过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。
可以将一个或多个过滤器附加到一个 Servlet 或一组 Servlet。过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。
过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:
- 在客户端的请求访问后端资源之前,拦截这些请求。
- 在服务器的响应发送回客户端之前,处理这些响应。
https://www.runoob.com/jsp/jsp-writing-filters.html
二、Servlet 过滤器方法
1.过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。
- javax.servlet.Filter 接口定义了三个方法:
序号 | 方法 & 描述 |
---|---|
1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) 该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet 容器将先调用过滤器的 doFilter 方法。FilterChain 用于访问后续过滤器。 |
2 | public void init(FilterConfig filterConfig) web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。 |
3 | public void destroy() Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。 |
三、使用过滤器处理中文乱码
1.配置
- 在web.xml中配置过滤器信息
- 编写自定义类EncodeFilter
<!--在web.xml中配置过滤器信息-->
<web-app>
<filter>
<filter-name>EncodeFilter</filter-name>
<filter-class>cn.jbit.demo.web.EncodeFilter</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
//编写自定义类EncodeFilter
public class EncodeFilter implements Filter {
private String encode = null;
/* 在 Filter 实例被 Web 容器从服务移除之前调用 */
public void destroy() {encode = null;}
// 对所有页面设置字符集编码
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws Exception {
if (null == request.getCharacterEncoding()) {
request.setCharacterEncoding(this.encode);
Response.setCharacterEncoding(this.encoding);
}
// 把请求传回过滤链
chain.doFilter(request, response);//放行
}
public void init(FilterConfig filterConfig) throws ServletException {
// 获取web.xml初始化参数
String encode = filterConfig.getInitParameter("encode");
if (this.encode == null) {
this.encode = encode; // 查找配置文件中欲设的字符集编码
}
}
}
四、使用过滤器处理身份验证
<!--在web.xml中配置过滤器信息-->
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>cn.gwj.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
package cn.gwj.filter;
/*
Created by IntelliJ IDEA.
Package:cn.gwj.fillter
User:1093499975@qq.com
Date:2019/7/4 0004
Time:14:10
*/
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
//实现 Filter 类
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
HttpServletResponse httpServletResponse=(HttpServletResponse)servletResponse;
if(Objects.nonNull(httpServletRequest.getSession().getAttribute("user"))){
filterChain.doFilter(servletRequest,servletResponse);
}else {
httpServletResponse.sendRedirect(httpServletRequest.getContextPath()+"/view/login.jsp");
}
}
@Override
public void destroy() {}
}
-
在controller包中的登录控制文件中编写
package cn.gwj.controller;
/*
Created by IntelliJ IDEA.
Package:cn.gwj.controller
User:1093499975@qq.com
Date:2019/7/4 0004
Time:09:18
*/
import cn.gwj.entity.User;
import cn.gwj.service.impl.UserServiceImpl;
import com.alibaba.fastjson.JSONArray;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@WebServlet("/admin/LoginServlet.html")
public class LoginServlet extends BaseController {
public void login(HttpServletRequest request, HttpServletResponse response){
String uName=request.getParameter("uName");
String uPwd=request.getParameter("uPwd");
User user=new User();
user.setuName(uName);
user.setuPwd(uPwd);
user=new UserServiceImpl().getUser(user);
Map msgMap=new HashMap();
if(user.getId()>0 && user.getuPwd().equals(uPwd)){//用户存在且密码正确
request.getSession().setAttribute("user",user);//登陆成功设置session
msgMap.put("msg","登录成功");
msgMap.put("status","true");
msgMap.put("user",user.getuName());
if(Objects.isNull(getServletContext().getAttribute("loginCount"))){
getServletContext().setAttribute("loginCount",1);
}else{
Integer count=(Integer)getServletContext().getAttribute("loginCount");
getServletContext().setAttribute("loginCount",count+1);
}
}else {
msgMap.put("msg","登录失败,用户名或密码错误!");
msgMap.put("status",false);
}
PrintWriter pw= null;
try {
pw = response.getWriter();
} catch (IOException e) {
e.printStackTrace();
}
pw.println(JSONArray.toJSON(msgMap));
}
/**
* 注销
* @param request
* @param response
*/
public void loginOut(HttpServletRequest request,HttpServletResponse response) throws IOException {
request.getSession().removeAttribute("user");
response.sendRedirect(request.getContextPath()+"/view/login.jsp");
Integer count=(Integer)getServletContext().getAttribute("loginCount");
getServletContext().setAttribute("loginCount",count-1);
}
}
五、过滤器的应用顺序
- web.xml 中的 filter-mapping 元素的顺序决定了 Web 容器应用过滤器到 Servlet 的顺序。
- 若要反转过滤器的顺序,您只需要在 web.xml 文件中反转 filter-mapping 元素即可。
六、web.xml配置各节点说明
<filter>
指定一个过滤器。
<filter-name>
用于为过滤器指定一个名字,该元素的内容不能为空。<filter-class>
元素用于指定过滤器的完整的限定类名。<init-param>
元素用于为过滤器指定初始化参数,它的子元素<param-name>
指定参数的名字,<param-value>
指定参数的值。- 在过滤器中,可以使用
FilterConfig
接口对象来访问初始化参数。<filter-mapping>
元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-name>
子元素用于设置filter的注册名称。该值必须是在<filter>
元素中声明过的过滤器的名字<url-pattern>
设置 filter 所拦截的请求路径(过滤器关联的URL样式)<servlet-name>
指定过滤器所拦截的Servlet名称。<dispatcher>
指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是request
,include
,forward
和error
之一,默认request
。用户可以设置多个<dispatcher>
子元素用来指定 Filter 对资源的多种调用方式进行拦截。<dispatcher>
子元素可以设置的值及其意义
request
:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。include
:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。forward
:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。error
:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。