Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC @Controller to intercept own requests

Imagine we have a controller like this:

@RestController
@RequestMapping("/{parameter}")
public class MyController {

    @ExceptionHandler(SomeException.class)
    public Object handleSomeException() { /* handle */ }

    @RequestMapping("/something")
    public Object handleSomething(@PathVariable("parameter") String parameter) {
        /* handle */
    }

    @RequestMapping("/somethingElse")
    public Object handleSomethingElse(@PathVariable("parameter") String parameter) {
        /* handle */
    }
}

The question is, how to implement some common pre-\post-handling for this particular controller in similar way as @ExceptionHandler is working? E.g. I want to have a method in controller which receives request prior to handler methods, but only requests for this particular controller.

I'm aware of RequestBodyAdvice and ResponseBodyAdvice interfaces, but want something local to controller.

As a usage example - I want to do some validation for common parameter variable before each handler.

like image 686
scorpp Avatar asked Oct 20 '25 01:10

scorpp


2 Answers

What is miss in all above answers it how to register interceptor for specific controller, which can be done as follows:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LocaleChangeInterceptor());
        registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
        registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
    }
}

In XML, the same:

<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/admin/**"/>
        <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/secure/*"/>
        <bean class="org.example.SecurityInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

spring documentation

like image 74
Sylwek Avatar answered Oct 21 '25 15:10

Sylwek


You will need to write you own HandlerInterceptor. You can do it easily by extending HandlerInterceptorAdapter. And then you can override preHandle() and/or postHandle().

preHandle() is called after HandlerMapping determined an appropriate handler object, but before HandlerAdapter invokes the handler.

postHandle() is called after HandlerAdapter actually invoked the handler, but before the DispatcherServlet renders the view.

You can use the getRequestURI() method of HttpServletRequest to add logics for different handlers in preHandle().

Example:

public class ValidationInterceptor extends HandlerInterceptorAdapter {

    public static final String FOO_URL = "foo";
    public static final String BAR_URL = "bar";

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        String uri = request.getRequestURI();

        if (FOO_URL.equals(uri)) {        
            // for example - validation failed
            response.sendRedirect("/to/some/url");
            return false;
        } else if (BAR_URL.equals(uri)) {
            // for example - validation successful
        }
        return true;
    }
}

Then register this HandlerInterceptor in your dispatcher-servlet.xml.

<mvc:interceptors>
    <bean class="your.package.ValidationInterceptor"/>
</mvc:interceptors>

You can configure this to be more url-specific. See 22.16.5 Interceptors section of Spring Reference.

like image 33
Minar Mahmud Avatar answered Oct 21 '25 14:10

Minar Mahmud