Spring Boot --- Spring MVC: Controller控制


Spring Boot中的Controller是对Java Web中的Servlet进行封装处理.等同于Struts 2中的Action.
在对Conroller的处理上,主要分为
- 过滤器(Filter)
- 拦截器(Interceptor)
- 监听器(Listener)
- Spring Boot提供的其他工具类.

功能上, 过滤器,拦截器,监听器所能做的功能,彼此都能相互替代.而仅仅以设计模式的角度分析:
- 过滤器: 将请求中符合要求的东西挑选出来.
- 拦截器: 干涉流程的进展, 甚至终止它进行
- 监听器: 获得请求中的详细信息,但不干预这个请求.

过滤器(Filter)

基本过滤器

过滤器的顶级接口为:javax.servlet.Filter, 通过实现这个接口可以创建一个最基本的Filter Bean.然后通过@WebFilter将这个Filter Bean加入过滤器列表. 这是最基本的过滤器的实现.

@Configuration
@WebFilter
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter doFilter");
    }

    @Override
    public void destroy() {
        System.out.println("MyFilter destroy");
    }
}

其他过滤器实现类

OncePerRequestFilter

这个过滤器的实现类,可以保证每次请求,只调用一次该过滤器.
为了兼容各种不同的运行环境和版本,Filter继承OncePerRequestFilter是一个比较稳妥的选择。

因为Servlet不同版本的表现不同.在servlet-2.3中,Filter会过滤一切请求,包括服务器内部使用forward转发请求.
到了servlet-2.4中Filter默认下只拦截外部提交的请求,forward和include这些内部转发都不会被过滤,但是有时候我们需要 forward的时候也用到Filter.

配置过滤器列表

通过注解配置过滤器

  • @WebFilter
    Filter Bean添加@WebFilter即可将该Filter加入过滤器列表
属性 类型 是否必须 说明
filterName String 过滤器名,
默认为类名
urlPatterns String[] 过滤地址匹配式,
默认/*
未实际使用过
asyncSupported boolean 指定Filter是否支持异步模式
默认false
dispatcherTypes DispatcherType[] 指定Filter对哪种方式的请求进行过滤。
支持的属性:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST;
默认过滤所有方式的请求
initParams WebInitParam[] 配置参数
displayName String Filter显示名
servletNames String[] 指定对哪些Servlet进行过滤

- @Order
Filter Bean添加@Order可配置Filter的顺序

属性 说明
value Filter Bean顺序,值越小越靠前

拦截器(Interceptor)

实现HandlerInterceptor类,可定义一个拦截器

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 在实际的handler被执行前调用
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        return true;
    }

    /**
     * 在handler被执行后调用     
     * @param request
     * @param response
     * @param handler HandlerMethod实现类
     * @param modelAndView
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    }

    /**
     * 当request处理完成后调用
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    }
}

配置拦截器列表

Spring Boot 2.0中,WebMvcConfigurerAdapter类被标记废弃,可使用WebMvcConfigurationSupport添加拦截器列表

@Configuration
public class MyWebMvcConfigureAdapter extends WebMvcConfigurationSupport{

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        super.addInterceptors(registry);

        registry.addInterceptor(new MyInterceptor())  
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/login")
                .order(1);

        registry.addInterceptor(new MyInterceptor2())  
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/login")
                .order(10)
    }
}

监听器(Listener)

监听器负责监听容器生命周期的创建与销毁,包括ServletContext,SessionContext, RequestContext等.

Context

ServletContextListener

Servlet容器生命周期的监听器.

@Log4j2
@Configuration
@WebListener
public class MyListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

SessionContextListener

Session生命周期的监听器

@Log4j2
@Configuration
@WebListener
public class MyListener implements SessionListener {

    @Override
    public void sessionEvent(SessionEvent sessionEvent) {
        Session session = sessionEvent.getSession();
    }
}

RequestContextListener

Http Request 生命周期的监听器


@Log4j2
@Configuration
@WebListener
public class MyListener extends RequestContextListener {
    @Override
    public void requestInitialized(ServletRequestEvent requestEvent) {
        super.requestInitialized(requestEvent);

    }

    @Override
    public void requestDestroyed(ServletRequestEvent requestEvent) {
        super.requestDestroyed(requestEvent);
    }
}

配置

@WebListener

Sprring提供的Controller控制

@ControllerAdvice

Spring 3.2提供的新注解,大体意思为Controller增强器.
可将一个类声明为Controller Advice.
默认情况下,注解了ControllerAdvice,作用域是全部声明了@RequestMapper注解的Controller类.

属性 类型 是否必须 说明
value() String[] 作用域包地址
basePackages String[] 同上
basePackageClasses Class[] 作用域的类,实际测试为该类所在的包全部有效
assignableTypes Class[]
annotations Class[]

Controller Advice类可使用以下注解
- @ExceptionHandler: 该注解声明的方法,将作为@ControllerAdvice作用域中Controller抛出异常时的处理方法.
- @ModelAttribute: 该注解声明的方法返回值,可在@ControllerAdvice作用域中作为Controller的参数.
- @InitBinder:

这三个注解可用于所有Controller类,当声明在Controller类时,则仅对该Controller方法有效

@ExceptionHandler

声明一个统一处理Controller抛出异常的方法

  • 该注解声明一个处理异常的方法
    @ExceptionHandler
    public void exceptionHandler(HttpServletRequest request, HttpServletResponse response,Exception e) throws IOException {
        // 异常处理逻辑
    }
  • 指明处理何种异常
    @ExceptionHandler(value = ServletException.class)
    public void exceptionHandler(HttpServletRequest request, HttpServletResponse response,ServletException e) throws IOException {
        // 异常处理逻辑
    }

参数

@ExceptionHandler声明的方法,参数可以是以下任意类型
- HttpServletRequestServletRequest
- HttpServletResponseServletResponse
- Exception: 可以是@ExceptionHandler.value声明的异常类或其父类(或其公共父类)

返回值

  • 空返回值
    @ExceptionHandler声明的方法,返回值可以为void,由response对象写入返回值
    @ExceptionHandler
    public void exceptionHandler(HttpServletRequest request, HttpServletResponse response,Exception e) throws IOException {
        response.setStatus(500);
        response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        response.getWriter().write(e.getMessage());
    }
  • 根据注解定义返回值
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = Exception.class)
    public MyResult exceptionHandler(Exception e) throws IOException {
        // 异常处理逻辑
        return new MyResult(e.getMessage());
    }
  • 返回ResponseEntity<T>对象
    可通过自定义ResponseEntity对象对返回值进行设置
    @ExceptionHandler(Exception.class)
    public ResponseEntity<MyError> handlerException(Exception e) {
        log.error("发生异常:{}", e);
        ResponseEntity<MyError> responseEntity = ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(new MyError("A01",e.getMessage()));
        return responseEntity;
    }

@ModelAttribute

@ModelAttribute声明的方法,将为ControllerAdvice作用于下的所有Controller添加通用对象.

    @ModelAttribute
    public MyResult newUser(){
        return new MyResult("1111");
    }
    @GetMapping("/1")
    public String say(MyResult myResult){
        System.out.println(myResult);
        return myResult.getMessage();
    }

@InitBinder

自定义参数解析 – HandlerMethodArgumentResolver

public interface HandlerMethodArgumentResolver {
    /**
     * 是否执行resolveArgument
     * @param methodParameter
     * @return
    */
    boolean supportsParameter(MethodParameter var1);

    /**
     * 读取request并取得参数.
     * 返回的参数将会创配到同Class下的Controller方法参数中
     *
     * @param methodParameter
     * @param modelAndViewContainer
     * @param nativeWebRequest
     * @param webDataBinderFactory
     * @return
     * @throws Exception
    */
    @Nullable
    Object resolveArgument(MethodParameter var1, @Nullable ModelAndViewContainer var2, NativeWebRequest var3, @Nullable WebDataBinderFactory var4) throws Exception;
}
  • HandlerMethodArgumentResolver的实现类,不是通过Spring Bean生效,而是要通过WebMvcConfigurationSupport类进行配置.

@Configuration
public class MyWebMvcConfigurationSupport extends WebMvcConfigurationSupport {

    @Override
    protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        super.addArgumentResolvers(argumentResolvers);
        argumentResolvers.add(new MyHandlerMethodArgumentResolver());
    }
}

HandlerMethodArgumentResolver@ModelAttribute

HandlerMethodArgumentResolver@ModelAttribute都可以对Controller的请求数据进行装配.而他们两者之间的区别在于:
1. HandlerMethodArgumentResolver可获得MethodParameter对象.再加上Request对象,可对请求进行更加细粒化的判断.所以一般用于特例性的自定义参数装配.
2. @ModelAttribute方法中只能取得Request对象,他的作用域是基于ControllerAdvice当前Controller的.所以一般用于全局或通用参数的自定义装配.

自定义返回值处理 – HandlerMethodReturnValueHandler

public interface HandlerMethodReturnValueHandler {
    /**
     * 是否执行handleReturnValue
     * @param MethodParameter
     * @return
    */
    boolean supportsReturnType(MethodParameter var1);

    /**
     *
    */
    void handleReturnValue(@Nullable Object var1, MethodParameter var2, ModelAndViewContainer var3, NativeWebRequest var4) throws Exception;
}

在handleReturnValue方法体中可用的方法:

//该方法执行后不执行后续HandlerMethodReturnValueHandler类方法
modelAndViewContainer.setRequestHandled(true);
//取得Request
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
//取得Response
HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
  • 基本用法同上
  • 创建了HandlerMethodReturnValueHandler类后,也需要将其注册.可通过WebMvcConfigurationSupport.addReturnValueHandlers方法注册.
  • Spring MVC中,已注册了许多Handler.而自定义返回值处理,与自定义参数装配不同的是:当HandlerMethodReturnValueHandler列表中已有符合该请求的返回值处理器,处理返回值后将不再查找排在后面的返回值处理器.所以注册HandlerMethodReturnValueHandler还需要考虑列表顺序.
  • 处理JSON数据返回值,需要将其加入在RequestResponseBodyMethodProcessor返回其之前.

猜你喜欢

转载自blog.csdn.net/d292222100/article/details/81904932