Spring是否有一种内置的方式可以为我提供“ / customers / a”(/ customers / {id})的RestController +方法?即进行标准的Spring路由,但是知道将调用哪个类/方法?
我正在尝试在中心位置根据路线确定该方法是否具有特定注释。用于集中请求/响应日志记录。
我可以遍历应用程序中的rest控制器并自己构建地图,但是想知道是否已经暴露了任何东西,以知道请求将发送到哪里?
谢谢。
答案 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(您必须稍微更改切入点定义,以使该方面适用于您选择的其余控制器)。