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

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;

}

 

 

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

 

                                                                           

 

 

转载于:https://my.oschina.net/u/3059492/blog/790936

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值