2023年6月24日发(作者:)
SpringMVCController返回值及异常的统⼀处理⽅法旧的设计⽅案开发api的时候,需要先定义好接⼝的数据响应结果.如下是⼀个很简单直接的Controller实现⽅法及响应结果定义.@RestController@RequestMapping("/users")public class UserController { @Inject private UserService userService; @GetRequest("/{userId:d+}") public ResponseBean signin(@PathVariable long userId) { try { User user = rBaseInfo(userId); return s(user); } catch (ServiceException e) { return new ReponseBean(e(), ()); } catch (Exception e) { return Error(); } }}{ code: "", data: {}, // 可以是对象或者数组 msg: ""}从上⾯的代码,我们可以看到对于每个 Controller ⽅法,都会有很多重复的代码出现,我们应该设法去避免重复的代码。将重复的代码移除之后,可以得到如下的代码,简单易懂。@RestController@RequestMapping("/users")public class UserController {
@Inject private UserService userService; @GetRequest("/{userId:d+}") public User signin(@PathVariable long userId) { return rBaseInfo(userId); }}在以上的实现中,还做了⼀个必要的要求,就是 ServiceException 需要定义为 RuntimeException的⼦类,⽽不是 Exception的⼦类。由于 ServiceException 表⽰服务异常,⼀般发⽣这种异常是应该直接提⽰前端,⽽⽆需进⾏其他特殊处理的。在定义为 RuntimeException 的⼦类之后,会减少⼤量的异常抛出声明,⽽且不再需要在事务@Transactional 中进⾏特殊声明。统⼀ Controller 返回值格式在开发的过程中,我发现上⾯的结构@ControllerAdvicepublic class ControllerResponseHandler implements ResponseBodyAdvice
private Logger logger = ger(getClass()); @Override public boolean supports(MethodParameter returnType, Class extends HttpMessageConverter>> converterType) { // ⽀持所有的返回值类型 return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { if(body instanceof ResponseBean) { return body; } else { // 所有没有返回 ResponseBean 结构的结果均认为是成功的 return s(body); } }}统⼀异常处理如下的代码中,ServiceException ServiceMessageException ValidatorErrorType FieldValidatorError
均为⾃定义类。@ControllerAdvicepublic class ControllerExceptionHandler { private Logger logger = ger(getClass()); private static final String logExceptionFormat = "[EXIGENCE] Some thing wrong with the system: %s"; /** * ⾃定义异常 */ @ExceptionHandler() public ResponseBean handleServiceMessageException(HttpServletRequest request, ServiceMessageException ex) { (ex); return new ResponseBean(Code(), sage()); } /** * ⾃定义异常 */ @ExceptionHandler() public ResponseBean handleServiceException(HttpServletRequest request, ServiceException ex) { (ex); String message = codeToMessage(Code()); return new ResponseBean(Code(), message); } /** * MethodArgumentNotValidException: 实体类属性校验不通过 * 如: listUsersValid(@RequestBody @Valid UserFilterOption option) */ @ExceptionHandler() public ResponseBean handleMethodArgumentNotValid(HttpServletRequest request, MethodArgumentNotValidException ex) { (ex); return validatorErrors(dingResult()); } private ResponseBean validatorErrors(BindingResult result) { List
List
/** * 对应 Http 请求头的 accept * 客户器端希望接受的类型和服务器端返回类型不⼀致。 * 这⾥虽然设置了拦截,但是并没有起到作⽤。需要通过http请求的流程来进⼀步确定原因。 */ @ExceptionHandler() public ResponseBean handleHttpMediaTypeNotAcceptableException(HttpServletRequest request, HttpMediaTypeNotAcceptableException ex) { (ex); StringBuilder messageBuilder = new StringBuilder().append("The media type is not acceptable.") .append(" Acceptable media types are "); portedMediaTypes().forEach(t -> (t + ", ")); String message = ing(0, () - 2); return new ResponseBean(_(), message); } /** * 对应请求头的 content-type * 客户端发送的数据类型和服务器端希望接收到的数据不⼀致 */ @ExceptionHandler() public ResponseBean handleHttpMediaTypeNotSupportedException(HttpServletRequest request, HttpMediaTypeNotSupportedException ex) { (ex); StringBuilder messageBuilder = new StringBuilder().append(tentType()) .append(" media type is not supported.").append(" Supported media types are "); portedMediaTypes().forEach(t -> (t + ", ")); String message = ing(0, () - 2); n(message); return new ResponseBean(ORTED_MEDIA_(), message); } /** * 前端发送过来的数据⽆法被正常处理 * ⽐如后天希望收到的是⼀个json的数据,但是前端发送过来的却是xml格式的数据或者是⼀个错误的json格式数据 */ @ExceptionHandler() public ResponseBean handlerHttpMessageNotReadableException(HttpServletRequest request, HttpMessageNotReadableException ex) { (ex); String message = "Problems parsing JSON"; return new ResponseBean(_(), message); } /** * 将返回的结果转化到响应的数据时候导致的问题。 * 当使⽤json作为结果格式时,可能导致的原因为序列化错误。 * ⽬前知道,如果返回⼀个没有属性的对象作为结果时,会导致该异常。 */ @ExceptionHandler() public ResponseBean handlerHttpMessageNotWritableException(HttpServletRequest request, HttpMessageNotWritableException ex) { return internalServiceError(ex); } /** * 请求⽅法不⽀持 */ @ExceptionHandler() public ResponseBean exceptionHandle(HttpServletRequest request, HttpRequestMethodNotSupportedException ex) { (ex); StringBuilder messageBuilder = new StringBuilder().append(hod()) .append(" method is not supported for this request.").append(" Supported methods are "); portedHttpMethods().forEach(m -> (m + ",")); String message = ing(0, () - 2); return new ResponseBean(_NOT_(), message); } /** * 参数类型不匹配 */ @ExceptionHandler() public ResponseBean methodArgumentTypeMismatchExceptionHandler(HttpServletRequest request, MethodArgumentTypeMismatchException ex) { (ex); String message = "The parameter '" + e() + "' should of type '" + uiredType().getSimpleName().toLowerCase() + "'"; FieldValidatorError fieldNotValidError = new FieldValidatorError(); e(_()); ld(e()); sage(message); return torError((fieldNotValidError)); } /** * 缺少必填字段 */ @ExceptionHandler() public ResponseBean exceptionHandle(HttpServletRequest request, MissingServletRequestParameterException ex) { (ex); String message = "Required parameter '" + ameterName() + "' is not present"; FieldValidatorError fieldNotValidError = new FieldValidatorError(); e(G_()); ld(ameterName()); sage(message); return torError((fieldNotValidError)); } /** * ⽂件上传时,缺少 file 字段 */ @ExceptionHandler() public ResponseBean exceptionHandle(HttpServletRequest request, MissingServletRequestPartException ex) { (ex); return new ResponseBean(_(), sage()); } /** * 请求路径不存在 */ @ExceptionHandler() public ResponseBean exceptionHandle(HttpServletRequest request, NoHandlerFoundException ex) { (ex); String message = "No resource found for " + pMethod() + " " + uestURL(); return new ResponseBean(_(), message); } /** * 缺少路径参数 * Controller⽅法中定义了 @PathVariable(required=true) 的参数,但是却没有在url中提供 */ @ExceptionHandler() public ResponseBean exceptionHandle(HttpServletRequest request, MissingPathVariableException ex) { return internalServiceError(ex); } /** * 其他所有的异常 */ @ExceptionHandler() public ResponseBean handleAll(HttpServletRequest request, Exception ex) { return internalServiceError(ex); } private String codeToMessage(int code) { //TODO 这个需要进⾏⾃定,每个 code 会匹配到⼀个相应的 msg return "The code is " + code; } private ResponseBean internalServiceError(Exception ex) { logException(ex); // do something else return Error(); } private
发布者:admin,转转请注明出处:http://www.yc00.com/web/1687606748a24136.html
评论列表(0条)