CRUD操作需要反复的校验字段是否为空,字段长度等,如果每个字段都用if语句来判断工作量大且会有遗漏。
通过使用注解,可以大大简化实体字段校验。需要在不同的层使用各种注解(@NotEmpty、@Valid、@ControllerAdvice)来合作完成。
本文简单介绍在保存一个module实体时,对name和projectId做非空校验,需要做哪些工作。
Bean层
实体使用@NotEmpty @NotBlank 等来控制非空校验,使用message定义检验不通过的提示信息
import org.hibernate.validator.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class ModuleParam {
@NotNull(message = "项目id不能为空")
private Long projectId;
@NotBlank(message = "模块名称不能为空")
private String name;
...
}
Controller层
使用@Valid注解来对ModuleParam的绑定参数进行校验
import javax.validation.Valid;
@RestController
@RequestMapping(value = "/module")
public class ModuleController {
@ResponseBody
@RequestMapping(value = "/SaveModule", method = RequestMethod.POST)
public Response save( @Valid @RequestBody ModuleParam param) {
logger.info("module saving...");
TblModule module = new TblModule();
if (!StringUtils.isEmpty(param.getId())) {
module = moduleService.findModuleById(param.getId());
}
...
int result = moduleService.save(module);
return Response.ok(result, "模块", module);
}
}
Response 为自己定义的响应类
异常处理
- 在Controller中使用@Valid注解时,会对注解的对象自动触发校验,校验不通过时会抛出MethodArgumentNotValidException异常,所以捕获这个异常就可以自己设计response返回的报错信息。
- 使用注解@ControllerAdvice
来定义一个Global的异常处理类ExceptionhandlerController - 使用注解@ExceptionHandler(MethodArgumentNotValidException.class)来告诉我们的方法要处理Controller抛出的校验异常(MethodArgumentNotValidException)
- 方法里使用BindingResult 来获取校验的message,即我们在实体里定义的(message = “项目id不能为空”)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice
class ExceptionhandlerController {
private static final Logger logger = LoggerFactory.getLogger(ExceptionhandlerController.class);
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Response exception(HttpServletRequest request, Exception exception) {
logger.error("raised exception : " + exception);
return Response.error(exception.getMessage());
}
/**
* 处理实体字段校验不通过异常
* @param ex
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public Response validationError(MethodArgumentNotValidException ex) {
logger.error("raised MethodArgumentNotValidException : " + ex);
BindingResult result = ex.getBindingResult();
final List<FieldError> fieldErrors = result.getFieldErrors();
StringBuilder builder = new StringBuilder();
for (FieldError error : fieldErrors) {
builder.append( error.getDefaultMessage()+"\n");
}
return Response.error(builder.toString());
}
}
Response 示例
public class Response{
private String status;
private Result result = new Result();
private String errorCode;
private String message;
...
protected Response(String message, String code) {
this.status = "02";
this.errorCode=code;
this.message=message;
}
public static Response error(String message) {
return new Response(message, "");
}
}