zoukankan      html  css  js  c++  java
  • Spring拦截机制之后端国际化心得

    需求

    前端请求的header里带有Prefer_Lang参数,向后端传递国际化信息,后端需要在处理业务之前(建立拦截机制),将Prefer_Lang保存于线程上下文。

    思路分析

    初次接收该需求时,为了不改变既有代码而捕获request中的Prefer_Lang参数,脑海中第一反应是拦截器的概念。

    方案一

    Servlet的javax.servlet.Filter 或起源于Spring Security的org.springframework.web.filter.DelegatingFilterProxy

    要点分析

    • 这种Filter在web.xml中配置,表面上能满足需求,但Filter与web容器耦合,不利于将国际化模块提供给第三方使用

    方案二

    SpringMVC的org.springframework.web.servlet.HandlerInterceptor

    具体实施

    • 在spring mvc的xml中配置,基于request-response模型进行拦截,与方案一Filter类似
    <mvc:interceptors>
        <mvc:interceptor>
        <mvc:mapping path="/**" />
        <bean class="com.shjv.tdscdma.omc.server.platform.web.interceptor.LanguageInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    

    要点分析

    • 仔细探讨需求后,发现我们仅需要对Controller的调用进行拦截即可,只有Controller的调用才与后端国际化逻辑有关
    • 该方案对包括html、js等等与后端国际化逻辑无关的任意请求皆进行拦截,无意义地消耗大量系统资源
    • 虽然request-response模型上的拦截机制不可取,但是拦截也是AOP概念中的一部分,故有更优方案

    方案三

    Spring古老的AOP技术org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator

    具体实施

    • 在spring mvc的xml中配置,为所有beanNameController为后缀的bean生成代理对象
    <bean id="languageInterceptor"
          class="com.shjv.tdscdma.omc.server.platform.web.interceptor.LanguageInterceptor"></bean>
    <bean
        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
        <list>
        <value>*Controller</value>
        </list>
        </property>
        <property name="interceptorNames">
        <list>
        <value>languageInterceptor</value>
        </list>
        </property>
    </bean>
    

    要点分析

    • 表面上,该方案很好地实现了对所有beanNameController为后缀的bean进行拦截,没有方案二浪费系统资源的弊端。
    • 但是,无法保证开发人员自行编写的其他bean就不会以Controller为后缀
    • 同时,无法保证开发人员编写的Controller类就一定是以ControllerbeanName后缀
    • 我们知道,编写的Controller能为Spring MVC调度,是因为从代码结构上,强制了Controller类必须标注@Controller的注解,故有更优方案

    方案四

    Spring AOP的XML配置

    具体实施

    • 在spring mvc的xml中配置,拦截所有标注@Controller的注解的Controller
    <bean id="languageInterceptor"
          class="com.shjv.tdscdma.omc.server.platform.web.interceptor.LanguageInterceptor"></bean>
    <aop:config>
        <aop:aspect ref="languageInterceptor">
            <aop:before method="trapLanguage"
                        pointcut="execution(* *(..)) and within(@org.springframework.stereotype.Controller *)"/>
        </aop:aspect>
    </aop:config>
    

    要点分析

    • 目前看来,该方案已经近乎完美地满足了我们的需求,通过within(@org.springframework.stereotype.Controller *)只拦截Spring MVC中的Controller的public方法
      做到。
    • 如果你与我一样是个XML Hater,我们还有更优雅的实现方式。

    方案五

    Spring AOP的Annotation配置。

    具体实施

    • 在此,我们更进一步,只拦截Controller下标注了@RequestMapping的公共方法,JAVA代码如下
    @Component
    @Aspect
    public class LanguageInterceptor {
        @Pointcut("execution(@org.springframework.web.bind.annotation.RequestMapping * *(..)) && within(@org.springframework.stereotype.Controller *)")
        public void controllerMethod() {
        }
    
        @Before("controllerMethod()")
        public void trapLanguage() {
            final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
            LanguageOption.setPreferLang(request == null ? null : request.getHeader("Prefer_Lang"));
        }
    }
    
    • 在spring mvc的xml中配置如下
    <aop:aspectj-autoproxy />
    
  • 相关阅读:
    Socket
    字符串,byte,字典转换整理
    1-嵌入式面试题库
    10-FreeRTOS 队列
    9-FreeRTOS API获取任务使用CPU时间
    7-代码区 | 常量区 | 静态区(全局区) | 堆区 | 栈区
    8-FreeRTOS任务API
    7-FreeRTOS时间片进行任务调度
    6-C指针
    用Union体测试处理器大小端
  • 原文地址:https://www.cnblogs.com/lewh/p/6248267.html
Copyright © 2011-2022 走看看