sirve - spring mvc formulario ejemplo
¿Es posible conectar un Interceptor Spring MVC usando anotaciones? (5)
¿Es posible conectar un interceptor Spring MVC utilizando anotaciones y, de ser así, podría alguien proporcionarme un ejemplo de cómo hacerlo?
Por cable a través de una anotación me refiero a hacer tan poco en la configuración XML como sea posible. Por ejemplo, en este archivo de configuración que encontré en http://www.vaannila.com/spring/spring-interceptors.html ;
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:interceptors-ref="loggerInterceptor" />
<bean id="loggerInterceptor" class="com.vaannila.interceptor.LoggerInterceptor" />
¿Cuánta configuración podría escaparse allí? Me imagino que @Autowired
eliminaría la necesidad de declarar explícitamente el bean en la línea 2, pero ¿sería posible deshacerse de la línea 1 con una anotación también?
Hasta donde yo sé, no hay formas de configurar interceptores Spring MVC sin XML en absoluto.
Sin embargo, hay algunas simplificaciones con el espacio de nombres mvc
en las últimas versiones de Spring 3.0.x (¡no en Spring 3.0.0!):
<mvc:interceptors>
<bean class="com.vaannila.interceptor.LoggerInterceptor" />
</mvc:interceptors>
Ver también:
Implementé una solución de trabajo usando una anotación @Interceptor
personalizada en el espíritu de la anotación @Controller
de Spring:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Component
public @interface Interceptor {
String[] pathPatterns() default {};
String[] excludePathPatterns() default {};
}
Esta anotación debe aplicarse a los tipos de HandlerInterceptor
así:
@Interceptor
public class BuildTimestampInterceptor extends HandlerInterceptorAdapter {
private final String buildTimestamp;
public BuildTimestampInterceptor(@Value("${build.timestamp}") String buildTimestamp) {
this.buildTimestamp = buildTimestamp;
}
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
req.setAttribute("buildTimestamp", buildTimestamp);
return true;
}
}
Finalmente, la clase de procesador, InterceptorProcessor
, es un bean de Spring que extiende WebMvcConfigurerAdapter
e implementa BeanPostProcessor
para buscar las anotaciones @Interceptor
personalizadas y registrar beans que tengan esa anotación como HandlerInterceptor
dentro del método addInterceptors
reemplazado:
@Component
public class InterceptorProcessor extends WebMvcConfigurerAdapter implements BeanPostProcessor {
private final Map<HandlerInterceptor,Interceptor> interceptors = new HashMap<>();
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
scanForInterceptorAnnotation(bean, beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String string) throws BeansException {
return bean;
}
protected void scanForInterceptorAnnotation(Object bean, String beanName) {
Optional<Interceptor> optionalInterceptor = getInterceptorAnnotation(bean.getClass());
if (optionalInterceptor.isPresent() && bean instanceof HandlerInterceptor) {
interceptors.put((HandlerInterceptor) bean, optionalInterceptor.get());
}
}
private Optional<Interceptor> getInterceptorAnnotation(Class cls) {
Annotation[] annotations = cls.getAnnotationsByType(Interceptor.class);
if (hasValue(annotations)) {
return Optional.of((Interceptor) annotations[0]);
}
return Optional.empty();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
interceptors.forEach((HandlerInterceptor key, Interceptor val) -> {
InterceptorRegistration registration = registry.addInterceptor(key);
if (hasValue(val.pathPatterns())) {
registration.addPathPatterns(val.pathPatterns());
}
if (hasValue(val.excludePathPatterns())) {
registration.excludePathPatterns(val.excludePathPatterns());
}
});
}
private static <T> boolean hasValue(T[] array) {
return array != null && array.length > 0;
}
}
Solo recuerda tener tu aplicación de primavera escaneada para este procesador Bean para que realmente registre tu @Interceptor
. Algo como:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"org.my.controller", "org.my.utils.processor"})
public class WebConfig extends WebMvcConfigurerAdapter {...
No sé sobre Spring-AOP pero si estás usando AspectJ a través de Spring puedes usar @Aspect, @Pointcut, @Advise y más ...
También hay un buen artículo sobre cómo usar estas anotaciones con Spring AOP aquí: http://java-x.blogspot.com/2009/07/spring-aop-with-aspecj-annotations.html
Tropecé con esta pregunta mientras buscaba exactamente esto. Finalmente descubrí que funciona en Spring 3.1 usando @EnableWebMVC junto con WebMvcConfigurerAdapter.
Ejemplo simple:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="webapp.base.package")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggerInterceptor());
}
}
como las respuestas de Markus Kreusch, también podría funcionar así
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="webapp.base.package")
public class WebApplicationConfig extends WebMvcConfigurerAdapter {
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping RequestMappingHandlerMapping= super.requestMappingHandlerMapping();
Object[] interceptors = new Object[1];
interceptors[0] = new RoleInterceptor();
RequestMappingHandlerMapping.setInterceptors(interceptors);
return RequestMappingHandlerMapping;
}
}