对于web http 请求我们在项目里常用的就是@Controller/@RestController 定义类,并且通过@RequestMapping 定义控制器的路径,除了常见的这种web 请求,实际上在mvc 层面还提供了另外两种的路由方式。
这个是我们最常使用的只需要 ,在类上声明 @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 然后进行请求的处理;
这两种方式主要通过BeanNameUrlHandlerMapping 的 父类AbstractDetectingUrlHandlerMapping 中的initApplicationContext 方法来扫描所有 以 以"/" 开头
的bean ,服务端当接收到请求时通过筛选发现是BeanNameUrlHandlerMapping 来处理请求,则直接调用业务中我们自己实现的handleRequest 方法;
我们在声明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 格式的数据;
我们在声明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 调用");
}
}
需要注意的是该方法没有返回值;
此种适应于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 的三中方法,可以根据不同的场景进行使用。