springmvc 动态修改返回值类型,实现方法既能被ajax调用,又能被同步请求调用

点点圈 提交于 2020-05-08 21:11:56

spingmvc 的requestmappling方法如何动态修改返回值类型

业务场景:

    客户端请求服务端(两个公司的不同系统之间的请求,类似于http接口),请求中参数异常就直接给客户端提示,请求正常,服务端控制跳转到自己系统的页面,执行剩余逻辑。

springmvc 的requestmapping 方法,分两种,一种是带有responsebody注解的(ajax操作),一种是没有(做请求跳转)

springmvc 提供了一个 标签(

<mvc:annotation-driven><mvc:return-value-handlers><bean/></mvc:return-value-handlers></mvc:annotation-driven>

),用来注册返回值类型的,我们可以自己定义返回值类型(例如:定义User),

接下来可以了解下生命周期,启动的时候把把自定义的方法返回值类型注册,然后放到一个list里面,

requestmapping方法被调用的时候,先执行方法体,然后会根据方法的实际返回类型,到list中去找,

如果这个返回值类型没有,并且是responsebody方法则转换成json,返回页面,如果不是responsebody则抛出返回类型不支持的异常,要实现我们的需求,就要从这里侵入源码,

前面定义user 假设有两个属性,一个url(地址挑转),一个code(表示给客户端返回错误码)

源码中, org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(

ServletWebRequest webRequest,

ModelAndViewContainer mavContainer, Object... providedArgs

)throws Exception

 

//调用requestmapping 方法

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

//执行完requestmapping 方法,returnValue 就是返回的类型

setResponseStatus(webRequest);

 

if (returnValue == null) {

if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {

mavContainer.setRequestHandled(true);

return;

}

}

else if (StringUtils.hasText(this.responseReason)) {

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;

}

}

 

 

//匹配返回值类型执行的方法

org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(Object returnValue, MethodParameter returnType,

ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {

 

//看方法名就知道,匹配返回值类型

HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);

if (handler == null) {

throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());

}

//类似于渲染

handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);

}

 

//Object value 如果是对象,那肯定就去匹配 json的返回值类型,如果是字符串那就去匹配跳转请求的试图,所以在这里提前对这个对象坐判断,然后在封装成原有的请求就可以实现需求

private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) {

//这里用来判断异步的,可以研究下

boolean isAsyncValue = isAsyncReturnValue(value, returnType);

//匹配自己返回值类型

for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {

if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {

continue;

}

if (handler.supportsReturnType(returnType)) {

//找到对应的返回值类型,

//可以从这里侵入(改源码),

//  没有responbody注解返回

//org.springframework.web.method.annotation.ModelAttributeMethodProcessor@618b340e

//有responbody注解返回

//org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor@5cff5f93

 

 

return handler;

}

}

return null;

}

 

 

//无聊时,瞎研究,可能没有实战意义,特定场景会用上,又不对的麻烦指出

 

                                                                           

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!