最近做springboot项目,踩下的坑,留个笔记
接收参数的对象
package cn.invcloud.platform.optMnt.vo;
import javax.validation.constraints.NotBlank;
public class PasswordUserVO {
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
将参数自动转成对象,如果参数@Valid有错误,就会保存在BindingResult中
填坑一:BindingResult 对象必须在 @Valid 的紧挨着的后面,否则接收不到错误信息。
@ApiOperation(value = "用户名密码方式登陆API", notes = "传入用户名密码,获取登陆token")
@PostMapping("/password")
public ResponseBean login(@RequestBody @Valid PasswordUserVO passwordUserVO, BindingResult bindingResult) {
//根据用户名密码获取用户
OperateUser operateUser = loginService.getOperateUserFromPassword(passwordUserVO.getUsername(), passwordUserVO.getPassword());
if (operateUser == null) {
throw new OperationServException(OperationServExceptionEnum.WRONGUSERNAMEORPASSWORD);
}
//查询权限,把用户名,角色放到jwt并签名
Role role = roleRepository.findById(operateUser.getRoleId()).get();
String[] roles = {role.getName()};
String sign = JWTUtil.sign(operateUser.getUuid(), roles);
// response.addCookie(new Cookie("sign",sign));
// response.setStatus(302);
return new ResponseBean(sign);
}
AOP拦截所有的controller相关的方法,bindingResult如果有异常,就获取其中错误,往外抛,让异常处理器处理
package cn.invcloud.platform.optMnt.aop;
import cn.invcloud.platform.optMnt.exception.OperationServException;
import cn.invcloud.platform.optMnt.exception.OperationServExceptionEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import java.util.ArrayList;
import java.util.List;
/**
* 统一参数异常处理
*/
@Aspect
@Component
public class ParamValidatorInterceptor {
@Around("execution(* cn.invcloud.platform.optMnt.controller.*.*(..)) && args(..,bindingResult)")
public Object doAround(ProceedingJoinPoint pjp, BindingResult bindingResult) throws Throwable {
//检查请求bindingResult是否有异常
if (bindingResult.hasErrors()) {
List<String> errMsgs = new ArrayList<>();
for(ObjectError error : bindingResult.getAllErrors()){
errMsgs.add(error.getDefaultMessage());
}
OperationServException operationServException = new OperationServException(OperationServExceptionEnum.BADREQUESTPARAM,errMsgs);
//向外抛出异常,由异常处理器处理
throw operationServException;
}
return pjp.proceed();
}
}
异常处理器
package cn.invcloud.platform.optMnt.exception;
import cn.invcloud.platform.optMnt.vo.ResponseBean;
import org.apache.shiro.ShiroException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
@RestControllerAdvice
public class MyExceptionHandler {
private Logger LOGGER = LoggerFactory.getLogger(MyExceptionHandler.class);
// 捕捉已知的业务异常
@ExceptionHandler(OperationServException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseBean globalException(HttpServletRequest request, OperationServException ex) {
ex.printStackTrace();
LOGGER.error(ex.getMessage());
return new ResponseBean(ex.getCode(), ex.getMessage(), ex.getErrorDetail());
}
}
填坑二:AOP拦截器的expression 包含了我的controller,如果controller的方法是private的,会导致@Autowired依赖注入失败,只需把controller的请求方法改成public即可
详情可参考http://www.cnblogs.com/lcngu/p/6246950.html
附上常见限制说明