zoukankan      html  css  js  c++  java
  • Spring过滤器和拦截器 2017-12-20

    今天在处理多个不同跨域请求时,突然发现一个问题。那就是什么时候用过滤器,什么时候使用拦截器。

    曾记得不久前面试的时候面试官提出过这个问题,当时也粗略的看过相关信息,但是答题时根据自己的理解再加以描述的时候发现似乎找不出2者的区别。

    现在轮到自己处理问题了,今天在CSDN找到一篇文章,其文章来源链接指向博客园,优雅的编辑和展现风格吸引我注册了博客园。

    因为这个缘故所以将第一篇随笔记录此内容,当然大部分都是这个链接的内容http://www.cnblogs.com/dreamroute/p/4198087.html?utm_source=tuicool,也包含自己项目中的一些经验。

    另外关于技术方面的博客、百度等,国内的网络IT知识可信度确实不高,很多问题都要绕道许久才能解决,又由于工作强度或者习惯问题在处理问题之后不愿意随手记录,相信自己的头脑

    肯定能胜过小时候厌恶的“烂笔头”记忆。所以当有些问题无法确定的时候又要重复一遍一遍的百度,将以前的路重新走一遍,浪费时间和情绪。

    说了这么多,只是想说明2个问题:一、记录博客的时候尽量记录自己的实际操作记录,尽量详细。不要给看的人埋坑,不要给自己埋坑    二、有用的东西记录下来,不能偷懒

    以下引用http://www.cnblogs.com/dreamroute/p/4198087.html?utm_source=tuicool:

    ①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
      ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
      ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
      ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
      ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

      6.拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

    另摘自http://blog.csdn.net/chenleixing/article/details/44573495#reply ,疑似《java编程思想》截图

    这本书对java开发者来说确实是奇书,虽然不管什么时候看都是似懂非懂,而且每次都没看完。但确实有帮助,推荐1-2年开发者看

    什么时候使用过滤器?(以最原始的spring框架为例)

    大家请看我的web.xml过滤器配置,依次 为shiro权限过滤器,编码过滤器,微信接口过滤器,上传文件过滤器

    <!-- shiro过滤器定义 -->
      <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
          <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
          <param-name>targetFilterLifecycle</param-name>
          <param-value>true</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      <!-- 编码过滤器 -->
      <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--<async-supported>true</async-supported>-->
        <init-param>
          <param-name>encoding</param-name>
          <param-value>UTF-8</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    
    
      <!--微信接口访问-->
      <filter>
        <filter-name>WXInterface</filter-name>
        <filter-class>com.shangtu.filter.WXInterfaceFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>WXInterface</filter-name>
        <url-pattern>/WX/*</url-pattern><!-- 你开放的接口前缀  -->
      </filter-mapping>
    
      <!--上传接口访问-->
      <filter>
        <filter-name>UploadInterface</filter-name>
        <filter-class>com.shangtu.filter.FileUploadFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>UploadInterface</filter-name>
        <url-pattern>/upload/*</url-pattern><!-- 你开放的接口前缀  -->
      </filter-mapping>

    然后很不幸的我的项目中没有使用interceptor(第一次自己搭建项目,很多功能需求还在确认中),使用的是aspect,以下以日志记录为例:

    1、注册bean,开启aspect注解支持,开启aspect注解扫描

    <bean id="syslogAspect" class="com.zmz.common.SyslogAspect"></bean>
    <aop:aspectj-autoproxy/>
        <!-- 启动 @AspectJ 支持 -->
        <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
    View Code

    2、建立自定义注解类,达到灵活注解的目的

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    public @interface SyslogAnnotation {
    
        String modelName() default "";   //模块名称
    
        String functionName() default "";  //操作方法
    
        String commons() default "";    //参数注解
    }
    View Code

    3、写入逻辑,日志为操作成功后记录

    @Aspect
    @Component
    public class SyslogAspect {
    
        @Resource
        private SyslogDao syslogDao;
    
        @Value("${dbname}")
        private String dbname;
    
        @Value("${syslogTable}")
        private String syslogTable;
    
        @Pointcut("@annotation(com.zmz.common.SyslogAnnotation)")
        public void syslogAspect() {
        }
    
        @After(value="syslogAspect()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            //获取当前登录人员信息
            ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
            //获取切入当前点的注解对象
            Signature signature = joinPoint.getSignature();
            /*if (!(signature instanceof HandlerMethod)) {
                return;
            }*/
    //        HandlerMethod method = (HandlerMethod)joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
            Method targetMethod =  methodSignature.getMethod();
            SyslogAnnotation logAnnotation = targetMethod.getAnnotation(SyslogAnnotation.class);
    //        SyslogAnnotation logAnnotation = method.getMethodAnnotation(SyslogAnnotation.class);
            //获取注解内容
            String modelName = logAnnotation.modelName();  //使用模块  注解第一部分
            String functionName = logAnnotation.functionName();   //使用功能  注解第二部分
            String commons = logAnnotation.commons(); //参数注解
            //获取方法中的传递参数,使用url格式连接
            StringBuffer bfParams = new StringBuffer();
            Object[] params = joinPoint.getArgs();
            Enumeration<String> paraNames = null;
            if (params != null && params.length > 0) {
                paraNames = request.getParameterNames();
                String key;
                String value;
                while (paraNames.hasMoreElements()) {
                    key = paraNames.nextElement();
                    value = request.getParameter(key);
                    bfParams.append(key).append("=").append(value).append("&");
                }
                if (StringUtils.isEmpty(bfParams)) {
                    bfParams.append(request.getQueryString());
                }
            }
            /**
             * 查询当前日期表是否存在,不存在则先创建再插入
             */
            String tableName = syslogTable + DateUtil.getToday(DateUtil.DATEYYMMDD);
            List tableList = syslogDao.getTableByTableName(dbname,tableName);
            if (tableList == null || tableList.isEmpty()) {
                //创建当前日期表
                Map map = new HashMap();
                String sql = "create table    IF NOT EXISTS    " + tableName + "   like syslog";
                map.put("sql",sql);
                syslogDao.createTableByDate(map);
            }
            //补全参数值,插入表
            Syslog syslog = new Syslog();
            syslog.setModelName(modelName);
            syslog.setFunctionName(functionName);
            syslog.setCommons(commons);
            syslog.setParamString(bfParams.toString());
            syslog.setCreateTime(new Date());
            syslog.setLoginUserId(shiroUser.getId());
            syslog.setLoginUserAccount(shiroUser.getAccount());
            syslog.setLoginUserNick(shiroUser.getNick());
            syslog.setTableName(tableName);
            syslogDao.insertSyslog(syslog);
        }
    
    
    }
    View Code

    至此,只要在controller方法中加入

    @SyslogAnnotation(modelName="代理中心", functionName="给代理发卡", commons="userId:登录ID,agentId:被发卡人ID,card:发卡数量")

    即可获取参数,插入自定义日志到数据库中 。

    而关于Aspect与interceptor的关系,大致百度了一下(不能不信,也不能全信,希望以后能在这方面继续完善更新) 

    AOP是一种将业务逻辑提取出来,以实现代码复用,易于维护的方式,拦截器是它的一种具体实现,aspectJ也是一种具体实现,但拦截器具有代码侵入性,aspectJ具有相比更低的侵入性,更好,易于维护

    根据以上代码事实可以确认的是,

    1、大量的请求块信息处理使用filter,  特别的内部逻辑处理所使用aspect

    2、filter是servlet级别的,不属于spring      aspect和interceptor属于spring框架 

    3、filter配置在web.xml中    interceptor配置在spring配置文件中 

    4、filter的作用范围中可以包含aspect和interceptor

  • 相关阅读:
    Java VS .NET:Java与.NET的特点对比
    .NET Core 快速入门教程
    System.Net.Mail.SmtpClient通过SSL/TLS协议发送邮件失败问题解决
    在CentOS 7上安装&配置PostgreSQL 12
    如何在团队中做好Code Review
    SonarQube部署及代码质量扫描入门教程
    Kafka集群部署指南
    ASP.NET Core 入门教程 10、ASP.NET Core 日志记录(NLog)入门
    ASP.NET Core 入门教程 9、ASP.NET Core 中间件(Middleware)入门
    ASP.NET Core 入门教程 8、ASP.NET Core + Entity Framework Core 数据访问入门
  • 原文地址:https://www.cnblogs.com/mzyy/p/8072951.html
Copyright © 2011-2022 走看看