java - servlet - para que sirve spring mvc
Agregue atributos al modelo de todos los controladores en Spring 3 (6)
Cada vista en mi aplicación Spring 3 tiene un conjunto de atributos en los que pueden confiar. Entonces, la primera línea de cada controlador es algo así como:
ControllerHelper.addDefaultModel(model, personManager, request);
Ahí agregaré
- objeto de usuario y nombre completo recuperado de la base de datos si la persona ha iniciado sesión
- conjunto de variables que generalmente se establecen una sola vez (por ejemplo,
imagesHost
) - conjunto de idiomas que un visitante puede cambiar a
- idioma actual
- algunas estadísticas (por ejemplo, el número total de personas en nuestro sistema)
Todo esto permite que cada vista muestre el nombre del usuario registrado, haga referencia fácilmente a la ubicación de una imagen, una lista de idiomas y algunas estadísticas generales sobre el sitio.
Entonces, la pregunta es, ¿es el objeto del modelo de controlador el mejor lugar para almacenar todos los datos o hay un lugar más conveniente que hace que sea tan fácil para las vistas acceder a esta información?
Y en segundo lugar, REALMENTE me encantaría no tener que tener la línea ControllerHelper
arriba como la primera línea en cada controlador. En realidad, no siempre es la primera línea, a veces primero compruebo si necesito redireccionar en ese controlador, porque no quiero desperdiciar recursos llenando el modelo sin ningún motivo. Tal vez un filtro o anotación o algún mecanismo de devolución de llamada de Spring podría asegurarse de que se llame al código de ControllerHelper
vez que el controlador haya finalizado, pero justo antes de que se visualice la vista, omitiendo esto si se devuelve una redirección.
Hay un problema que ocurre con la redirección cuando se usa el enfoque @ModelAttribute o HandlerInterceptor. Cuando el controlador devuelve la vista Redirigir, los atributos del modelo agregados de esta manera se anexan como parámetros de consulta.
Otra forma de manejar esta situación es crear bean con ámbito de sesión, que se pueda autoconectar en el controlador de la aplicación base, o explícitamente en cada controlador donde se necesite acceso.
Los detalles sobre los ámbitos disponibles y el uso se pueden encontrar here .
Podría usar una clase de controlador anotada con @ControllerAdvice
"@ControllerAdvice se introdujo en 3.2 para los métodos @ExceptionHandler, @ModelAttribute y @InitBinder compartidos en todos o en un subconjunto de controladores".
Para obtener más información, echa un vistazo a esta parte del video grabado durante SpringOne2GX 2014 http://www.youtube.com/watch?v=yxKJsgNYDQI&t=6m33s
Puede escribir un org.springframework.web.servlet.HandlerInterceptor
. (o su conveniente subclase HandlerInterceptorAdapter
)
Tiene el método:
void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception;
Este método se invoca después de que el controlador finaliza y antes de que se visualice la vista. Entonces puede usarlo para agregar algunas propiedades al ModelMap
Un ejemplo:
/**
* Add the current version under name {@link #VERSION_MODEL_ATTRIBUTE_NAME}
* to each model.
* @author Ralph
*/
public class VersionAddingHandlerInterceptor extends HandlerInterceptorAdapter {
/**
* The name under which the version is added to the model map.
*/
public static final String VERSION_MODEL_ATTRIBUTE_NAME =
"VersionAddingHandlerInterceptor_version";
/**
* it is my personal implmentation
* I wanted to demonstrate something usefull
*/
private VersionService versionService;
public VersionAddingHandlerInterceptor(final VersionService versionService) {
this.versionService = versionService;
}
@Override
public void postHandle(final HttpServletRequest request,
final HttpServletResponse response, final Object handler,
final ModelAndView modelAndView) throws Exception {
if (modelAndView != null) {
modelAndView.getModelMap().
addAttribute(VERSION_MODEL_ATTRIBUTE_NAME,
versionService.getVersion());
}
}
}
webmvc-config.xml
<mvc:interceptors>
<bean class="demo.VersionAddingHandlerInterceptor" autowire="constructor" />
</mvc:interceptors>
También puede usar @ModelAttribute en métodos, por ejemplo
@ModelAttribute("version")
public String getVersion() {
return versionService.getVersion();
}
Esto lo agregará para todas las asignaciones de solicitudes en un controlador. Si coloca esto en una súper clase, podría estar disponible para todos los controladores que lo extiendan.
como @blank responde este trabajo por mí:
@ControllerAdvice(annotations = RestController.class)
public class AnnotationAdvice {
@Autowired
UserServiceImpl userService;
@ModelAttribute("currentUser")
public User getCurrentUser() {
UserDetails userDetails = (UserDetails)
SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return userService.findUserByEmail(userDetails.getUsername());
}
}
si necesita agregar algunas variables globales para que cada vista pueda resolver estas variables, ¿por qué no definirlas en una propiedad o en un mapa? luego use la primavera DI, consulte la resolución del bean de resolución. es muy útil, como static veriable, eg resUrl
<property name="viewResolvers">
<list>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="attributes" ref="env" />
<property name="exposeContextBeansAsAttributes" value="false" />
<property name="prefix" value="${webmvc.view.prefix}" />
<property name="suffix" value="${webmvc.view.suffix}" />
</bean>
</list>
</property>