开发知识

基于注解的Controller接口这些高级功能,你都知道吗?

来源: Spring全家桶实战案例源码  日期:2024-04-29 20:46:35  点击:19  属于:开发知识

环境:SpringBoot2.7.18

1. 简介

基于注解的Controller接口,你可以使用 @RequestMapping 注解将请求映射到控制器方法。它有多种属性,可根据 URL、HTTP 方法、请求参数、头和媒体类型进行匹配。该注解可以在类上使用它来表达共享映射,也可以在方法级使用它来缩小特定接口映射的范围。

@RequestMapping 还有 HTTP 方法特定的快捷方式变体:

  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping

通过上面的注解,我们能更加具体的去匹配我们的Controller接口方法。这些注解在开发中都是些基本的操作,并且在绝大多数情况下使用这些接口完全够用了。接下来将介绍几个高级用法。

2. 实战案例

2.1 HEAD、OPTIONS请求

对于head,options请求Spring并没有提供对应的快捷注解,我们只能通过@RequestMapping注解来指定method属性。

@GetMapping (和 @RequestMapping(method=HttpMethod.GET))支持 HTTP HEAD 透明请求映射。控制器方法无需更改。在 javax.servlet.http.HttpServlet 中应用的响应封装器可确保 Content-Length 标头被设置为写入的字节数(而不会实际写入响应)。如下示例:

@GetMapping("/h")
public Object h() {
  System.out.println("header....") ;
  return "h method..." ;
}

当上面的接口以head方式请求时,也是可以成功进入该方法的只是并不会输出内容到客户端,而仅仅是通过Content-Leng告知有多少个字节内容。

图片图片

响应header中有Content-Length

图片图片

对应HEAD请求我们完全可以通过GET方式来解决。

默认情况下,HTTP OPTIONS 的处理方式是将 Allow 响应头设置为具有匹配 URL 模式的所有 @RequestMapping 方法中列出的 HTTP 方法列表。简单说当你通过OPTIONS请求一个URL时,Allow的响应头会设置为你@RequestMapping(method = ...)这里你method设置的列表+OPTIONS,如下示例:

@RequestMapping(value = "/o", method = {RequestMethod.DELETE, RequestMethod.HEAD})
public Object o() {
  System.out.println("o....") ;
  return "h method..." ;
}

当上面的接口通过OPTIONS请求时,那么响应header Allow将设置为如下:

图片图片

如果你的@RequestMapping没有指定method属性值,那么Allow 头信息会被设置为 GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS。上面的即可删除method属性再次请求如下:

图片图片

2.2 自定义请求注解

在某些场景下你可能需要自定义自己的一些注解来配置通用的匹配模式,那么这时候通过自定义请求注解的方式是非常合适的,而不用你对每一个请求都去做重复的事。

自定义请求注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping
public @interface PackMapping {


 @AliasFor(annotation = RequestMapping.class)
 String name() default "";
 @AliasFor(annotation = RequestMapping.class)
 String[] value() default {};
 @AliasFor(annotation = RequestMapping.class)
 // 配置只能是GET或POST方法
 RequestMethod[] method() default {RequestMethod.GET, RequestMethod.POST} ;
 @AliasFor(annotation = RequestMapping.class)
 String[] path() default {};
 @AliasFor(annotation = RequestMapping.class)
 String[] params() default {};
 // 设置请求header必须包含X-API-Version并且值必须是v1
 @AliasFor(annotation = RequestMapping.class)
 String[] headers() default {"X-API-Versinotallow=v1"};
 @AliasFor(annotation = RequestMapping.class)
 String[] consumes() default {};
 @AliasFor(annotation = RequestMapping.class)
 String[] produces() default {};
}

测试Controller接口

@PackMapping("/v")
public Object v() {
  System.out.println("自定义请求注解....") ;
  return "PackMapping method..." ;
}

输出结果

图片图片

请求中必须携带X-API-Version请求header。

2.3 动态显示注册接口

你可以通过编程方式注册处理程序方法,这些方法可以用于动态注册或高级情况,例如不同URL下的同一处理程序的不同实例,如下示例:

@Configuration
public class CustomWebConfig {


  @Autowired
  public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserService handler)
      throws NoSuchMethodException {
    BuilderConfiguration options = new BuilderConfiguration() ;
    options.setPatternParser(new PathPatternParser()) ;
    RequestMappingInfo info = RequestMappingInfo.paths("/api/user/{id}").methods(RequestMethod.GET).options(options ).build();
    Method method = UserHandler.class.getMethod("getUser", Integer.class) ;
    mapping.registerMapping(info, handler, method);
  }
}

UserService

@Component
public class UserHandler {
  
  @ResponseBody
  public User getUser(@PathVairable("id")Integer id) {
    User user = new User() ;
    user.setId(id) ;
    user.setName("张三") ;
    return user ;
  }
}

输出结果

图片图片

以上是本篇文章的全部内容,如对你有帮助就请作者吃个棒棒糖