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时刻发生了 ...
随机推荐
- 高性能 TCP & UDP 通信框架 HP-Socket v3.5.2
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...
- 玩儿转物联网IoT - 在Beagle Bone Black上运行node.js 程序
物联网(IoT)技术方兴未艾,智能手环,智能血压计,智能眼镜甚至智能鞋垫都开始进入我们的生活,各种智能设备层出不穷,世界已经到了一个"人有多大胆,地有多大产"的时代,不玩儿点物联网 ...
- Android窗口机制分析与UI管理系统
类图关系 在看Android的窗口机制之前,先看看其主要的类图关系以及层级之间的依赖与调用关系 1.window在当前的android系统的中的呈现形式是PhoneWindow (frameworks ...
- Allocators与Criterion的相同点及区别
C++98: 1.相同点: Allocators having the same type were assumed to be equal so that memory allocated by o ...
- 【译】Spring 4 自动装配、自动检测、组件扫描示例
前言 译文链接:http://websystique.com/spring/spring-auto-detection-autowire-component-scanning-example-with ...
- 高性能Mysql主从架构的复制原理及配置详解
温习<高性能MySQL>的复制篇. 1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台 ...
- SQL拼接字段数据
查询语句: SELECT STUFF ( ( SELECT ',' + --分隔符 KeyID --查询字段 FROM #tmp --查询数据表 WITH(NOLOCK) --查询条件 FOR XML ...
- 迭代字典中的key和value
字典是python中十分重要的一个内容. 今天我们来谈谈,在一个 for 循环中,能否同时迭代 key和value?当然可以咯. dict 对象的 items() 方法返回的值: >>&g ...
- 为Ubuntu的root设置密码
问题描述:当安装好Ubuntu系统的时候,root用户没有密码,需要设置. 解决方法:
- 记一次简单的SQL优化
原来的sql是这样写的 SELECT d.ONSALE_BARCODE, d.ONSALE_NAME, c.ONSALE_ID, CAST( , ) ) AS CUSTOMARY_PRICE, CAS ...