SpringMVC優雅的實現數據校驗

我們在使用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方法就行了,我們可以看到代碼的可讀性也大大的提高了。




分享到:


相關文章: