spring mvc 为控制器添加通知

为控制器添加通知

与SpringAOP一样,SpringMVC也可以为控制器加入通知,它主要涉及4个注解:

  • @ControllerAdvice:作用于类,用以标识全局性的控制的拦截器,将应用于对应的控制器
  • @InitBinder:允许在构造控制器参数的时候,加入一定的自定义控制
  • @ExceptionHandler:当控制器发生异常时,就会跳转到该方法上
  • @ModelAttribute:先于控制器方法执行,当标注方法返回对象时,会保存到数据模型中,并传递给拦截的控制器

一个控制器通知的实例。

//标识控制器通知,并且指定对应的包  
@ControllerAdvice(basePackages = {"com.wise.tiger.controller.advice"})  
public class CommonControllerAdvice {  
    /** 
     * 定义http对应参数处理规则 
     */  
    @InitBinder  
    public void initBinder(WebDataBinder binder){  
        //针对日期类型的格式化,其中CustomDateEditor是客户自定义编辑器  
        //boolean值表示是否允许为空  
        binder.registerCustomEditor(Date.class,  
                new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),  
                        false));  
    }  
  
    @ModelAttribute //处理数据模型  
    public void populateModel(Model model){  
        model.addAttribute("projectName","peppa");  
    }  
    //被拦截控制器出现Exception异常时,会调用该方法,该方法返回会返回exception视图  
    @ExceptionHandler(Exception.class)  
    public String exception(){  
        return "exception";  
    }  
}  
  • @ControllerAdvice已经标记了@Component,它的属性packages则是指定拦截的控制器,然后通过注解@InitBinder可以获得一个参数----WebDataBinder,它是一个可以指定pojo参数属性转换的数据绑定。这里被拦截到的控制器关于日期对象的参数都会被它处理不需要我们自己制定Formatter了。
  • @ModelAttribute是关于数据模型的,它会在进入控制器方法前运行,加入一个数据模型键值对"projectName"->"peppa".
  • @ExceptionHandler作用是制定被拦截到的控制器发生异常后,如果异常匹配,就会使用该方法处理,返回视图exception去响应,这样可以避免异常页面的不友好

       也可以在控制器当中使用@InitBinder、@ExceptionHandler、@ModelAttribute,此时标注的方法只对当前控制器有效,控制器形参可以通过@ModelAttribute("参数名")获得提前保存在数据模型中的数据,拿上面的例子来说,如果一个控制器方法想获得projectName参数的值:

@RequestMapping(value="getProjectName")  
public String getProjectName(@ModelAttribute("projectName") String name){  
    System.out.println(name);//name的最终值为peppa  
}  

处理异常

        控制器的通知注解@ExceptionHandler可以处理异常,此外,spring mvc还提供了其他的异常处理机制,使用它们可以获取更为精确的信息,从而为定位问题带来方便。在默认情况下,spring会将自身产生的异常转换为合适的状态码,通过这些状态码可以进一步确定异常发生的原因,以便找到对应的问题。

 spring中部分异常默认映射码

BindException400 - Bad Request
ConversionNotSupportedException500 - Internal Server Error
HttpMediaTypeNotAcceptableException406 - Not Acceptable
HttpMediaTypeNotSupportedException415 - Unsupported Media Type
HttpMessageNotReadableException400 - Bad Request
HttpMessageNotWritableException500 - Internal Server Error
HttpRequestMethodNotSupportedException405 - Method Not Allowed
MethodArgumentNotValidException400 - Bad Request
MissingServletRequestParameterException400 - Bad Request
MissingServletRequesPartException400 - Bad Request
NoSuchRequestHandlingMethodException404 - Not Found
TypeMismatchException400 - Bad Request

有时候可以自定义一些异常,比如定义一个找不到角色异常

@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "找不到角色信息异常")  
public class RoleException extends RuntimeException {  
    // ...  
}  

 通过注解@ResponseStatus将异常映射为某一种状态码,通过配置reason可以了解配置产生异常的原因。

  • 处理方式一:通过配置专门的错误页(可以在web.xml中使用<error-page>标签进行配置)进行处理 
<web-app>  
    <error-page>  
        <error-code>404</error-code>  
        <location>/404.html</location>  
    </error-page>  
</web-app>  
  • 处理方式二: 在Controller中添加一个或多个用于处理异常的方法并在方法上用@ExceptionHandler加以注解,并指明该方法可以处理的异常类型,该方法可以返回错误视图的视图名或者返回ModelAndView对象
    @Controller  
    public class RoleController {  
        //当前控制器发生RoleException异常时,进入该方法  
        @ExceptionHandler(RoleException.class)  
        public String handleRoleException(Model model, RoleException ex) {  
            model.addAttribute("hint", ex.getMessage());  
            //返回指定的页面,避免不友好  
            return "error";  
        }  
    }  

  • 处理方式三:多个控制器有公共的异常需要统一处理,那么可以通过@ControllerAdvice为控制器写一个处理异常的Advice
    @ControllerAdvice  
    public class ControllerExceptionAdvice {  
        @ExceptionHandler(RoleException.class)  
        public ModelAndView handleRE(Model model, RoleException ex) {  
            ModelAndView mav = new ModelAndView("error");  
            mav.addObject("hint", ex.getMessage());  
            return mav;  
        }  
    }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值