zoukankan      html  css  js  c++  java
  • 拦截器、过滤器

    拦截器

    配置拦截器

    • 配置springmvc.xml
        <!--配置拦截器-->
        <mvc:interceptors>
             <!--多个拦截器顺序执行-->
            <mvc:interceptor>
                <!--拦截规则-->
                <mvc:mapping path="/user/*"/>
                <!--拦截器类-->
                <bean id="MyInterceptor" class="com.hd.interceptor.MyInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    

    注解方式

    • addPathPatterns 用于添加拦截规则
    • excludePathPatterns 用户排除拦截
    @Configuration
    public class MyWebAppConfigurer implements WebMvcConfigurer {
        /**
         * 拦截器上注入Bean
         * @return
         */
        @Bean
        MyInterceptor myInterceptor() {
            return new MyInterceptor();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
                  // 多个拦截器组成一个拦截器链
               registry.addInterceptor(myInterceptor()).addPathPatterns("/**").excludePathPatterns("/article/**").
    excludePathPatterns("/articles/**").excludePathPatterns("/register.html").excludePathPatterns("/login.html").excludePathPatterns("/user/**").excludePathPatterns("/error/**").excludePathPatterns("/findOne");
    
            super.addInterceptors(registry);
        }
    }
    

    创建拦截器类

    • 继承org.springframework.web.servlet.HandlerInterceptor
    • 其他拦截器接口org.springframework.web.context.request.WebRequestInterceptor,区别HandlerInterceptor接口preHandle无返回值,不能终止请求
    • 方法执行顺序:
      • preHandle:执行handle方法之前调用,多个拦截器会顺序执行多个preHandle方法,其中某个拦截器preHandle方法返回false都终止请求
      • postHandle:执行handle方法之后,返回ModelAndView之前执行(可修改视图),多个拦截器会逆序执行多个postHandle方法
      • afterCompletion:执行完handle方法之后,视图渲染之后执行,多个拦截器会逆序执行多个afterCompletion方法
    • postHandle方法的ModelAndView参数可以修改视图,如改变ctntroller发往视图的参数
    public class MyInterceptor implements HandlerInterceptor {
        /**
         *
         * @param httpServletRequest 请求
         * @param httpServletResponse 响应
         * @param object 当前拦截器对象
         * @return 是否将当前请求拦截下来,true将拦截处理并进入下一步骤,false请求将被终止
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
            System.out.println("preHandle...");
            return true;
        }
    
        /**
         *
         * @param httpServletRequest 请求
         * @param httpServletResponse 响应
         * @param object 当前拦截器对象
         * @param modelAndView 模型视图对象,用于修改视图
         * @throws Exception
         */
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle...");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            System.out.println("afterCompletion...");
        }
    }
    

    使用拦截器实现中文编码设置

        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
            httpServletRequest.setCharacterEncoding("utf-8");
            httpServletResponse.setCharacterEncoding("utf-8");
            return true;
        }
    

    多个拦截器执行顺序

    • 所有拦截器链的preHandle方法返回true才会执行postHandle、afterCompletion
    • 多个拦截器的preHandle()方法顺序执行,postHandle、afterCompletion逆序执行
    • 可通过重写拦截器方法改变顺序

    基于拦截器的用户登陆

    1. 创建拦截器类
    • 获取session中用户数据,session中没有用户说明未登录,跳转登陆页面
    • 实现自动登陆:获取Cookie中用户token,通过token获取用户数据,并保存在session中
    public class MyInterceptor implements HandlerInterceptor {
        @Autowired
        UserService userService;
    
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
            Object userBysession = httpServletRequest.getSession().getAttribute("user");
            if (userBysession == null){
                // 未登录,根据token获取用户
                String loginToken = CookieUtil.findCookieByName(httpServletRequest, "vmds_login_token");
                if (StringUtils.isNotBlank(loginToken)){
                    // 获取用户
                    User user = userService.getUserByToken(loginToken);
                    if (user != null){
                        // 保存用户到session
                        httpServletRequest.getSession().setAttribute("user", user);
                        return true;
                    } else {
                        // 用户未找到,清除cookie
                        CookieUtil.clearCookie(httpServletRequest,httpServletResponse,"vmds_login_token");
                        httpServletResponse.sendRedirect("/login.html");
                        return false;
                    }
                }
                else {
                    // 没有cookie,跳转登录页面
                    httpServletResponse.sendRedirect("/login.html");
                    return false;
                }
            }
            else {
                // 已登陆
                return  true;
            }
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object, ModelAndView modelAndView) throws Exception {
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        }
    }
    
    1. 配置
        <!--配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--拦截规则-->
                <mvc:mapping path="/user/*"/>
                <!--拦截器类-->
                <bean id="MyInterceptor" class="com.hd.interceptor.MyInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    
    1. Controller
    • 保存登陆成功的用户信息到session
    • 更新用户token,写入Cookie
        @RequestMapping(value = "/userlogin", method = RequestMethod.POST)
        @ResponseBody
        public String login(@RequestParam(value = "username") String name, @RequestParam(value = "password") String password, HttpSession session,HttpServletRequest request, HttpServletResponse response) {
            PageData pageData = new PageData(request);
            User user = userService.getUserByLogin(pageData);
            if (null == user) {
                // 用户未找到
                return "error";
            }
    
            // 添加cookie token
            Long mi = System.currentTimeMillis();
            CookieUtil.addCookie(response, "vmds_login_token", mi.toString(), 60 * 60 * 24 * 7);
    
            // 更新用户token
            user.setToken(mi.toString());
            userService.saveUser(user);
    
            session.setAttribute("user", user);
            return "200";
        }
    

    过滤器

    Filter(过滤器)是实现了Filter接口的java类,由 Servlet 容器进行调用和执行的,它可以决定是否将请求继续传递给 Servlet 程序,以及对请求和响应消息是否进行修改

    配置过滤器

    中文过滤器:解决前端传递的中文字符乱码问题

    web.xml

      <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--springmvc提供的字符编码过滤器类-->
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
          <param-name>encoding</param-name>
          <param-value>utf-8</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

    注解方式

    • @WebFilter:过滤器注解
    • FilterConfig:Filter 配置对象,包含初始化参数、Filter name等
    • init(): Web 容器创建 Filter 的实例对象后,将立即调用该 Filter 对象的 init 方法。init 方法在 Filter 生命周期中仅被执行一次
    • doFilter():doFilter 方法来激活目标 Servlet 的 service 方法
    • destroy():该方法在 Web 容器卸载 Filter 对象之前被调用,也仅执行一次
    @WebFilter(
            urlPatterns = "/articles/*",
            initParams = {@WebInitParam(name = "val1", value = "t1"), @WebInitParam(name = "val", value = "t2")})
    public class TestFilter implements Filter{
    
        /**
         * 初始化,web 应用程序启动时实例化所有 Filter,实例化时执行init方法
         * @param filterConfig Filter 配置对象
         * @throws ServletException
         */
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("TestFilter init");
            // 初始化参数
            String filterName = filterConfig.getFilterName();
            Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
            System.out.println("filterName = " + filterName);
            while (initParameterNames.hasMoreElements()) {
                String s = initParameterNames.nextElement();
                System.out.println(s + " = " + filterConfig.getInitParameter(s));
            }
        }
    
        /**
         * 当一个 Filter 对象能够拦截访问请求时,Servlet 容器将调用 Filter 对象的 doFilter 方法
         * @param request
         * @param response
         * @param chain  当前 Filter 链的对象
         * @throws IOException
         * @throws ServletException
         */
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            // 目标Servlet service 方法之前
            chain.doFilter(request, response); // doFilter 方法来激活目标 Servlet 的 service 方法
            // 目标Servlet service 方法之后
        }
    
        @Override
        public void destroy() {
            System.out.println("TestFilter destroy");
        }
    }
    

    拦截器、过滤器区别

    1. 过滤器Filter依赖于servlet,基于回掉函数,范围更大(可过滤一些资源)
    2. 拦截器Interceptor依赖于框架容器,基于反射机制,只能过滤url请求
  • 相关阅读:
    ASP.NET的票据工具类FormsAuthenticationTicket
    FormsAuthenticationTicket学习笔记
    FormsAuthentication与Session超时时间不一的解决方法
    asp.net mvc 从数据库中读取图片的实现代码
    ASP.NET下载远程图片保存到本地的方法、保存抓取远程图片
    获取客户端的IP地址
    C#实现DNS解析服务
    Linux下安装Nginx详细图解教程
    手动配置Ubuntu Linux系列3-缺省网关和主机名
    web运维第一篇:nginx配置文件详解笔记
  • 原文地址:https://www.cnblogs.com/xiongyungang/p/13966671.html
Copyright © 2011-2022 走看看