Reputation: 965
Is there any annotation similar to @PreAuthorize
or @PreFilter
that I can use to run code before a method in the Controller is invoked?
I need to add info to the request context (specific to the method being called) to be then retrieved by the ExceptionHandler
.
For example
@RestController
public MyController{
@UnkwonwAnnotation("prepareContext(request.getAgentId())"){
public ResponseEntity method1(RequestA requestA) {
...
}
@UnkwonwAnnotation("prepareContext(request.getUserName())"){
public ResponseEntity method1(RequestB requestB) {
...
}
}
I could actually just use @PreAuthorize
but doesn't feel right
Upvotes: 11
Views: 28787
Reputation: 407
A good option is to implement a custom filter that runs every time a request is received.
You need to extend "OncePerRequestFilter" and override the method "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.
}
}
You have to register the filter in Spring with FilterRegistrationBean. If you have Spring Security, you need add your filter after security filter.
Upvotes: 5
Reputation: 11115
You Can add interceptor for this
Sample Interceptor
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response) {
//Add Login here
return true;
}
}
Configuration
@Configuration
public class MyConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyCustomInterceptor()).addPathPatterns("/**");
}
}
Hope this helps
Upvotes: 14
Reputation: 965
Expanding on Sai Prateek answer, I'v created a custom annotation:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationContext {
String clientId();
String userId();
String operation();
}
and a component to handle it:
@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);
}
}
I then annotate the controller methods providing the required parameters:
@RestController
public class MyController {
@OperationContext(clientId = '#request.getClientId', userId = '#request.getUserId', operation = "OPERATION_A")
public ResponseEntity aMethod(MyRequest request) {
...
}
}
Upvotes: 5
Reputation: 11926
Spring Aspect is also a good option to execute code before controller.
@Component
@Aspect
public class TestAspect {
@Before("execution(* com.test.myMethod(..)))")
public void doSomethingBefore(JoinPoint jp) throws Exception {
//code
}
}
Here myMethod()
will execute before controller.
Upvotes: 7