我們在使用SpringMVC提供接口時,所提供的參數難免會進行參數的合法性校驗,比如非空校驗,最原始的辦法就是手動校驗,比如下面的代碼:
if(StringUtils.isBlank(authorize.getClientId())){ log.debug("clientId為必填項!"); }如果一個兩個參數還好,如果參數很多比如幾十個,那麼就要判斷幾十次,代碼量劇增,可讀性也不好。 SpringMVC為我們提供了Valid,通過Valid很方便的進行數據的合法性校驗,請看代碼:
@GetMapping("authorize") public void authorize(@Valid AuthorizeIn authorize, BindingResult ret){ if(result.hasFieldErrors()){ List errorList = result.getFieldErrors(); //通過斷言拋出參數不合法的異常 errorList.stream().forEach(item -> Assert.isTrue(false,item.getDefaultMessage())); } } public class AuthorizeIn extends BaseModel{ @NotBlank(message = "缺少response_type參數") private String responseType; @NotBlank(message = "缺少client_id參數") private String ClientId; private String state; @NotBlank(message = "缺少redirect_uri參數") private String redirectUri; public String getResponseType() { return responseType; } public void setResponseType(String responseType) { this.responseType = responseType; } public String getClientId() { return ClientId; } public void setClientId(String clientId) { ClientId = clientId; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getRedirectUri() { return redirectUri; } public void setRedirectUri(String redirectUri) { this.redirectUri = redirectUri; } }在controller的方法需要校驗的參數後面必須跟BindingResult,否則無法進行校驗。但是這樣會拋出異常,對用戶而言不太友好! 那怎麼辦呢? 很簡單,我們可以利用Spring的AOP特性,攔截異常,並輸出友好的參數。接下來我們就來實現異常的攔截:
@Component @Aspect public class WebExceptionAspect implements ThrowsAdvice{ public static final Logger logger = LoggerFactory.getLogger(WebExceptionAspect.class); //攔截被RequestMapping註解的方法 @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)") private void webPointcut() { } @AfterThrowing(pointcut = "webPointcut()",throwing = "e") public void afterThrowing(Exception e) throws Throwable { logger.debug("exception 來了!"); if(StringUtils.isNotBlank(e.getMessage())){ writeContent(e.getMessage()); }else{ writeContent("參數錯誤!"); } } /** * 將內容輸出到瀏覽器 * * @param content * 輸出內容 */ private void writeContent(String content) { HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .getResponse(); response.reset(); response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "text/plain;charset=UTF-8"); response.setHeader("icop-content-type", "exception"); PrintWriter writer = null; try { writer = response.getWriter(); writer.print((content == null) ? "" : content); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } } }這樣當我們傳入不合法的參數時就會進入WebExceptionAspect類,從而輸出友好參數。 我們再把驗證的代碼單獨封裝成方法:
protected void validate(BindingResult result){ if(result.hasFieldErrors()){ List errorList = result.getFieldErrors(); errorList.stream().forEach(item -> Assert.isTrue(false,item.getDefaultMessage())); } }這樣每次參數校驗只需要調用validate方法就行了,我們可以看到代碼的可讀性也大大的提高了。