@PostMapping("/login")
public void login(@RequestBody LoginInfoVo vo,HttpServletResponse response) {
//从redis中获取保存的验证码
String code = jedisPool.getResource().get(RedisMessageConstant.SENDTYPE_LOGIN + vo.getTelephone());
if (!(vo.getValidateCode() != null && code != null && code.equals(vo.getValidateCode()))) {
throw new MyException("验证码错误");
}
loginService.login(vo);
Cookie cookie = new Cookie("telephone", vo.getTelephone());
cookie.setPath("/");
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
}
2.生效写法
//1.
@PostMapping("/login")
public BigDecimal login(@RequestBody LoginInfoVo vo,HttpServletResponse response) {
//从redis中获取保存的验证码
String code = jedisPool.getResource().get(RedisMessageConstant.SENDTYPE_LOGIN + vo.getTelephone());
if (!(vo.getValidateCode() != null && code != null && code.equals(vo.getValidateCode()))) {
throw new MyException("验证码错误");
}
loginService.login(vo);
Cookie cookie = new Cookie("telephone", vo.getTelephone());
cookie.setPath("/");
cookie.setMaxAge(60 * 60 * 24 * 30);
response.addCookie(cookie);
return BigDecimal.ZERO;
}
//2.
@PostMapping("/login")
public void login(@RequestBody LoginInfoVo vo) {
//从redis中获取保存的验证码
String code = jedisPool.getResource().get(RedisMessageConstant.SENDTYPE_LOGIN + vo.getTelephone());
if (!(vo.getValidateCode() != null && code != null && code.equals(vo.getValidateCode()))) {
throw new MyException("验证码错误");
}
loginService.login(vo);
}
入参中有HttpServletResponse需要有返回值ResponseBodyAdvice才会生效
原因
spring源码分析
ServletInvocableHandlerMethod.java
没有返回值时走下面代码mavContainer.isRequestHandled()==true会直接return 不走返回值处理逻辑
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);
Assert.state(this.returnValueHandlers != null, "No return value handlers");
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.isRequestHandled()默认值为false
public boolean isRequestHandled() {
return this.requestHandled;
}
只有在入参里面有HttpServletResponse时,匹配对应的参数解析器 ServletResponseMethodArgumentResolver执行resolveArgument方法时把requestHandled置为了true
方法作用:让调用的方法获得访问HttpServletResponse的权限,同时把状态置为请求已处理,我们就能在方法里面处理返回请求
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
if (mavContainer != null) {
mavContainer.setRequestHandled(true);
}
Class> paramType = parameter.getParameterType();
// ServletResponse, HttpServletResponse
if (ServletResponse.class.isAssignableFrom(paramType)) {
return resolveNativeResponse(webRequest, paramType);
}
// ServletResponse required for all further argument types
return resolveArgument(paramType, resolveNativeResponse(webRequest, ServletResponse.class));
}
总结
入参有HttpServletResponse 时,spring参数解析器ServletResponseMethodArgumentResolver把返回请求处理交给我们处理,mavContainer置为已处理,如果没有返回值且mavContainer状态为已处理spring就默认我们处理了返回请求,spring就不处理,如果有返回值spring就还是会处理


