Spring定义Controller接口的这些方式你肯定不知道

2023年 9月 8日 92.3k 0

环境:Springboot2.4.12

概述

当一个请求过来后Spring是如何进行处理的?下面简单的罗列下请个的过程中核心组件

SpringMVC处理的流程:

  • DispatcherServlet 所有请求的入口
  • HandlerMapping 将请求地址与处理程序关联
  • HandlerAdapter 真正处理程序,如执行上一步中对应的处理程
  • HandlerMethodArgumentResolver 对参数进行解析,这里面还涉及到很多其它东西
  • HanlderMethodReturnValueHandler 对返回值进行输出处理
  • ViewResolver 结果HandlerAdapter返回的有ModelAndView则会应用视图解析器
  • 常规Controller定义

    @RestController
    @RequestMapping("/users")
    public class UsersController {
      @GetMapping("/save")
      public Object save(Users users) {
        return users ;
      }
    }

    上面这个Controller接口是我们最常的定义方法,对于绝大多数人来说或许也就知道这样去定义Controller接口,而这种定义Controller方式基本上已经可以满足我们日常的所有操作了。接下来看看其它的定义Controller方法

    HttpRequestHandler

    @Component("/others/chrh")
    public class ControllerHttpRequestHandler implements HttpRequestHandler {
      @Override
      public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;");
        PrintWriter out = response.getWriter() ;
        out.print("你好,HttpRequestHandler") ;
        out.close() ;
      }
    }

    定义一个类实现HttpRequestHandler接口即可,注意这里注解@Component("/others/chrh")使用的以‘/’ 开头,为什么这么定义?在概述中说到HandlerMapping是用来将请求地址与处理程序关联起来,在常规中都是使用@RequestMapping定义接口请求地址,那在这里我们是不能用该注解的,但是又要让容器知道我们这个接口就必须使用'/'开头,这样就会有一个 BeanNameUrlHandlerMapping的HandlerMapping将我们这个Bean进行收集保存起来,以 /others/chrh为key,Bean对象为value保存到Map中。

    测试

    图片图片

    Controller接口

    定义一个Bean实现该即可

    @Component("/others/custom")
    public class CustomController implements Controller {
    
    
      @Override
      public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html;charset=utf8");
        PrintWriter out = response.getWriter() ;
        out.print("Controller接口") ;
        out.close() ;
        return null ;
      }
    
    
    }

    Bean的名称还是以'/' 开头,那么还是由BeanNameUrlHandlerMapping与之关联

    测试

    图片图片

    继承HttpServlet

    这里的判断依据就是你的这个Bean是否是Servlet接口类型(有没有实现Servlet接口)。

    @Component("/others/servlet")
    public class ControllerServlet extends HttpServlet {
    
    
      private static final long serialVersionUID = 1L;
    
    
      @Override
      protected void service(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf8");
        PrintWriter out = response.getWriter() ;
        out.print("你好 HttpServlet") ;
        out.close() ;
      }
    
    
    }

    这样看起来就是个标准的Servlet程序。

    如果你只是这样,那这可运行不起来,你还需要注册一个SimpleServletHandlerAdapter。

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
      @Bean
      public SimpleServletHandlerAdapter simpleServletHandlerAdapter() {
        return new SimpleServletHandlerAdapter() ;
      }
    }

    测试

    图片图片

    在这个程序中我们还可以让这个程序成为一个受应用服务管理的Servlet程序。可以将注解改成@WebServlet("/others/servlet")。只是换成这个注解还并不能生效,还需要在启动类(任何配置类上)添加@ServletComponentScan注解。

    以上就是在SpringMVC中支持的几种接口定义处理方式。

    下一篇文章会对上面几种实现的方式进行源码分析,一个请求是如何知道使用哪个HandlerMapping的,找到了HandlerMapping又是怎么确定由哪个HandlerAdapter处理的(在上面的例子中,每一种实现他们的实现方法都不一样,所以一定的需要不同的HandlerAdapter进行处理);通过源码的分析,让你知其然,知其所以然。关注我让你对Spring源码不再畏惧。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论