您的位置:首页 > 移动开发

自定义统一api返回json格式(app后台框架搭建三)

2017-07-01 11:28 891 查看
在统一json自定义格式的方式有多种:1,直接重写@reposeBody的实现,2,自定义一个注解,自己去解析对象成为json字符串进行返回第一种方式,我就不推荐,想弄得的话,可以自己去研究一下源码第二种方式,主要通过定义注解,通过 HandlerMethodReturnValueHandler 对返回值的处理,而不让他进去viewResolver处理==================================================================================1,讲解HandlerMethodReturnValueHandler 处理原理 (简单介绍,网上资料很多)2,如何实现自定义统一的json返回格式==================================================================================

1,HandlerMethodReturnValueHandler

HandlerMethodReturnValueHandler是RequestMappingHandlerAdapter用来处理完映射控制类方法返回的值处理,RequestMappingHandlerAdapter类包含默认的值处理器链的所有处理引擎,默认是会加入handlers.add(new ModelAttributeMethodProcessor(true)); getDefaultReturnValueHandlers()方法里可以查看到所有默认的处理引擎。对处理后的对象,会调用RequestMappingHandlerAdapter里invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)方法:
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {

ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);

WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}

invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}

return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}
}
关键是调用 invocableMethod.invokeAndHandle(webRequest, mavContainer);
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {

Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);

if (returnValue == null) {
if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(getResponseStatusReason())) {
mavContainer.setRequestHandled(true);
return;
}

mavContainer.setRequestHandled(false);
try {
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
}
throw ex;
}
}
首先设置 mavContainer.setRequestHandled(false);说明是会按处理链进行处理,如果设置为true就是处理完就结束了。

this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest); 是真正获取处理链,然后从处理链中选择合适的引擎并依次处理。


HandlerMethodReturnValueHandler 只提供两个接口,
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter returnType);
void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}
第一方法是判断是否支持值处理引擎,第二方法是对值进行处理,并确定是否继续进行下一个处理引擎执行。所以,第一个supportsReturnType(MethodParameter returnType)的判断一定要正确,如果不正确,就永远不会被执行,这是关键。具体的执行,就可以按这几个关键的类去debug一下就可以了。-----------------------------------------------------------------------------------------------------------------

2, 具体的实现

2.1 定义注解:用于识别json转换处理的
import java.lang.annotation.*;

/**
* Created by ThinkPad on 2017/6/22.
*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AppResponsBody {
String type() default "json";
}
2.2 处理引擎的:需要实现 HandlerMethodReturnValueHandler
/**
* Created by ThinkPad on 2017/6/22.
*/
public class FormatJsonReturnValueHandler implements HandlerMethodReturnValueHandler{
@Override
public boolean supportsReturnType(MethodParameter returnType) {
System.out.println("===========sdfdsf==============="+ returnType.getMethodAnnotation(AppResponsBody.class));
boolean hasJSONAnno = returnType.getMethodAnnotation(AppResponsBody.class) != null || returnType.getMethodAnnotation(AppResponsBody.class) != null;
return hasJSONAnno;
}

@Override
public void handleReturnValue(Object obj, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest) throws Exception {
modelAndViewContainer.setRequestHandled(true);
AppResponsBody res=methodParameter.getMethodAnnotation(AppResponsBody.class);
String type = res.type();
HttpServletResponse response=nativeWebRequest.getNativeResponse(HttpServletResponse.class);
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
PrintWriter writer = null;
Gson gson=new Gson();
ResultInfo info=new ResultInfo();
info.setData(obj);
try {
writer = response.getWriter();
writer.write(gson.toJson(info));
writer.flush();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (writer != null)
writer.close();
}
}

}
2.3 注册你编写的HandlerMethodReturnValueHandler引擎 到webConfig配置文件里
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.ouyang.teson"},useDefaultFilters = true)
public class WebConfig extends WebMvcConfigurerAdapter{
配置文件里增加以下:
@Bean
public FormatJsonReturnValueHandler JsonReturnHandler(){
FormatJsonReturnValueHandler formatJsonReturnValueHandler=new FormatJsonReturnValueHandler();
return formatJsonReturnValueHandler;
}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
returnValueHandlers.add(JsonReturnHandler());
}
另外,还需要定义一个响应类处理统一格式的:ResultInfo.java
public class ResultInfo {

public long code;
public String message;
public Object data;

public long getCode() {
if(code==0l){
code=200l;
}
return code;
}

public void setCode(long code) {
this.code = code;
}

public String getMessage() {
if(message==null){
message="处理成功!";
}
return message;
}

public void setMessage(String message) {
this.message = message;
}

public Object getData() {
return data;
}

public void setData(Object data) {
this.data = data;
}
}
至此,我们的所有工作完成,接着进行测试操作:浏览测试结果:注意:如果中途有什么问题,自己可以debug以下,用intellij可以很方便的下载源码,直接debug,这一点很不错,这也没有什么难度。下一节,要讲的就是怎么使用spring-boot快速搭建api后台框架,即是把该配置迁移到spring-boot上并快速启动。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐