Spring - 在调用控制器方法之前执行代码

alg*_*gia 6 java spring

在调用控制器中的方法之前,是否有任何类似于@PreAuthorize@PreFilter我可以用来运行代码的注释?

我需要将信息添加到请求上下文(特定于被调用的方法),然后由 ExceptionHandler.

例如

@RestController
public MyController{

  @UnkwonwAnnotation("prepareContext(request.getAgentId())"){
  public ResponseEntity method1(RequestA requestA) {
    ...
  }

  @UnkwonwAnnotation("prepareContext(request.getUserName())"){
  public ResponseEntity method1(RequestB requestB) {
    ...
  }

}
Run Code Online (Sandbox Code Playgroud)

我实际上可以使用@PreAuthorize但感觉不对

Nir*_*ane 10

您可以为此添加拦截器

样本拦截器

Public class CustomInterceptor implements HandlerInterceptor{


    @Override
    public boolean preHandle(HttpServletRequest request,HttpServletResponse  response){
    //Add Login here 
        return true;
    }
} 
Run Code Online (Sandbox Code Playgroud)

配置

@Configuration
public class MyConfig extends WebMvcConfigurerAdapter{
    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(new MyCustomInterceptor()).addPathPatterns("/**");
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助


Sai*_*eek 7

Spring Aspect 也是在控制器之前执行代码的一个不错的选择。

@Component
@Aspect
public class TestAspect {

    @Before("execution(* com.test.myMethod(..)))")
    public void doSomethingBefore(JoinPoint jp) throws Exception {

        //code  
    }
}
Run Code Online (Sandbox Code Playgroud)

这里myMethod()将在控制器之前执行。


Jos*_*yAB 5

也许一个不错的选择是实现一个自定义过滤器,该过滤器在每次收到请求时运行。

您需要扩展“OncePerRequestFilter”并覆盖方法“doFilterInternal”

public class CustomFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        //Add attributes to request
        request.getSession().setAttribute("attrName", new String("myValue"));

        // Run the method requested by petition
        filterChain.doFilter(request, response);

        //Do something after method runs if you need.

    }
}
Run Code Online (Sandbox Code Playgroud)

之后您必须使用 FilterRegistrationBean 在 Spring 中注册过滤器。如果您有 Spring security,则需要在安全过滤器之后添加过滤器。


alg*_*gia 5

扩展 Sai Prateek 的答案,我创建了一个自定义注释:

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

  String clientId();

  String userId();

  String operation();
}
Run Code Online (Sandbox Code Playgroud)

和一个处理它的组件:

@Aspect
@Component
public class OperationContextAspect {

  @Before(value = "@annotation(operationContext)", argNames = "operationContext")
  public void preHandle(OperationContext operationContext) {

    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

    requestAttributes.setAttribute("operation", operationContext.operation, RequestAttributes.SCOPE_REQUEST);
    requestAttributes.setAttribute("clientId", operationContext.clientId(), RequestAttributes.SCOPE_REQUEST);
    requestAttributes.setAttribute("userId", operationContext.userId(), RequestAttributes.SCOPE_REQUEST);

  }
}
Run Code Online (Sandbox Code Playgroud)

然后,我注释控制器方法,提供所需的参数:

@RestController
public class MyController {

  @OperationContext(clientId = '#request.getClientId', userId = '#request.getUserId', operation = "OPERATION_A")
  public ResponseEntity aMethod(MyRequest request) {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)