过滤器
借鉴:
https://www.cnblogs.com/ygj0930/p/6374212.html
实质:
实现Filter接口的Java类
API:
init() //启动服务器时执行
doFilter(ServletRequest ,ServletResponse , FilterChain)//当可以拦截的请求到达时,新建一个线程去执行。同Servlet一样,
destory()//关闭服务器时执行
public class FilterDemo1 implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//拦截时执行语句
//执行这一句,说明放行(让下一个过滤器执行,如果没有过滤器了,就执行执行目标资源)
chain.doFilter(req, resp);
//从后一个过滤器返回,或从目标资源返回时,执行语句。
}
public void init(FilterConfig config) throws ServletException {
}
}
功能:
- 拦截访问Servlet的请求,在执行Servlet前执行自定义代码
- 通过chain.doFilter(req, resp);的有无决定是否放行,放行的话会执行到过滤器链下一个过滤器,如果还有的话;如果没有则会执行请求的目标Servlet
- 在Servlet执行后,返回到Filter时,执行一些自定义代码
实现方法:
- 新建Filter类,实现doFilter方法
- 部署,即配置Filter所拦截的url、参数等等
实现方式一、在web.xml中配置
//filter用于注册过滤器
<filter>
<filter-name>FilterDemo1</filter-name>
<filter-class>FilterDemo1</filter-class>
<init-param>
<param-name>word_file</param-name>
<param-value>/WEB-INF/word.txt</param-value>
</init-param>
</filter>
//<filter-mapping>元素用于设置一个Filter 所负责拦截的资源
//一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-mapping>
<filter-name>FilterDemo1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
实现方式二、在Filter类上直接写注解
@WebFilter(filterName = "FilterDemo1",urlPatterns = "/*")
使用场景
- 编码问题,解决中文乱码
在Filter类,添加注解,指明urlpatterns或value(2者不可同时使用)
Filter类doFilter方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
req.setCharacterEncoding("utf-8");
res.setCharacterEncoding("utf-8");
res.setHeader("Content-type", "text/html;charset=utf-8");
chain.doFilter(req, res);
}
- 过滤敏感词汇(用户输入的敏感词汇)
- 对所有输出进行压缩(包括文本流和字节流的)
- 权限验证(登录权限、资源访问权限…)
- 自动登录
在登录过后,重新访问登录页面时,使用过滤器判断后跳转到,显示信息的页面。
在浏览器关闭后,利用cookie使得在一定时间之内,仍然可以自动登录
github
过滤器类:AutoLoginFilter.java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//常用的3个参数强制转换 ServletRequest->HttpServletReques
HttpServletRequest req = (HttpServletRequest)request;
//因为后边 进行了请求转发,所以此处不能获取response
//HttpServletResponse res = (HttpServletResponse)response;
HttpSession session = req.getSession();
//当前用户此时已经在浏览器登录,此时正在使用浏览器。
//由session的属性值(可以是<str,str>,<str,User>),判断是否登录了
String uname1 = (String)session.getAttribute("uname");
if(uname1!=null){
request.setAttribute("msg", uname1+",登录成功");
//注意在doFilter之前,可以使用请求转发
request.getRequestDispatcher("message.jsp").forward(request, response);
chain.doFilter(request, response);
return;
}
//浏览器关闭一段时间后重开浏览器,访问登录页面。遍历cookie,取出用户名密码,检查。
Cookie[] cookies = req.getCookies();
if(cookies != null) {
for(Cookie cookie: cookies) {
if(cookie.getName() == "autolog") {
String[] str = cookie.getValue().split("&");
String uname = str[0].split("=")[1];
String upsw = str[1].split("=")[1];
if(uname.equals("aaa")&&upsw.equals("123")) {
request.setAttribute("msg", uname1+",登录成功");
request.getRequestDispatcher("message.jsp").forward(request, response);
chain.doFilter(request, response);
return;
}
}
}
}
chain.doFilter(request, response);
}
登录页面login.jsp
<form action="LoginServlet">
<input type="text" name="uname" />用户名
<input type="password" name="upsw" />密码
<input type="submit" value="登录" />
</form>
控制器LoginServlet.java
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//LoginServlet中只用写,正常从login.jsp过来的请求即可。不需要判断是否登录过,这些由Filter处理。
String uname = request.getParameter("uname");
String upsw = request.getParameter("upsw");
if(uname.equals("aaa")&&upsw.equals("123")) {
//设置session属性,标记已登录
request.getSession().setAttribute("uname", uname);
//增加cookie,关闭浏览器后也能自动登录
Cookie cookie = new Cookie("autolog","uname="+uname+"&"+"upsw="+upsw);
cookie.setMaxAge(3*60);
response.addCookie(cookie);
//System.out.println(uname+",登录成功");
request.setAttribute("msg", uname+",登录成功");
}else {
//System.out.println("登录失败");
request.setAttribute("msg", "登录失败");
}
request.getRequestDispatcher("message.jsp").forward(request, response);
}
显示信息页面message.jsp
<%=request.getAttribute("msg")%>
- 禁止浏览器缓存数据
- 在服务器端内存中缓存客户端经常访问的数据(提高访问速度,不用每次都去硬盘读)