过滤器(Filter)和拦截器(Interceptor)

servlet+过滤器:github:https://github.com/xaioheilj/ServeletCRUDandJSON.git

所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。该接口定义了以下3个方法:

  •  init(FilterConfig) :这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后就会调用这个方法。在这个方法中可以通过 FilterConfig来读取web.xml文件中Servlet过滤器的初始化参数。
  • doFilter(ServletRequest, ServletResponse, FilterChain) : 这是完成实际的过滤操作的方法,当客户请求访问与过滤器关联的URL时,Servlet容器先调用该方法。FilterChain参数用来访问后续的过滤 器的doFilter()方法。
  • destroy() :Servlet容器在销毁过滤器实例前调用该方法,在这个方法中,可以释放过滤器占用的资源。

Filter的生命周期

    Filter的创建和销毁由web服务器控制。

  • 服务器启动的时候,web服务器创建Filter的实例对象,并调用其init方法,完成对象的初始化功能。filter对象只会创建一次,init方法也只会执行一次。
  • 拦截到请求时,执行doFilter方法。可以执行多次。
  • 服务器关闭时,web服务器销毁Filter的实例对象。
  • 缺点是一个过滤器实例只能在容器初始化时调用一次。

1.集中解决中文乱码 

public class EncodingFilter implements Filter {
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
 
        request.setCharacterEncoding("UTF-8");
 
        chain.doFilter(request, response);
    }
 
    @Override
    public void init(FilterConfig arg0) throws ServletException {
 
    }
 
}

 在web.xml中添加映射即可

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>filter.EncodingFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

2.登录验证

 

public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession(true); //启用Session,过滤器从中获取信息
        String name = request.getParameter("userName");
        String password = request.getParameter("password");

        session.setAttribute("userName",name);
        session.setAttribute("password",password);

        if ("admin".equals(name) && "123".equals(password)) {
            request.getRequestDispatcher("addHero.html").forward(request, response);
        }else{
            response.sendRedirect("login.html");
        }

    }
}
public class AuthFilter implements Filter {

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String uri = request.getRequestURI();
        if (uri.endsWith("login.html") || uri.endsWith("login")) {
            chain.doFilter(request, response);
            return;
        }

        String userName = (String) request.getSession().getAttribute("userName");
        if (null == userName) {
            response.sendRedirect("login.html");
            return;
        }

        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

}

  在web.xml中添加映射即可

    <filter>
        <filter-name>AuthFilter</filter-name>
        <filter-class>filter.AuthFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>AuthFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

SpringBoot+Interceptor :github:https://github.com/xaioheilj/SpringBoottest1.git

它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
 

/*过滤器,登录检查*/
/*实现拦截器可以通过继承HandlerInterceptorAdapter类。如果preHandle方法return true,则继续后续处理。*/
public class LoginHandleInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object user= request.getSession().getAttribute("loginUser");
        if (user == null){
            //没有登陆过,不予许直接访问dashboard,并返回到登录页面
            request.setAttribute("msg","没有权限,先登录");
            request.getRequestDispatcher("/login").forward(request,response);
            return false;
        }else {
            return true;
        }

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

在配置信息注册拦截器

/*
*实现拦截器后还需要将拦截器注册到spring容器中,可以通过implements WebMvcConfigurer,覆盖其*addInterceptors(InterceptorRegistry registry)方法。记得把Bean注册到Spring容器中,可以选择*@Component 或者 @Configuration。
*/
//@EnableWebMvc //全面接管SpringMVC
@Configuration
//使用WebMvcConfigurer扩展SpringMVC的功能,所有的WebMvcConfigurer都会一起起作用
public class MyMVCconfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //浏览器发送/felix请求,到达firstPage页面
        registry.addViewController("/felix").setViewName("firstPage");
    }
        @Bean // 将组建注册在容器中
    public WebMvcConfigurer wbc(){
                //引入静态资源文件,使访问路径直接访问到login页面
                WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
                    @Override
                    public void addViewControllers(ViewControllerRegistry registry) {
                        registry.addViewController("/").setViewName("login");
                        registry.addViewController("/login").setViewName("login");
                        registry.addViewController("/main").setViewName("dashboard");
                    }

                    //注册拦截器
                    @Override
                    public void addInterceptors(InterceptorRegistry registry) {
                        registry.addInterceptor(new LoginHandleInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/","/user/login","/asserts/**","/webjars/**");

                    }


                };
                return webMvcConfigurer;
    }

}

 

 过滤器filter和拦截器Interceptor的区别
spring的拦截器和servlet的过滤器有相似之处,都是AOP思想的体现,都可以实现权限检查,日志记录,不同的是

适用范围不同:Filter是Servlet容器规定的,只能使用在servlet容器中,而拦截器的使用范围就大得多
使用的资源不同:拦截器是属于spring的一个组件,因此可以使用spring的所有资源,对象,如service对象,数据源,事务控制等,而过滤器就不行
深度不同:Filter还在servlet前后起作用。而拦截器能够深入到方法前后,异常抛出前后,因此拦截器具有更大的弹性,所有在spring框架中应该优先使用拦截器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章