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

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

环境:Springboot2.4.12

概述

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

SpringMVC处理的流程:

  1. DispatcherServlet 所有请求的入口
  2. HandlerMapping 将请求地址与处理程序关联
  3. HandlerAdapter 真正处理程序,如执行上一步中对应的处理程
  4. HandlerMethodArgumentResolver 对参数进行解析,这里面还涉及到很多其它东西
  5. HanlderMethodReturnValueHandler 对返回值进行输出处理
  6. 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;charset=utf8");
    PrintWriter out = response.getWriter() ;
    out.print("<h1>你好,HttpRequestHandler</h1>") ;
    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("<h1>Controller接口</h1>") ;
    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("<h1>你好 HttpServlet</h1>") ;
    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源码不再畏惧。

责任编辑:武晓燕 来源: Spring全家桶实战案例源码
相关推荐

2018-09-02 15:43:56

Python代码编程语言

2023-11-15 08:22:42

Java开发小技巧

2021-08-30 07:49:33

索引ICP Mysql

2019-07-23 15:56:56

Spring Boot部署servlet

2019-07-23 17:52:59

Spring BootJava开发

2023-11-30 08:32:31

OpenFeign工具

2014-12-08 10:39:15

2022-07-17 06:53:24

微服务架构

2020-03-05 11:10:18

Left join数据库MySQL

2022-05-05 12:02:45

SCSS函数开发

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket浏览器

2010-08-06 13:15:35

2009-12-10 09:37:43

2011-09-15 17:10:41

2021-02-01 23:23:39

FiddlerCharlesWeb

2022-10-13 11:48:37

Web共享机制操作系统

2021-08-10 10:25:16

HTML 网络开发前端开

2018-01-26 08:26:35

RAID阵列组成

2021-10-19 14:49:49

CSS前端
点赞
收藏

51CTO技术栈公众号