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 也会在内部将 ...
随机推荐
- json 中关于json数组跟json对象的区别
原文地址:http://blog.csdn.net/lafengwnagzi/article/details/52789171 JSON 是存储和交换文本信息的语法 JSON 文本格式在语法上与创建 ...
- Flume架构
Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统: Flume 介绍 Flume是由cloudera软件公司产出的高可用.高可靠.分布式的海量日志收集系 ...
- 网络编程 tftp下载文件的编程
一.代码 操作码 功能 1 读请求,即下载 2 写请求,即上传 3 表示数据包,即DATA 4 确认码,即ACK 5 错误 from socket import * import struct s=s ...
- 系统计划 Cron作业 为什么/etc/crontab /etc/cron.d /etc/cron.* 那么多的定义方式????
当我们要增加全局性的计划任务时,一种方式是直接修改/etc/crontab.但是,一般不建议这样做,/etc/cron.d目录就是为了解决这种问题而创建的.例如,增加一项定时的备份任务,我们可以这样处 ...
- ElasicSearch(1)
ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java开发的,并作为Apach ...
- PL2303 USB转串口 com
PL2303 USB转串口 com PL-2303 XA/HXA chip http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=225&pc ...
- LNMP 支持 ThinkPHP 的 pathinfo 模式
注意使用LNMP 1.4版 1.修改php.ini 启用pathinfo /usr/local/php/etc/php.ini cgi.fix_pathinfo = 0 值改为1 2.修改/usr/l ...
- 如何学习DeepLearning
多年来,科学家们为了搞清楚神经网络的运行机制,进行了无数次实验.但关于神经网络的内在运行方式,目前还没有系统性的理论,没有具体的路线可以指引你获得更好的性能.简单地下载开源工具包直接使用并不能跑出很棒 ...
- LeetCode OJ 129. Sum Root to Leaf Numbers
题目 Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a num ...
- 微探eventlet.monkey_patch
e ventlet.monkey_patch在运行时动态修改已有的代码,而不需要修改原始代码 在eventlet.monkey_patch中支持以下几种python原生库修改 eventlet.mon ...