Spring REST从路由获取控制器+方法?

时间:2019-11-23 00:17:27

标签: java spring spring-boot

Spring是否有一种内置的方式可以为我提供“ / customers / a”(/ customers / {id})的RestController +方法?即进行标准的Spring路由,但是知道将调用哪个类/方法?

我正在尝试在中心位置根据路线确定该方法是否具有特定注释。用于集中请求/响应日志记录。

我可以遍历应用程序中的rest控制器并自己构建地图,但是想知道是否已经暴露了任何东西,以知道请求将发送到哪里?

谢谢。

2 个答案:

答案 0 :(得分:2)

您可以使用Spring AOP模块。而且我认为一种干净的方法(在不中断RestController端点流的情况下管理响应)可以如下。

首先添加 spring-boot-starter-aop依赖项

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

让我们看看代码。

这是我们的 ExampleRequest

import lombok.Data;

@Data
public class ExampleRequest {
    String name;
}

我们假设我们要验证请求->如果name ==“ anonymous”,我们想返回HTTP状态BAD_REQUEST。


这是我们的 TestController

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {
    @Anonymous
    @GetMapping("")
    public ResponseEntity<String> test(ExampleRequest exampleRequest, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        else return new ResponseEntity<>(HttpStatus.OK);
    }    
}

我们将作为请求的ExampleRequest和以后将使用的BindingResult作为参数传递。无论如何,如果bindingResult出现错误,我们的验证逻辑将被破坏,因此我们需要返回所需的错误!

@Anonymous 是我们的自定义批注,我们将使用该批注向我们的建议告知哪些方法,或者更好的方法-哪些类(Aspect是“代理”的整个类)想要代理

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

}  

还有我们的 TestAspect

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;

@Aspect
@Component
public class TestAspect {

    @Before(value = "@annotation(Anonymous) && args(exampleRequest, bindingResult,..)", argNames = "joinPoint,exampleRequest,bindingResult")
    public Object logExecutionTime(JoinPoint joinPoint, ExampleRequest exampleRequest, BindingResult bindingResult) throws Throwable {
        if (exampleRequest.getName().equals("anonymous")) bindingResult.rejectValue("name", "incorrect");
        return joinPoint;
    }

}   

我们要说的是:之前执行带有我们的自定义 ANONYMOUS 批注的每种方法以及这些 ARGUMENTS >执行此逻辑!

很显然,您将具有自定义的验证逻辑,因此请实施它。


正如我在上面的评论中所说,我认为您可以直接从代理类返回错误,但与此同时,我认为该示例是使用AOP的一种更简洁的方法(使用BindingResult时,端点流受到尊重,技术不会破坏模型类的其他验证。您可以在建议中使用javax验证(例如,混入建议,所有方法都可以完美运行!),我个人很喜欢这个Spring AOP模块,但不要滥用它

以供参考:https://docs.spring.io/spring/docs/2.5.x/reference/aop.html

答案 1 :(得分:1)

您可能想尝试另一种方法:

使用spring支持的面向方面的编程。创建一个方面,它将充当所有控制器的拦截器。将在实际的rest方法之前(或根据建议的类型“而不是”)调用Advice,以便您能够获得访问权限,然后将执行转发给真实的控制器。在Aspect的代码中,您可以内省要在实际控制器上调用的方法,并弄清它是否具有注释。

我已经找到了一个准确完成此操作的示例Here(您必须稍微更改切入点定义,以使该方面适用于您选择的其余控制器)。