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中配置,为所有beanName以Controller为后缀的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>
要点分析
- 表面上,该方案很好地实现了对所有beanName以Controller为后缀的bean进行拦截,没有方案二浪费系统资源的弊端。
- 但是,无法保证开发人员自行编写的其他bean就不会以Controller为后缀
- 同时,无法保证开发人员编写的Controller类就一定是以Controller为beanName后缀
- 我们知道,编写的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 />
Spring拦截机制之后端国际化心得的更多相关文章
- 使用方法拦截机制在不修改原逻辑基础上为 spring MVC 工程添加 Redis 缓存
首先,相关文件:链接: https://pan.baidu.com/s/1H-D2M4RfXWnKzNLmsbqiQQ 密码: 5dzk 文件说明: redis-2.4.5-win32-win64.z ...
- 喜大普奔,两个开源的 Spring Boot + Vue 前后端分离项目可以在线体验了
折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...
- 两个开源的 Spring Boot + Vue 前后端分离项目
折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...
- spring拦截器中修改响应消息头
问题描述 前后端分离的项目,前端使用Vue,后端使用Spring MVC. 显然,需要解决浏览器跨域访问数据限制的问题,在此使用CROS协议解决. 由于该项目我在中期加入的,主要负责集成shiro框架 ...
- Spring 拦截器实现+后台原理(HandlerInterceptor)
过滤器跟拦截器的区别 spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的.这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成 ...
- Hibernate工作原理及为什么要用?. Struts工作机制?为什么要使用Struts? spring工作机制及为什么要用?
三大框架是用来开发web应用程序中使用的.Struts:基于MVC的充当了其中的试图层和控制器Hibernate:做持久化的,对JDBC轻量级的封装,使得我们能过面向对象的操作数据库Spring: 采 ...
- Spring Filter过滤器,Spring拦截未登录用户权限限制
转载自:http://pouyang.iteye.com/blog/695429 实现的功能:判断用户是否已登录,未登录用户禁止访问任何页面或action,自动跳转到登录页面. 比较好的做法是不管什 ...
- spring工作机制及为什么要用?
spring工作机制及为什么要用?1.spring mvc请所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求进行真正的处理工作.2.DispatcherSer ...
- Spring(五)Spring缓存机制与Redis的结合
一.Redis和数据库的结合 使用Redis可以优化性能,但是存在Redis的数据和数据库同步的问题. 例如,T1时刻以将 key1 保存数据到 Redis,T2时刻刷新进入数据库,但是T3时刻发生了 ...
随机推荐
- Maven创建web项目:SpringMVC+Mybatis 【转】
IDEA14创建Maven管理的SpringMVC+Mybatis,web项目 项目构建步骤 1.File->New->Project 勾选Create from archetype 点击 ...
- 关于addSubView需要注意的事项 -今天吃了一个大亏
addSubview: Adds a view to the end of the receiver’s list of subviews. 译:增加一个视图到接收者的子视图列表中. - (void) ...
- android 帧动画
首先在res/drawable/name1.xml/定义一组图片集合: <?xml version="1.0" encoding="utf-8"?> ...
- Laravel大型项目系列教程(一)
Laravel大型项目系列教程(一) 一.课程概述 1.课程介绍 本教程将使用Laravel完成一个多用户的博客系统,大概会包含如下内容: 路由管理. 用户管理,如用户注册.修改信息.锁定用户等. 文 ...
- 关于case语句中声明变量并初始化的注意事项
今天看到一句对这个问题特别精辟的总结,记录如下: It is possible to transfer into a block, but not in a way that bypasses dec ...
- Windows API 函数列表 附帮助手册
所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...
- 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题
调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...
- shell比较两个字符串是否相等
比较两个字符串是否相等的办法是: if [ "$test"x = "test"x ]; then这里的关键有几点:1 使用单个等号2 注意到等号两边各有一个空格 ...
- Web系统性能测试术语简介
并发用户 并发一般分为两种情况.一种是严格意义上的并发,即所有的用户在同一时刻做同一件事情或者操作.这种操作一般指做同一类型的业务,比如在信用卡审批业务中,一定数目的用户在同一时刻对已经完成的审批业务 ...
- Linux shell脚本编程(三)
Linux shell脚本编程 流程控制: 循环语句:for,while,until while循环: while CONDITION; do 循环体 done 进入条件:当CONDITION为“真” ...