Spring-MVC web 实现http 请求的三种方式

文章目录

  • 前言
  • 一、mvc 处理http 的请求流程:
  • 二、web端处理http 的三种方式
    • 2.1 使用 @RequestMapping和 @RestController
    • 2.2 实现Controller 接口/实现HttpRequestHandler接口:
      • 2.2.1 实现Controller 接口:
      • 2.2.2 实现HttpRequestHandler接口:
    • 2.3 定义RouterFunction 类型的bean:
  • 总结


前言

对于web http 请求我们在项目里常用的就是@Controller/@RestController 定义类,并且通过@RequestMapping 定义控制器的路径,除了常见的这种web 请求,实际上在mvc 层面还提供了另外两种的路由方式。


一、mvc 处理http 的请求流程:

  • 用户发送 HTTP 请求到服务器;
  • 前端控制器(DispatcherServlet)接收到请求,它是整个流程的入口点;
  • DispatcherServlet 根据 URL 映射找到对应的处理器 HandlerMapping(Handler)来处理请求;
  • 通过HandlerMapping 找到对应的HandlerAdapter 来解析请求参数,然后完成请求的调用 获得返回结果;
  • 根据返沪结果获取到对应的 HttpMessageConverter 将请求结果进行转换浏览器需要的类型;
  • 判断结果是否是json 字符串如果是则将结果写回到浏览器;
  • 如果是字符串,则进行转发或者页面的渲染将页面返回给浏览器;

二、web端处理http 的三种方式

2.1 使用 @RequestMapping和 @RestController

这个是我们最常使用的只需要 ,在类上声明 @RestController/@Controller 注解,spring 在启动时就可以帮我们将这个类生成bean 对象放入到容器中;通过在方法上 定义 @RequestMapping 就可以被RequestMappingHandlerMapping 的bean 的后置处理方法afterPropertiesSet 去扫描解析加了 @RequestMapping 方法的注解;

@RestController
public class UserController {
@GetMapping("/{id}/{name}")
@ResponseBody
 public String testGet(HttpServletRequest request, @PathVariable("name") String name, @PathVariable("id") String id) {
     System.out.println("name = " + name);
     System.out.println("id = " + id);
     return "success";
 }


 @PostMapping("post")
 @ResponseBody
 public String testPost1(@RequestBody Map map) {
     System.out.println("map = " + map);
     return "success";
 }
} 

此时客户端发起http 请求后,通过请求的路径吗,进行筛选得到 RequestMappingHandlerMapping 然后进行请求的处理;

2.2 实现Controller 接口/实现HttpRequestHandler接口:

这两种方式主要通过BeanNameUrlHandlerMapping 的 父类AbstractDetectingUrlHandlerMapping 中的initApplicationContext 方法来扫描所有 以 以"/" 开头 的bean ,服务端当接收到请求时通过筛选发现是BeanNameUrlHandlerMapping 来处理请求,则直接调用业务中我们自己实现的handleRequest 方法;

2.2.1 实现Controller 接口:

我们在声明bean 名字的时候可以 以"/" 开头并且实现Controller 接口 重写ModelAndView 方法来处理请求

@Component("/beanNameController")
public class BeanNameController implements Controller{

    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView  modelAndView = new ModelAndView();
        Map<String,Object> oneMap = new HashMap<>();
        oneMap.put("name","lisi");
        modelAndView.addObject("data",oneMap);
        modelAndView.setViewName(null);
        System.out.println("bean name 调用");
        return modelAndView;
    }

}

需要注意的是该方法返回的是一个ModelAndView 对象,web端会对ModelAndView 进行页面渲染后返回,此时无法返回json 格式的数据;

2.2.2 实现HttpRequestHandler接口:

我们在声明bean 名字的时候可以 以"/" 开头并且实现HttpRequestHandler 接口 重写handleRequest方法来处理请求

@Component("/beanNameControllerhttp")
public class BeanNameControllerForHttp implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("bean name http 调用");
    }


}

需要注意的是该方法没有返回值;

2.3 定义RouterFunction 类型的bean:

此种适应于WebFlux ,如果我们在gateWay 网关想要处理http 请求,因为gateWay 使用了WebFlux 并没有使用传统的Spring MVC 所以此时就需要通过定义RouterFunction 类型的bean来实现;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.http.MediaType.TEXT_PLAIN;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;

/**
 * Spring MVC 和 WebFlux 冲突
 */
@Configuration
public class RoutingConfig {
    @Bean
    public RouterFunction<ServerResponse> route(DemoHandler handler) {
        return RouterFunctions
                .route(GET("/handle").and(RequestPredicates.accept(TEXT_PLAIN)),handler::handle)
                .andRoute(POST("/echo"), handler::echo)
                .andRoute(GET("/hello"), handler::hello);
    }
}

import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

@Component
public class DemoHandler  implements HandlerFunction<ServerResponse> {

    public Mono<ServerResponse> hello(ServerRequest request) {
        return ServerResponse.ok().bodyValue("Hello, World!");
    }

    public Mono<ServerResponse> echo(ServerRequest request) {
        return request.bodyToMono(String.class)
                .flatMap(body -> ServerResponse.ok().bodyValue("Echo: " + body));
    }


    @Override
    public Mono<ServerResponse> handle(ServerRequest request) {
        return ServerResponse.ok().bodyValue("Hello, handle!");
    }
}


RouterFunction 主要通过RouterFunctionMapping 类中的afterPropertiesSet 方法来扫描spring 所有的RouterFunction 类型的bean 并进行解析,服务端接收到请求后 发现需要 RouterFunctionMapping 来处理 则通过在遍历其绑定的方法,获取到方法后完成调用;


总结

本文介绍了使用Spring-MVC web端处理http 的三中方法,可以根据不同的场景进行使用。

你可能感兴趣的:(Spring框架篇,java工具篇,web前端,spring,mvc,前端)