想象一下,我们有一个像这样的控制器:
@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 */
}
}
问题是,如何以与@ExceptionHandler
类似的方式为此特定控制器实现一些常见的预处理?例如。我想在控制器中有一个方法,它在处理程序方法之前接收请求,但只请求这个特定的控制器。
我知道RequestBodyAdvice
和ResponseBodyAdvice
接口,但想要控制器本地的东西。
作为一个用法示例 - 我希望在每个处理程序之前对常见的parameter
变量进行一些验证。
答案 0 :(得分:2)
以上所有内容中缺少的内容回答了如何为特定控制器注册拦截器,可以通过以下操作完成:
@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/*");
}
}
在XML中,相同:
<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>
答案 1 :(得分:1)
您需要自己编写HandlerInterceptor
。您可以通过扩展HandlerInterceptorAdapter
轻松完成。然后,您可以覆盖preHandle()
和/或postHandle()
。
在preHandle()
确定合适后,在
HandlerMapping
会被调用 handler对象,但在HandlerAdapter
调用处理程序之前。postHandle()
实际调用之后调用
HandlerAdapter
处理程序,但在DispatcherServlet
呈现视图之前。
您可以使用getRequestURI()
的{{1}}方法为HttpServletRequest
中的不同处理程序添加逻辑。
示例:
preHandle()
然后在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;
}
}
。
HandlerInterceptor
dispatcher-servlet.xml
您可以将其配置为更具体网址。请参阅Spring Reference的22.16.5 Interceptors部分。
答案 2 :(得分:0)
使用HandlerInterceptorAdapter
拦截控制器执行前后,记录执行时间的开始和结束,将其保存到现有拦截控制器的modelAndView中以供日后显示。
public class ExecuteTimeInterceptor extends HandlerInterceptorAdapter{
private static final Logger logger = Logger.getLogger(ExecuteTimeInterceptor.class);
//before the actual handler will be executed
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler)
throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
return true;
}
//after the handler is executed
public void postHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView)
throws Exception {
long startTime = (Long)request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
//modified the exisitng modelAndView
modelAndView.addObject("executeTime",executeTime);
//log it
if(logger.isDebugEnabled()){
logger.debug("[" + handler + "] executeTime : " + executeTime + "ms");
}
}
更多示例 - http://www.mkyong.com/spring-mvc/spring-mvc-handler-interceptors-example/
答案 3 :(得分:0)
虽然HandlerInterceptorAdapter
似乎是“正确”的解决方案,
它似乎不是你想要的解决方案。
以下代码可能是您想要的解决方案 (或者至少是你在问题中要求的那个)。
摘要:编写您自己的preBlam
和postBlam
方法。
一些代码:
@RestController
@RequestMapping("/{parameter}")
public class MyController
{
@ExceptionHandler(SomeException.class)
public Object handleSomeException()
{
/* handle */
}
@RequestMapping("/something")
public Object handleSomething(@PathVariable("parameter") String parameter)
{
preBlam(desired params here);
/* handle */
postBlam(desired params here);
}
@RequestMapping("/somethingElse")
public Object handleSomethingElse(@PathVariable("parameter") String parameter)
{
preBlam(desired params here);
/* handle */
postBlam(desired params here);
}
private blam preBlam(parameters)
{
// do initial blamish work
}
private blam postBlam(parameters)
{
// do post blamish work here
}
}
另一种选择: 使用AOP为受影响的方法设置前处理程序和后处理程序。 我不是一个很大的AOP用户,所以我不能只是滔滔不绝地说出一个例子。
答案 4 :(得分:0)
由于您希望以常用方式处理路径变量,请考虑引入模型对象。有了这个,您可以验证属性(java bean验证),还可以混合路径变量和查询参数(这里是一个非常简单的示例,您甚至可以创建自定义验证):
@Data
class SomeModel {
@NotEmpty
private String parameter;
}
在控制器中,您只需将模型添加为参数:
@RequestMapping("/something")
public Object handleSomething(@Valid SomeModel model) {
/* handle using model.getParameter() */
}