SpringMvc在返回数据之前进行统一处理
这里其实有多种解决方案
如果你不需要获取request对象 可以采用aop(环绕通知)的方式来统一修改
如果你需要获取request对象,那么就需要采用下面的方式
0自己定义一个注解,内容如下
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyResponseBody {
}
1继承org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
覆盖
supportsReturnType()方法
handleReturnValue() 方法
以上两个方法的意思就是如果返回值对应的方法或其所在的类打上了@ResponseBody注解, 则返回true, 即使用这个MethodProcessor进行处理. 具体处理过程在handleReturnValue()中
具体代码如下
import java.io.IOException;
import java.util.List; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor; import com.zhaoyao.zybb2b.annotation.MyResponseBody;
import com.zhaoyao.zybb2b.utils.ZybResult; public class MuliLanguageResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor {
private final Logger log = LoggerFactory.getLogger(getClass()); public MuliLanguageResponseBodyMethodProcessor(List<HttpMessageConverter<?>> messageConverters) {
super(messageConverters);
} // 打@MyResponseBody注解且返回类型为ZybResult的方法
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotationUtils.findAnnotation(returnType.getContainingClass(), MyResponseBody.class) != null
|| returnType.getMethodAnnotation(MyResponseBody.class) != null)
&& ZybResult.class.equals(returnType.getParameterType()); } // 具体的处理过程
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) {
// 设置为true以后, 其他的MethodProcessor就不会再进行处理了
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
try {
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
} catch (HttpMediaTypeNotAcceptableException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
2在SpringMvc中配置该bean(关于消息处理器,根据自己的需要灵活配置)
<mvc:annotation-driven>
<mvc:message-converters>
<ref bean="httpConverter" />
</mvc:message-converters>
<mvc:return-value-handlers>
<bean
class="com.zhaoyao.zybb2b.interceptor.MuliLanguageResponseBodyMethodProcessor">
<constructor-arg>
<list>
<ref bean="httpConverter" />
</list>
</constructor-arg>
</bean>
</mvc:return-value-handlers>
</mvc:annotation-driven> <bean id="httpConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<!-- 处理responseBody 里面日期类型 -->
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
</bean>
</property>
<!-- 为null字段时不显示 -->
<property name="serializationInclusion">
<value type="com.fasterxml.jackson.annotation.JsonInclude.Include">NON_NULL</value>
</property>
</bean>
</property>
</bean>
3在方法上 打上MyResponseBody 注解,并且返回值是ZybResult 就会执行我们的处理器
原理解读:
通过阅读RequestMappingHandlerAdapter相关代码发现,HandlerMethodReturnValueHandler是对方法返回值进行处理的策略接口。
而RequestResponseBodyMethodProcessor(用于处理@RequestBody和@ResponseBody注解)继承了AbstractMessageConverterMethodProcessor。
AbstractMessageConverterMethodProcessor实现了HandlerMethodReturnValueHandler接口。
因为我当前的项目是响应json数据给客户端,所以直接继承了RequestResponseBodyMethodProcessor,并重写相关方法
为什么要自定义注解?
因为SpringMvc会优先执行系统的,再执行用户自定义的处理器。
在这里,顺便提一下SpringMvc的核心处理过程,后面遇到问题就可以找到特定的流程去处理
Spring工作流程描述
1. 用户向服务器发送请求,请求被SpringMvc 前端控制器DispatcherServlet(org.springframework.web.servlet.DispatcherServlet)捕获;
2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)
4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(这里可以简单的理解为Controller)。 在填充Handler的入参过程中,根据你的配置,SprinMvc将帮你做一些额外的工作:
adapter具体怎么处理的,请查看这篇文章(http://donald-draper.iteye.com/blog/2326185)
HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
5. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
6. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
7. ViewResolver 结合Model和View,来渲染视图
8. 将渲染结果返回给客户端。
SpringMvc在返回数据之前进行统一处理的更多相关文章
- ajax 与springmvc交互返回数据
1.controller将数据封装成json格式返回页面 @RequestMapping("/dataList") public void datalist(CsoftCunsto ...
- ASP.NET API(MVC) 对APP接口(Json格式)接收数据与返回数据的统一管理
话不多说,直接进入主题. 需求:基于Http请求接收Json格式数据,返回Json格式的数据. 整理:对接收的数据与返回数据进行统一的封装整理,方便处理接收与返回数据,并对数据进行验证,通过C#的特性 ...
- 【springMVC 后台跳转前台】1.使用ajax访问的后台,后台正常执行,返回数据,但是不能进入前台的ajax回调函数中 ----2.前后台都没有报错,不能进入ajax回调函数
问题1: 使用ajax访问的后台,后台正常执行,并且正常返回数据,但是不能进入前台的ajax回调函数中 问题展示: 问题解决: 最后发现是因为后台的方法并未加注解:@ResponseBody,导致方 ...
- springMVC返回数据的四种方式
转自:https://blog.csdn.net/itcats_cn/article/details/82119673 springMVC返回数据的四种方式:第一种,通过request.setAttr ...
- Java封装接口统一返回数据模板
现在大多数都使用前后端分离开发模式,前端通过Ajax请求访问后台服务器,后台返回JSON数据供前端操作,这里编写一个统一返回数据模板类,方便日后操作 public class R extends Ha ...
- Java框架之SpringMVC 03-RequestMapping-请求数据-响应数据
SpringMVC SpringMVC是一种轻量级的.基于MVC的Web层应用框架. 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口. 采用了松散耦合可插拔组件结构,比 ...
- 【spring 后台跳转前台】使用ajax访问的后台,后台正常执行,返回数据,但是不能进入前台的ajax回调函数中
问题: 使用ajax访问的后台,后台正常执行,并且正常返回数据,但是不能进入前台的ajax回调函数中 问题展示: 问题解决: 最后发现是因为后台的方法并未加注解:@ResponseBody,导致方法 ...
- SpringMVC核心——返回值问题
一.SpringMVC 使用 ModelAndView 来处理返回值问题. 1.ModelAndView 官方描述: Holder for both Model and View in the web ...
- SpringMVC(三)-- 视图和视图解析器、数据格式化标签、数据类型转换、SpringMVC处理JSON数据、文件上传
1.视图和视图解析器 请求处理方法执行完成后,最终返回一个 ModelAndView 对象 对于那些返回 String,View 或 ModeMap 等类型的处理方法,SpringMVC 也会在内部将 ...
随机推荐
- NodeJS入门教学
http://v.baidu.com/v?word=Node.JS+%2B+MongoDB&ct=301989888&rn=27&pn=0&db=0&s=0&a ...
- Docker三大核心概念及DockerToolBox安装
一.核心概念 Docker大部分操作都围绕三大概念——镜像.容器和仓库展开. 1.Docker镜像 Docker镜像类似于虚拟机镜像,可以将它理解为一个只读的模板.镜像是创建Docker容器的基础. ...
- AsyncTask(异步任务)
一.AsyncTask ①AsyncTask的源码: public abstract class AsyncTask<Params, Progress, Result> 三种泛型类型分别代 ...
- [UE4]Safe Zone:安全区域
一.在做移动开发的时候,为了避免被手机上的硬件元素挡住界面,就可以使用Safe Zone控件,如下图所示的棕色区域就是Apple IphoneX的课被挡住界面的区域:上面的是Iphone的喇叭位置,下 ...
- c# 数据结构 ArrayList
数据结构 描述数据之间的关系 行为:添加数据,删除数据,插入数据,查找数据,修改数据 追加数据:向这个结构的末尾添加一个数据 删除数据:在这个结构中删除你指定的数据 插入数据:向这个结构中某一个位置插 ...
- k8s学习笔记之二:使用kubeadm安装k8s集群
一.集群环境信息及安装前准备 部署前操作(集群内所有主机): .关闭防火墙,关闭selinux(生产环境按需关闭或打开) .同步服务器时间,选择公网ntpd服务器或者自建ntpd服务器 .关闭swap ...
- List 的add()与addAll()的区别
add 是将传入的参数作为当前List中的一个Item存储,即使你传入一个List也只会另当前的List增加1个元素addAll 是传入一个List,将此List中的所有元素加入到当前List中,也就 ...
- node-gyp和node-pre-gyp笔记
node-gyp大家都不陌生,先不做赘述. node-pre-gyp,install命令可以将存在网络上的作者根据不同平台预编译好的二进制文件下载下来 因为项目需要,博主需要本地编译,而不是去网上下载 ...
- ORACLE_11G归档空间满,由于数据库装完后使用的是默认空间是闪回区
1.首先根据alert跟踪日志发现归档空间满,路径大致如下:cd $ORACLE_BASE/diag/rdbms/jsswgsjk/jsswgsjk1/tracetail -f alert_jsswg ...
- win7+win10系统使用日常经验集锦
请保留此份 Cmd Markdown 的欢迎稿兼使用说明, 当然你也可以使用彩色字体. 或者使用小体字. 或者使用大体字. 如需撰写新稿件,点击顶部工具栏右侧的 新文稿 或者使用快捷键 Ctrl+Al ...