hibernate validator 校驗(yàn)操作小結(jié)
@Override
public Result<List<Month>> getCalendarList(@Validated({ calendar.class }) @RequestBody GroupDTO dto)}...
在controller 的方法定義中加上 @Validated({ calendar.class }) 注解
(calendar.class 為校驗(yàn)分組 ),那么按照該分組的規(guī)則校驗(yàn)前端傳過(guò)來(lái)的值是否滿足定義的校驗(yàn)規(guī)則。
同一個(gè)dto可能會(huì)在多個(gè)handler的方法中使用,但是可能會(huì)要按照不同的校驗(yàn)規(guī)則分組,如insert的controller需要這個(gè)對(duì)象的屬性都非空,但是刪除的controller只需要id非空即可。那么在dto定義的校驗(yàn)規(guī)則就需要分組:
@NotNull(message="{ProductEmpty}",groups = {deleteGroup.class, addPriceList.class, addPriceWeeks.class,calendarPrice.class})
private Integer productId;
@NotNull(message="{MenuEmpty}",groups = {deleteGroup.class, addPriceList.class,addPriceWeeks.class,calendarPrice.class })
private Integer menuId;
如上所示在校驗(yàn)注解中有g(shù)roups屬性可以定義這個(gè)校驗(yàn)是屬于哪個(gè)分組的,而屬性的值只是一個(gè)空的接口,在controller方法的參數(shù)前使用@Validated({ calendar.class }) 即指定了這個(gè)方法使用哪組校驗(yàn),那么就只會(huì)校驗(yàn)該dto下groups中有該組的屬性。
message中返回的是校驗(yàn)失敗的信息 可以直接寫(xiě)字符串如 “****不能為空” 也可以如上所示在定義一個(gè)properties文件統(tǒng)一每個(gè)返回信息。

可以看到這個(gè)文件名字中有zh_CN,這個(gè)其實(shí)是jar包中自帶的中文返回信息配置,我們同樣可以在hibernate-validator的jar包下找到英文的配置文件 配置它 這樣方便國(guó)際化。
DateEmpty=\u65E5\u671F\u4FE1\u606F\u5FC5\u4F20
ProductEmpty=\u4EA7\u54C1\u4FE1\u606F\u4E0D\u5168
具體配置中是這樣的 配置信息被轉(zhuǎn)碼
配置的好處是有一個(gè)地方統(tǒng)一管理了返回信息,方便修改。
校驗(yàn)規(guī)則制定
1 普通校驗(yàn)

把該注解的屬性填好 加到被校驗(yàn)對(duì)象的字段上就可以了 注意一定要類(lèi)型 匹配 如@MIN加到string頭上 運(yùn)行就會(huì)報(bào)錯(cuò)
2 復(fù)合校驗(yàn)
如果說(shuō) 我的對(duì)象里有對(duì)象屬性 ,對(duì)象的屬性里又有對(duì)象 那么對(duì)這種深層次的校驗(yàn)應(yīng)該這么做:
@Override
public Result<List<Month>> getCalendarList(@Validated({ calendar.class }) @RequestBody GroupDTO dto
) {....
方法定義這里不用變
dto校驗(yàn)規(guī)則中
@NotEmpty(message="價(jià)格信息必傳",groups = { addPriceList.class,addPriceWeeks.class })
private List<@Valid PriceInfo> priceInfos;
首先在校驗(yàn)的屬性對(duì)象前加上@validate注解
然后定義這個(gè)對(duì)象的校驗(yàn)規(guī)則,即對(duì)priceInfo中各個(gè)屬性加上校驗(yàn)注解當(dāng)然想要在這里被校驗(yàn)的字段的校驗(yàn)分組要和外面一直為addPriceList.class 或另一個(gè)。
3 自定義校驗(yàn)
如果說(shuō)框架提供給我的校驗(yàn)不能滿足我的場(chǎng)景需求 那么我們可以自定義校驗(yàn)
屬性單獨(dú)校驗(yàn)
如果我們要定義一個(gè)對(duì)單獨(dú)屬性的校驗(yàn)類(lèi)型:
package admtic.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import admtic.validator.IsNumValidator;
@Documented
@Constraint(validatedBy = IsNumValidator.class)
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface IsNum {
/*
* 用于驗(yàn)證的注解下列這三個(gè)方法必須要,這是Hibernate Validation框架要求的,否則程序再在調(diào)用的時(shí)候會(huì)報(bào)錯(cuò)
* default用于對(duì)屬性給定默認(rèn)值
* 如果不給定默認(rèn)值,則在使用注解的時(shí)候必須給屬性指定屬性值,否則報(bào)錯(cuò)
* 給定默認(rèn)值時(shí),在使用注解的時(shí)候可以不用指定屬性值
*/
String message() default "不是數(shù)字!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
// 非必須屬性
// // 沒(méi)加default給定默認(rèn)值,使用注解的時(shí)候該屬性必須賦值,否則報(bào)錯(cuò)
// String regex();
// // value屬性,加上了default "mercy" 使得該屬性在使用注解的時(shí)候可以不用輸入也不會(huì)報(bào)錯(cuò)
// String value() default "mercy";
}
先自定義一個(gè)校驗(yàn)注解 然后再實(shí)現(xiàn)一個(gè)校驗(yàn)器
package admtic.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import admtic.annotation.IsNum;
/**
* 泛型中一個(gè)是枚舉類(lèi)一個(gè)是校驗(yàn)支持的數(shù)據(jù)類(lèi)型
* @author spf
* @version 2019年5月8日 下午3:46:35
*
*/
public class IsNumValidator implements ConstraintValidator<IsNum, Integer> {
// private String regex;
/**
* 通過(guò)initialize()可以獲取注解里的屬性值
*/
// @Override
// public void initialize(IsNum constraintAnnotation) {
// ConstraintValidator.super.initialize(constraintAnnotation);
// regex = constraintAnnotation.regex();
// }
/**
* 強(qiáng)行return true hahahhah
*/
@Override
public boolean isValid(Integer s, ConstraintValidatorContext arg1) {
if(s == -1){
}
return false;
}
}
需要注意的是 該校驗(yàn)器泛型定義中 第一個(gè)是校驗(yàn)注解的名字 第二個(gè)是校驗(yàn)屬性的類(lèi)型 isvalid返回是否校驗(yàn)成功。
屬性聯(lián)合校驗(yàn)
如果我們要定義一個(gè)對(duì)對(duì)象的聯(lián)合校驗(yàn),比如說(shuō)如果有一個(gè)flag屬性,如果flag屬性為特殊值的話那么這個(gè)對(duì)象就不用校驗(yàn)其他屬性了,或者說(shuō)另一種場(chǎng)景前端輸入的密碼和重復(fù)密碼,我后端這里要校驗(yàn)一下這兩個(gè)屬性的值是否相同,不相同就定義校驗(yàn)失敗,不能操作。這種多個(gè)屬性之間聯(lián)合起來(lái)一起影響校驗(yàn)結(jié)果的聯(lián)合校驗(yàn)需要我們這樣定義:
由于校驗(yàn)注解是自定義的 我們可以把它定義到類(lèi)頭上 然后校驗(yàn)器里獲取到這個(gè)類(lèi)對(duì)象再做聯(lián)合校驗(yàn)
如
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface FieldMatch
{
String message() default "{constraints.fieldmatch}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
// /**
// * Defines several <code>@FieldMatch</code> annotations on the same element
// *
// * @see FieldMatch
// */
// @Target({TYPE, ANNOTATION_TYPE})
// @Retention(RUNTIME)
// @Documented
// @interface List
// {
// FieldMatch[] value();
// }
//只能有string 類(lèi)型的參數(shù) 獲取后再轉(zhuǎn)
String priceTypeId();
String costPrice();
String sellPrice();
String stock();
String flag();
}
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import admtic.annotation.FieldMatch;
//校驗(yàn)注解 也可以用于dto整個(gè)類(lèi) 注意這里的泛型 前面的時(shí)自定義的注解,后面那個(gè)時(shí)被校驗(yàn)的字段類(lèi)型 這個(gè)用于對(duì)象屬性的聯(lián)合校驗(yàn) 所以用object
public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {
// 只能有string 類(lèi)型的參數(shù)
private String priceTypeId;
private String costPrice;
private String sellPrice;
private String stock;
private String flag;
@Override
public void initialize(final FieldMatch constraintAnnotation) {
priceTypeId = constraintAnnotation.priceTypeId();
costPrice = constraintAnnotation.costPrice();
sellPrice = constraintAnnotation.sellPrice();
stock = constraintAnnotation.stock();
flag = constraintAnnotation.flag();
}
@Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
try {
List<Field> fields = Arrays.asList(value.getClass().getDeclaredFields());
Integer priceTypeIdValue = null;
Double sellPriceValue = null;
Double costPriceValue = null;
Integer stockValue = null;
Integer flagValue = null;
fields.forEach(e->e.setAccessible(true));
Map<String, List<Field>> group =
fields.stream().collect(Collectors.groupingBy(Field::getName));
priceTypeIdValue = (Integer) group.get(priceTypeId).get(0).get(value);
if(priceTypeIdValue == null || priceTypeIdValue < 1){
return false;
}
flagValue = (Integer) group.get(flag).get(0).get(value);
if(flagValue == -1){
return true;
}
sellPriceValue = (Double) group.get(sellPrice).get(0).get(value);
costPriceValue = (Double) group.get(costPrice).get(0).get(value);
stockValue=(Integer) group.get(stock).get(0).get(value);
// System.out.println("######");
// System.out.println(priceTypeIdValue);
// System.out.println(sellPriceValue);
// System.out.println(costPriceValue);
// System.out.println(stockValue);
// System.out.println(flagValue);
if(sellPriceValue == null || costPriceValue == null || stockValue == null || priceTypeIdValue == null){
return false;
}
} catch (final Exception ignore) {
ignore.printStackTrace();
return false;
}
return true;
}
}
在校驗(yàn)器中反射獲取屬性值 并進(jìn)行校驗(yàn)處理
校驗(yàn)結(jié)果的處理
立即返回和全部校驗(yàn)
對(duì)一個(gè)對(duì)象校驗(yàn)時(shí),比如說(shuō)我們要校驗(yàn)10個(gè)字段,第3個(gè)字段沒(méi)有通過(guò),此時(shí)我們可以選擇馬上返回前端失敗,也可以選擇把后面的字段全部校驗(yàn),拿到所有字段的校驗(yàn)結(jié)果后再返回。
對(duì)于第一種快速失敗的配置如下:
@Configuration
public class ValidatorConfiguration {
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast( true )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
}
或
//failFast: true 快速失敗返回模式,false 普通模式
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast( true )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
或
//hibernate.validator.fail_fast: true 快速失敗返回模式,false 普通模式
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.addProperty( "hibernate.validator.fail_fast", "true" )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
1 handler 單獨(dú)處理
在每個(gè)controller方法中可以獲取校驗(yàn)失敗后的錯(cuò)誤信息 進(jìn)行處理 如:
@Override
public Result<Boolean> addMenuOne(HttpServletRequest request, @RequestBody @Validated MenuDTO dto,
BindingResult result) {
if (result.hasErrors()) {
for (ObjectError error : result.getAllErrors()) {
return Result.failed(error.getDefaultMessage());
}
}
2 全局處理
每個(gè)方法都加這個(gè)處理太麻煩了 我們可以把這個(gè)錯(cuò)誤跑出來(lái) 再全局處理
方法:
@Override
public Result<List<Month>> getCalendarList(@Validated({ calendar.class }) @RequestBody GroupDTO dto
) {
// if (result.hasErrors()) {
// for (ObjectError error : result.getAllErrors()) {
// return Result.failed(error.getDefaultMessage());
// }
// }
List<Month> months = groupService.getDefaultCalendar(dto);
return Result.success(months);
}
我們把bindingResult 去掉不做處理 之后 全局定義一個(gè)錯(cuò)誤處理器:
package org.dmc.b.admtic.config;
import java.util.stream.Collectors;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.dmc.common.utils.Result;
@ControllerAdvice
public class GloableExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GloableExceptionHandler.class);
@ExceptionHandler({ ConstraintViolationException.class,
MethodArgumentNotValidException.class,
ServletRequestBindingException.class,
BindException.class })
@ResponseBody
public Result<?> handleValidationException(Exception e) {
String msg = "";
if (e instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException t = (MethodArgumentNotValidException) e;
msg = t.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(","));
} else if (e instanceof BindException) {
BindException t = (BindException) e;
msg = t.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(","));
} else if (e instanceof ConstraintViolationException) {
ConstraintViolationException t = (ConstraintViolationException) e;
msg = t.getConstraintViolations().stream().map(ConstraintViolation::getMessage)
.collect(Collectors.joining(","));
} else if (e instanceof MissingServletRequestParameterException) {
MissingServletRequestParameterException t = (MissingServletRequestParameterException) e;
msg = t.getParameterName() + " 不能為空";
} else if (e instanceof MissingPathVariableException) {
MissingPathVariableException t = (MissingPathVariableException) e;
msg = t.getVariableName() + " 不能為空";
} else {
msg = "必填參數(shù)缺失";
}
log.warn("=========================**********=====================參數(shù)校驗(yàn)不通過(guò),msg: {}", msg);
return Result.failed(msg);
}
}
可以達(dá)到同樣的效果 但是又少些了很多代碼

返回前端

用到的注解
@ControllerAdvice
@ControllerAdvice 注解,spring3.2提供的新注解,控制器增強(qiáng),全局增強(qiáng)可以用于定義@ExceptionHandler、@InitBinder、@ModelAttribute,并應(yīng)用到所有@RequestMapping中
使用 @ControllerAdvice,不用任何的配置,只要把這個(gè)類(lèi)放在項(xiàng)目中,Spring能掃描到的地方。就可以實(shí)現(xiàn)全局異常的回調(diào)。
該注解使用@Component注解,這樣的話當(dāng)我們使用<context:component-scan>掃描時(shí)也能掃描到。
僅僅從命名上來(lái)看 advice就是通知,猜想它就是依賴一個(gè)aop實(shí)現(xiàn)。
這個(gè)后面有時(shí)間探究。
如:
@ControllerAdvice
public class MyControllerAdvice {
/**
* 應(yīng)用到所有@RequestMapping注解方法,在其執(zhí)行之前初始化數(shù)據(jù)綁定器
* @param binder
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
//可以對(duì)日期的統(tǒng)一處理
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
//也可以添加對(duì)數(shù)據(jù)的校驗(yàn)
//binder.setValidator();
}
/**
* 把值綁定到Model中,使全局@RequestMapping可以獲取到該值
* @param model
*/
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("author", "Magical Sam");
}
/**
* 全局異常捕捉處理
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map errorHandler(Exception ex) {
Map map = new HashMap();
map.put("code", 100);
map.put("msg", ex.getMessage());
return map;
}
}
啟動(dòng)應(yīng)用后,上述三個(gè)方法都會(huì)作用在 被 @RequestMapping 注解的方法上
@controllerAdvice源碼
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] assignableTypes() default {};
Class<? extends Annotation>[] annotations() default {};
}
我們可以傳遞basePackage,聲明的類(lèi)(是一個(gè)數(shù)組)指定的Annotation參數(shù)
@ControllerAdvice是一個(gè)@Component,用于定義@ExceptionHandler,@InitBinder和@ModelAttribute方法,適用于所有使用@RequestMapping方法。
Spring4之前,@ControllerAdvice在同一調(diào)度的Servlet中協(xié)助所有控制器。Spring4已經(jīng)改變:@ControllerAdvice支持配置控制器的子集,而默認(rèn)的行為仍然可以利用。
在Spring4中, @ControllerAdvice通過(guò)annotations(), basePackageClasses(), basePackages() 方法定制用于選擇控制器子集。
ControllerAdvice定義的Class是有作用范圍的,默認(rèn)情況下,什么參數(shù)都不指定時(shí)它的作用范圍是所有的范圍。ControllerAdvice提供了一些可以縮小它的處理范圍的參數(shù)。
value:數(shù)組類(lèi)型,用來(lái)指定可以作用的基包,即將對(duì)指定的包下面的Controller及其子包下面的Controller起作用。
basePackages:數(shù)組類(lèi)型,等價(jià)于value。
basePackageClasses:數(shù)組類(lèi)型,此時(shí)的基包將以指定的Class所在的包為準(zhǔn)。
assignableTypes:數(shù)組類(lèi)型,用來(lái)指定具體的Controller類(lèi)型,它可以是一個(gè)共同的接口或父類(lèi)等。
annotations:數(shù)組類(lèi)型,用來(lái)指定Class上擁有指定的注解的Controller。
下面的ControllerAdvice將對(duì)定義在com.elim.app.mvc.controller包及其子包中的Controller起作用。
@ControllerAdvice(value="com.elim.app.mvc.controller")
下面的ControllerAdvice也將對(duì)定義在com.elim.app.mvc.controller包及其子包中的Controller起作用。
@ControllerAdvice(basePackages="com.elim.app.mvc.controller")
下面的ControllerAdvice也將對(duì)定義在com.elim.app.mvc.controller包及其子包中的Controller起作用。它通過(guò)basePackageClasses指定了需要作為基包的Class,此時(shí)基包將以basePackageClasses指定的Class所在的包為準(zhǔn),即com.elim.app.mvc.controller。
@ControllerAdvice(basePackageClasses=com.elim.app.mvc.controller.Package.class)
面的ControllerAdvice將對(duì)FooController及其子類(lèi)型的Controller起作用。
@ControllerAdvice(assignableTypes=FooController.class)
下面的ControllerAdvice將對(duì)所有Class上使用了RestController注解標(biāo)注的Controller起作用。
@ControllerAdvice(annotations=RestController.class)
也可以同時(shí)指定多個(gè)屬性,比如下面的ControllerAdvice將對(duì)FooController及其子類(lèi)型的Controller起作用,同時(shí)也將對(duì)com.elim.app.mvc.controller包及其子包下面的Controller起作用。
@ControllerAdvice(assignableTypes=FooController.class, basePackages="com.elim.app.m
@ExceptionHandler
@ExceptionHandler 攔截了異常,我們可以通過(guò)該注解實(shí)現(xiàn)自定義異常處理。其中,@ExceptionHandler 配置的 value 指定需要攔截的異常類(lèi)型。
需要注意的是使用@ExceptionHandler注解傳入的參數(shù)可以一個(gè)數(shù)組,且使用該注解時(shí),傳入的參數(shù)不能相同,也就是不能使用兩個(gè)@ExceptionHandler去處理同一個(gè)異常。如果傳入?yún)?shù)相同,則初始化ExceptionHandler時(shí)會(huì)失敗
當(dāng)一個(gè)Controller中有方法加了@ExceptionHandler之后,這個(gè)Controller其他方法中沒(méi)有捕獲的異常就會(huì)以參數(shù)的形式傳入加了@ExceptionHandler注解的那個(gè)方法中
除了全局增強(qiáng)捕獲所有Controller中拋出的異常,我們也可以使用接口的默認(rèn)方法(1.8)
public interface DataExceptionSolver {
@ExceptionHandler
@ResponseBody
default Object exceptionHandler(Exception e){
try {
throw e;
} catch (SystemException systemException) {
systemException.printStackTrace();
return WebResult.buildResult().status(systemException.getCode())
.msg(systemException.getMessage());
} catch (Exception e1){
e1.printStackTrace();
return WebResult.buildResult().status(Config.FAIL)
.msg("系統(tǒng)錯(cuò)誤");
}
}
}
但這種方法即依賴1.8 又需要controller實(shí)現(xiàn)接口 不如全局爽。
還有更加偷雞的方法時(shí)直接定義到handler中 @ExceptionHandler這個(gè)只會(huì)是在當(dāng)前的Controller里面起作用
當(dāng)一個(gè)Controller中有多個(gè)@ExceptionHandler注解出現(xiàn)時(shí),那么異常被哪個(gè)方法捕捉呢?這就存在一個(gè)優(yōu)先級(jí)的問(wèn)題,@ExceptionHandler的優(yōu)先級(jí)是:在異常的體系結(jié)構(gòu)中,哪個(gè)異常與目標(biāo)方法拋出的異常血緣關(guān)系越緊密,就會(huì)被哪個(gè)捕捉到
@Controller
@RequestMapping(value = "exception")
public class ExceptionHandlerController {
@ExceptionHandler({ ArithmeticException.class })
public String handleArithmeticException(Exception e) {
e.printStackTrace();
return "error";
}
@RequestMapping(value = "e/{id}", method = {RequestMethod.GET })
@ResponseBody
public String testExceptionHandle(@PathVariable(value = "id") Integer id) {
System.out.println(10 / id);
return id.toString();
}
}
當(dāng)訪問(wèn)exception/e/0的時(shí)候,會(huì)拋出ArithmeticException異常,@ExceptionHandler就會(huì)處理并響應(yīng)error.jsp
@ResponseStatus
這里還有一個(gè)注解@ResponseStatus 可以將某種異常映射為HTTP狀態(tài)碼
如:
@Controller
@RequestMapping(value = "status")
public class ResponseStatusController {
/**
* ResponseStatus修飾目標(biāo)方法,無(wú)論它執(zhí)行方法過(guò)程中有沒(méi)有異常產(chǎn)生,用戶都會(huì)得到異常的界面。而目標(biāo)方法正常執(zhí)行
* @param id
* @return
*/
@RequestMapping(value = "e2/{id}", method = { RequestMethod.GET })
@ResponseStatus(value = HttpStatus.BAD_GATEWAY)
@ResponseBody
public String status2(@PathVariable(value = "id") Integer id) {
System.out.println(10 / id);
return id.toString();
}
}
這樣前端即使請(qǐng)求成功了也會(huì)返回 502的狀態(tài)碼
那么 將這個(gè)注解也放入controller增強(qiáng)的代碼中
/**
* 捕獲CustomException
* @param e
* @return json格式類(lèi)型
*/
@ResponseBody
@ExceptionHandler({CustomException.class}) //指定攔截異常的類(lèi)型
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //自定義瀏覽器返回狀態(tài)碼
public Map<String, Object> customExceptionHandler(CustomException e) {
Map<String, Object> map = new HashMap<>();
map.put("code", e.getCode());
map.put("msg", e.getMsg());
return map;
}
/**
* 捕獲CustomException
* @param e
* @return 視圖
*/
// @ExceptionHandler({CustomException.class})
// public ModelAndView customModelAndViewExceptionHandler(CustomException e) {
// Map<String, Object> map = new HashMap<>();
// map.put("code", e.getCode());
// map.put("msg", e.getMsg());
// ModelAndView modelAndView = new ModelAndView();
// modelAndView.setViewName("error");
// modelAndView.addObject(map);
// return modelAndView;
// }
那么單獨(dú)多定義幾個(gè)處理方法 即可控制返回的錯(cuò)誤碼