使用自定义注释在方法级别中添加前缀或后缀在方法级别中删除控制器-Spring Rest Controller

发布于 2025-02-10 12:58:32 字数 1091 浏览 2 评论 0原文

我试图在控制器的方法级别上在get,post,put,删除映射的基础上添加一个前缀或后缀。

控制器类

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

,因此,基本上,上述请求URL应该是: http:// localhost:8080/sosings/some/some/path/path/

现在,我只想添加一些前缀或后缀请求URL,就像: http:// localhost:8080/themes/read/some/path/path/path/strong>或 http:// localhost:8080/sosings/some/some/some/some/path /read/额外的“/读”,需要将其作为前缀或后缀添加到请求URL中。我可以通过将其添加到putmapping值中直接做到这一点,但是我想使用 @read (例如

,更新的控制器类)

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

的注释来对其进行装饰,并且更新的请求URL将是相同的方式喜欢: http:// localhost:8080/something/read/some/path/

我找不到更好的方法。到目前为止,我只使用自定义注释添加了类级前缀。

任何人都可以帮助您满足上述要求吗? 谢谢 !!

我也很想知道是否可以实现?

I am trying to add a prefix or suffix in the controller at the method level on top of GET, POST, PUT, DELETE mappings.

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/

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. I can do this directly by adding this to the PutMapping value, but I want to decorate it somewhat using annotation like @Read

So, the updated Controller class will be like

@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/

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一桥轻雨一伞开 2025-02-17 12:58:33

使用这样的路径扩展使您的代码不太可理解。 (也许您应该阅读更多有关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);
    }

}

扩展点在这里,您可以像想要的那样更改路径。

示例:

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

响应:404

输出:

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)

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

wendment:asd

upputies appection:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: 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.properties.properties

logging.level.com.example.demo=debug

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.

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

response: 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

response: 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文