Python 官方文档:入门教程 => 点击学习
目录一、过滤器的使用以及实现原理当前的oa项目还存在什么缺陷Filter作用与执行原理过滤器怎么写过滤器的调用顺序Filter的生命周期二、责任链设计模式改造oa项目一、过滤器的使用
①对于DeptServlet、EmpServlet、OrderServlet,每一个Servlet都是处理自己相关的业务;在这些Servlet执行之前都是需要判断用户是否登录了。如果用户登录了,可以继续操作,如果没有登录,需要用户登录。
②这段判断用户是否登录的代码是固定的,并且在每一个Servlet类当中都需要编写,显然代码没有得到重复利用。包括每一个Servlet都要解决中文乱码问题,也有公共的代码。这些代码目前都是重复编写,并没有达到复用。
③怎么解决这个问题?
可以使用Servlet规范中的Filter过滤器来解决这个问题。
①Filter是过滤器。
②Filter可以在Servlet这个目标程序执行之前添加代码,也可以在目标Servlet执行之后添加代码;之前之后都可以添加过滤规则!
③一般情况下,都是在过滤器当中编写公共代码。
(1)编写一个Java类实现javax.servlet.Filter接口,并且实现这个接口当中所有的方法;有三个方法:
①init方法:在Filter对象第一次被创建之后调用,并且只调用一次。
②doFilter方法:只要用户发送一次请求,则执行一次;发送N次请求,则执行N次。在这个方法中编写过滤规则!
③destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。
package com.bjpowernode.javaweb.servlet;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
public MyFilter() {
System.out.println("无参数构造方法执行");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init方法执行");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("Filter1 doFilter方法开始执行");
}
@Override
public void destroy() {
System.out.println("destroy方法执行");
}
}
(2)在WEB.xml文件中对Filter进行配置,这个配置和Servlet很像。
或者使用注解:@WebFilter({"*.do"})
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="Http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<filter>
<filter-name>myfilter</filter-name>
<filter-class>com.bjpowernode.javaweb.servlet.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>/a.do</url-pattern>
</filter-mapping>
</web-app>
(3)打开服务器,无参构造方法和init方法都会执行;访问时doFilter方法才会执行。
①Servlet对象默认情况下,在服务器启动的时候是不会新建对象的。
②Filter对象默认情况下,在服务器启动的时候会新建对象,执行无参构造方法。
③Servlet是单例的,Filter也是单例的。
(4)编写两个类AServlet和BServlet继承httpservlet,并且AServlet路径定义为/a.do(和上面一样),BServlet路径定义为/b.do
package com.bjpowernode.javaweb.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 java.io.IOException;
@WebFilter("/a.do")
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("AServlet中的doGet方法执行了。");
}
}
BServlet类
package com.bjpowernode.javaweb.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 java.io.IOException;
@WebFilter("/b.do")
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("BServlet中的doGet方法执行了。");
}
}
发送请求:http://localhost:8080/servlet14/a.do发现只有过滤器MyFilter类中的doFilter方法执行了;而AServlet中的方法并没有执行:
(5)按理说我们发送http://localhost:8080/servlet14/a.doAservlet和MyFilter都会执行,因为路径都是/a.do ;实际上目标Servlet(Aservlet)是否执行,取决于两个条件:
①第一:在过滤器当中是否编写了:chain.doFilter(request, response); 代码。
②第二:用户发送的请求路径是否和Servlet的请求路径一致。
注意:chain.doFilter(request, response); 这行代码的作用:执行下一个过滤器,如果下面没有过滤器了,执行最终的Servlet。
注意:Filter的优先级,天生的就比Servlet优先级高。/a.do 对应一个Filter,也对应一个Servlet。那么一定是先执行Filter,然后再执行Servlet!
所以不妨重写一下doFilter方法,然后再次去访问:
package com.bjpowernode.javaweb.servlet;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
public MyFilter() {
System.out.println("无参数构造方法执行");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init方法执行");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 在请求的时候添加过滤规则。
System.out.println("Filter1 doFilter方法开始执行");
// 执行下一个过滤器,如果下一个不是过滤器了,则执行目标程序Servlet
// 简单理解就是向下走
chain.doFilter(request,response);
// 在响应的时候添加过滤规则。
System.out.println("Filter1 doFilter方法执行结束。");
}
@Override
public void destroy() {
System.out.println("destroy方法执行");
}
}
执行结果如下:
三句话都执行了,所以现在对于上面那个图就更加容易理解了:
①发送请求的时候,经过了过滤器;
②执行chain.doFilter(request, response); 执行下一个过滤器或者Servlet;
③进行响应也会经过过滤器;
补充:
①@WebFilter("/a.do") 精确匹配,只有发送a.do才会经过这个过滤器。
②@WebFilter({"/a.do", "/b.do"}) 匹配一个数组,发送a.do和b.do都可以经过这个过滤器。
③@WebFilter("*.do") 模糊匹配中的扩展匹配。以星号开始,注意这种路径不要以/开始。
④@WebFilter("/dept public class LoginFilter implements Filter { // 也可以只重写其中一个方法 @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { // 注意这里要先进行强转为HttpServlet,后面才能调用对应的方法 HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse) resp; // 获取请求路径 String servletPath = request.getServletPath(); // 获取当前session对象,获取不到就返回null HttpSession session = request.getSession(false); if("/index.jsp".equals(servletPath) || "/welcome".equals(servletPath) || "/dept/login".equals(servletPath) || "/dept/exit".equals(servletPath) || (session != null && session.getAttribute("username") != null)){ // 经过上面过滤,只有上面的路径才会直接通过;其它的操作都要先跳转到登录页面 // 继续往下走 chain.doFilter(request, response); }else{ response.sendRedirect(request.getContextPath() + "/index.jsp"); } } }
这个过滤器写好以后,以后其它类也可以调用这个过滤器,都不用验证登录了;例如:一个员工的Servlet(EmpServlet)
package com.bjpowernode.oa.web.action;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
public class EmpServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 乱码问题也可以写入过滤器当中
// post请求乱码问题
request.setCharacterEncoding("UTF-8");
// 响应中文乱码问题
response.setContentType("text/html;charset=UTF-8");
HttpSession session = request.getSession(false);
if(session != null && session.getAttribute("username") != null){
String servletPath = request.getServletPath();
//...
}else{
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}
}
对于原来的DeptServlet类也可以进行修改了:
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("username") != null){ // session对象不一定为null
// 获取servlet path
String servletPath = request.getServletPath();
if ("/dept/list".equals(servletPath)){
doList(request,response);
}else if("/dept/detail".equals(servletPath)){
doDetail(request,response);
}else if("/dept/delete".equals(servletPath)) {
doDel(request, response);
}else if("/dept/add".equals(servletPath)) {
doAdd(request, response);
}else if("/dept/modify".equals(servletPath)) {
doModify(request, response);
}
}else{
// 跳转到登录页面
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
修改为:
String servletPath = request.getServletPath();
if ("/dept/list".equals(servletPath)){
doList(request,response);
}else if("/dept/detail".equals(servletPath)){
doDetail(request,response);
}else if("/dept/delete".equals(servletPath)) {
doDel(request, response);
}else if("/dept/add".equals(servletPath)) {
doAdd(request, response);
}else if("/dept/modify".equals(servletPath)) {
doModify(request, response);
}
到此这篇关于Java Filter过滤器的使用教程的文章就介绍到这了,更多相关Java Filter过滤器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: JavaFilter过滤器的使用教程
本文链接: https://lsjlt.com/news/177633.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0