简体   繁体   English

使用自定义注释在方法级别为控制器中的 GET、PUT、POST、DELETE 映射添加前缀或后缀 - Spring REST 控制器

[英]Add prefix or suffix to the GET,PUT,POST,DELETE mappings in controller at method level using custom annotation - Spring REST Controller

I am trying to add a prefix or suffix in the controller at the method level on top of GET, POST, PUT, DELETE mappings.我正在尝试在 GET、POST、PUT、DELETE 映射之上的方法级别的控制器中添加前缀或后缀。

Controller class控制器类

@RestController
@RequestMapping("/something")
public class SomeController {
@PutMapping("/some/path/")
public ResponseEntity<ApiResponse<String>> someMethod() {
....
}
...
}

So, basically, the above request URL should be something like : http://localhost:8080/something/some/path/所以,基本上,上面的请求 URL 应该是这样的: http://localhost:8080/something/some/path/

Now, I just want to add some prefix or suffix whatever is feasible to the request URL which will be something like : http://localhost:8080/something/read/some/path/ or http://localhost:8080/something/some/path/read/ the extra "/read" which needs to be added to the request URL as a prefix or suffix.现在,我只想为请求 URL 添加一些可行的前缀或后缀,例如: http://localhost:8080/something/read/some/path/http://localhost:8080/something /some/path/read/额外的“/read”,需要作为前缀或后缀添加到请求 URL。 I can do this directly by adding this to the PutMapping value, but I want to decorate it somewhat using annotation like @Read我可以通过将其添加到 PutMapping 值来直接执行此操作,但我想使用@Read之类的注释对其进行一些装饰

So, the updated Controller class will be like所以,更新后的 Controller 类会像

@RestController
@RequestMapping("/something")
public class SomeController {
@Read
@PutMapping("/some/path/")
public ResponseEntity<ApiResponse<String>> someMethod() {
....
}
...
}

and the same way updated request URL will be like : http://localhost:8080/something/read/some/path/同样的方式更新的请求 URL 将类似于: http://localhost:8080/something/read/some/path/

I am unable to find a better way to do this.我无法找到更好的方法来做到这一点。 Till now I have only achieved adding a class-level prefix using custom annotation.到目前为止,我只实现了使用自定义注释添加类级前缀。

Can anyone please help with the above requirement.?有人可以帮忙解决上述要求吗? Thank you !!谢谢 !!

I am also curious to know whether is achievable or not even?我也很想知道是否可以实现?

Using such way of path extension make your code less understandable.使用这种路径扩展方式会使您的代码难以理解。 (maybe you should read more about RESTful API) But spring can do almost everything you want. (也许你应该阅读更多关于 RESTful API 的内容)但是 spring 几乎可以做任何你想做的事情。

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.stream.Stream;

@SpringBootApplication
public class DemoApplication {

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Read {
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Write {
    }

    @Bean
    public WebMvcRegistrations webMvcRegistrations() {
        return new WebMvcRegistrations() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new RequestMappingHandlerMapping() {
                    @Override
                    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
                        RequestMappingInfo defaultRequestMappingInfo = super.getMappingForMethod(method, handlerType);
                        if (defaultRequestMappingInfo == null) {
                            return null;
                        }
                        String pathSuffix;
                        if (method.isAnnotationPresent(Read.class)) {
                            pathSuffix = "read";
                        } else if (method.isAnnotationPresent(Write.class)) {
                            pathSuffix = "write";
                        } else {
                            return defaultRequestMappingInfo;
                        }
                        //extend path by mutating configured request mapping info
                        RequestMappingInfo.Builder mutateBuilder = defaultRequestMappingInfo.mutate();
                        mutateBuilder.paths(
                                defaultRequestMappingInfo.getPatternValues().stream()
                                        .map(path -> path + "/" + pathSuffix)
                                        .toArray(String[]::new)
                        );
                        return mutateBuilder.build();
                    }
                };
            }
        };
    }

    @RestController
    @RequestMapping("/books")
    public static class BooksController {

        @Read
        @GetMapping("/{id}")
        public String readBook(@PathVariable("id") String bookId) {
            return bookId;
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

Extension point is here, you can change path like you want.扩展点在这里,您可以随意更改路径。

Example:例子:

request: http://localhost:8080/books/asd请求:http://localhost:8080/books/asd

response: 404回复:404

output:输出:

2022-06-27 10:49:48.671 DEBUG 8300 --- [nio-8080-exec-2] com.example.demo.DemoApplication$1$1     : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)

request: http://localhost:8080/books/asd/read请求:http://localhost:8080/books/asd/read

response: asd回复:asd

output:输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.0)

2022-06-27 10:48:53.622  INFO 8300 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 1.8.0_312 on DESKTOP with PID 8300 ()
2022-06-27 10:48:53.624 DEBUG 8300 --- [           main] com.example.demo.DemoApplication         : Running with Spring Boot v2.7.0, Spring v5.3.20
2022-06-27 10:48:53.625  INFO 8300 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to 1 default profile: "default"
2022-06-27 10:48:54.227  INFO 8300 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-06-27 10:48:54.233  INFO 8300 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-06-27 10:48:54.233  INFO 8300 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.63]
2022-06-27 10:48:54.298  INFO 8300 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-06-27 10:48:54.298  INFO 8300 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 643 ms
2022-06-27 10:48:54.473 DEBUG 8300 --- [           main] com.example.demo.DemoApplication$1$1     : 3 mappings in 'requestMappingHandlerMapping'
2022-06-27 10:48:54.536  INFO 8300 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-06-27 10:48:54.543  INFO 8300 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 1.199 seconds (JVM running for 1.827)
2022-06-27 10:49:01.196  INFO 8300 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-06-27 10:49:01.196  INFO 8300 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-06-27 10:49:01.197  INFO 8300 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
2022-06-27 10:49:01.210 DEBUG 8300 --- [nio-8080-exec-1] com.example.demo.DemoApplication$1$1     : Mapped to com.example.demo.DemoApplication$BooksController#readBook(String)

dependencies依赖关系

org.springframework.boot:spring-boot-starter-web

application.properties应用程序属性

logging.level.com.example.demo=debug

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM