Cuatro estrategias para acceder a las propiedades de la sesión en Spring 2.5
Las aplicaciones WEB generalmente introducen la sesión para guardar una serie de operaciones/estado de mensajes entre el servidor y el cliente, como guardar la información de inicio de sesión del usuario durante las compras en línea hasta que el usuario cierra la sesión y después de que el usuario inicia sesión. el bucle de sesión Hay muchas operaciones que requieren obtener el permiso del usuario para volver a autenticar la identidad u otras operaciones de la sesión, lo que implicará el problema del acceso del programa a las propiedades de la sesión. En Java, la especificación de Servlet proporciona el objeto HttpSession para satisfacer esta necesidad. Los desarrolladores pueden obtener HttpSession del objeto HttpServletRquest y luego obtener información de estado de HttpSession.
Volviendo al ejemplo del carrito de compras, podemos utilizar el objeto HttpSession para almacenar una serie de operaciones/mensajes. Si el código basado en el estándar Servlet se vería así
Código Java
public void doGet( HttpServletRequest req HttpServletResponse resp) throws ServletException IOException {
Usuario usuario = (Usuario)req getSession() getAttribute( currentUser );
//
}
Código como este se utiliza en programas de Servlet tradicionales Es muy común en Servlet API porque el uso de Servlet API dependerá de Servlet API, por lo que si queremos probar una determinada operación, por supuesto, existen muchos marcos de prueba de Servlet de código abierto que pueden ayudarnos a aliviar el dolor, incluido La implementación de código auxiliar de estas clases que viene con Spring, pero esto todavía es demasiado engorroso y engorroso. Entonces, ¿existe una mejor manera de hacer que nuestro controlador esté más basado en POJO, de modo que nuestras operaciones puedan separarse de las dependencias de la API de Servlet y sean más propicias para las pruebas y la reutilización? Echemos un vistazo a varias soluciones para acceder a las propiedades de la sesión en Spring. Continuaremos explorando el significado más profundo detrás de la elección de la solución en artículos posteriores de este blog.
(a) Convierta el objeto HttpServletRequest o los objetos HttpSession pasados. como parámetros del método
He introducido brevemente las anotaciones de Spring en un artículo anterior. Las anotaciones de Spring permiten al controlador deshacerse de las restricciones de la API de Servlet sobre los parámetros del método. Los estudiantes interesados pueden consultar aquí. tipos Incluye Solicitud/Respuesta/HttpSession dentro de la API de Servlet (incluida la Solicitud de respuesta declarada en una subclase específica de la API de Servlet), por lo que los desarrolladores pueden declarar objetos de Solicitud u objetos HttpSession en parámetros de acción para que el contenedor pueda inyectar los objetos correspondientes.
Declare un objeto Request o un objeto HttpSession en los parámetros de operación para permitir que el contenedor inyecte el objeto apropiado
El código de operación es el siguiente
Código Java
@RequestMapping
public void hola(sesión HttpSession){
Usuario usuario = (Usuario) sesión getAttribute( usuario actual ); /
p>}
Ventajas
Los programas pueden usar directamente los objetos Request/HttpSession subyacentes, y usted puede manipular directamente las propiedades de estos objetos usando los métodos definido en la especificación API de Servlet. Simple y claro
La operación puede controlar las propiedades de sesión específicas a las que se debe acceder y realmente apuntar a cada propiedad específica en la sesión
Debilidades
El programa Se basa en la API de Servlet. Aunque la clase de controlador ya no hereda de HttpServlet, la API de Servlet aún debe compilarse. Compilar, ejecutar e incluso probar requiere la API de Servlet
La exposición de la API de Servlet subyacente expone una gran cantidad de métodos y clases subyacentes innecesarios, de los que los desarrolladores pueden abusar fácilmente
( b) Inyecte los objetos de usuario requeridos en el nivel de clase del controlador a través de un interceptor personalizado.
Interceptor es uno de los puntos de extensión proporcionados por Spring. SpringMVC manejará las solicitudes antes y después de la llamada en la configuración definida en Interceptor para completar algunos trabajos de reducción, como verificar los permisos del usuario para manejar la distribución, etc. De manera similar a AOP, podemos extraer dicha sección transversal en SpringMVC, es decir, antes de llamar a la operación, inyectar la variable miembro del Usuario en el controlador en el método preHandle del interceptor, de modo que el controlador tenga el Usuario actualmente conectado. object
Además, debe declarar una clase de interfaces para estos controladores específicos, como IUserAware.
Código IUserAware
Código Java
interfaz pública IUserAware {
public void setUser()
}
Código del controlador
Código Java
@Controller
public GreetingController implementa IUserAware {
usuario privado
p>public void setUser(Usuario usuario){
este usuario = usuario
}
@RequestMapping
public; void hola(){<
//usuario diceHola()
}
//
}
Código interceptor
Código Java
clase pública UserInjectInterceptor extiende HandlerInterceptorAdapter {
@Override
public booleanpreHandle(HttpServletRequest ServletRequest HttpServletResponse ServletResponse Objeto controlador) arroja una excepción {
if (handler isAssignableFrom(IUserAware)){
Usuario usuario = (Usuario)() getAttribute( currentUser
IUserAware userAware); = controlador (IUserAware);
userAware setUser(usuario);
}
Devuelve super preHandle (controlador ServletRequest ServletResponse); }
//
}
Para que SpringMVC llame al interceptor definido por el desarrollador, también debemos declarar el interceptor en el archivo de configuración de SpringMVC.
Tome el interceptor como ejemplo
Código XML
< nombre de propiedad= interceptores >
Ventajas
El acceso a la API del Servlet se transfiere a un controlador interceptor, que se extiende desde la API SpringMVC, sin importar cómo lo obtiene el usuario.
Los desarrolladores pueden agregar o eliminar interceptaciones en cualquier momento. Convertidor para completar el inyección de diferentes parámetros del tipo de controlador
El objeto de usuario del controlador se inyecta a través de una fuente externa. Los objetos de usuario se inyectan desde el exterior, los desarrolladores pueden inyectar fácilmente los objetos de usuario que deseen durante las pruebas
La clase de controlador elimina la dependencia de la API de Servlet y es más POJO y genérica
El controlador La clase se inyecta con la ayuda de la declaración de interfaz y no hay dependencia de herencia.
La clase del controlador se inyecta con la ayuda de la declaración de interfaz. Dependencias heredadas
Errores
SpringMVC trata a los controladores como mónadas de forma predeterminada. Agregar variables miembro en la clase de controlador puede causar problemas de seguridad de subprocesos múltiples
Porque el objeto Usuario se define como una variable miembro del controlador y se inyecta a través de un definidor. Dado que el objeto Usuario se define como una variable miembro del controlador y se inyecta a través del configurador, debemos tener mucho cuidado durante las pruebas para asegurarnos de que el controlador inyecte el objeto Usuario; de lo contrario, es posible que no obtengamos un buen ciudadano.
De hecho, en pocas palabras, estos defectos ocurren porque hemos roto la convención del controlador al elevar el objeto Usuario requerido desde el nivel de acción al nivel de controlador. La razón de estos defectos es que promovemos el objeto Usuario requerido por la capa de operación específica a la capa de controlador, rompiendo la convención sin estado de la clase de controlador, y la inyección de setter introduce algunas molestias y defectos implícitos. Por supuesto, podemos eludir la convención sin estado declarando el controlador como prototipo. Por supuesto, podemos evitar la convención sin estado declarando el controlador como un prototipo, y también podemos asegurarnos de que un objeto Usuario se inyecte en el controlador cada vez que se crea, pero ¿existe una manera más fácil y orientada a objetos de hacer esto? ¿Qué tal un poco?
(3) Inyectar objetos de usuario a nivel de método a través de MethodArgumentResolver
Como hemos visto antes, SpringMVC proporciona muchos puntos de extensión para los desarrolladores, permitiéndoles agregar complementos según sea necesario Solicitar una personalización clase o controlador. Entonces, a nivel de clase de controlador, SpringMVC proporciona extensiones de interceptor y, a nivel de acción, ¿proporciona los controladores correspondientes?
Al observar la documentación de la API de SpringMVC, SpringMVC en realidad proporciona una extensión Resolver para la inyección de parámetros de método en la capa de acción, lo que permite a los desarrolladores configurar la clase HandlerMapper como un MethodArgumentResolver personalizado.
MethodArgumentResolver
El código de operación es el siguiente
Código Java
@RequestMapping
public void hello(Usuario usuario){
//usuario diceHola()
}
El código de Resolver es el siguiente
Código Java
clase pública UserArgumentResolverimplements WebArgumentResolver {
objeto público resolveArgument (MethodParameter métodoParameter NativeWebRequest webRequest) lanza una excepción {
if (methodParameter getParameterType () es igual (clase de usuario)) {
return webRequest getAttribute( currentUser RequestAttributes SCOPE_SESSION);
}
Devolver UNRESOLVED
}
La configuración relevante del archivo de configuración es la siguiente. sigue
>
Ventajas
Todas las ventajas de la segunda opción
p>Verdadero bajo demanda, inyectando objetos específicos sólo donde realmente se necesitan. Solo inyecte un objeto específico donde realmente sea necesario, reduciendo así las dependencias de ese objeto en otros lugares
Otros pueden ver fácilmente en la lista de parámetros de la operación de qué API depende la operación, lo que la hace más clara y fácil de entender
Para los tipos de parámetros que se requieren para muchas operaciones, el parámetro se puede inyectar de manera conveniente y consistente en el único lugar donde se necesita
Desventajas
La inyección de dependencia de objetos funciona para todas las operaciones. La granularidad de la inyección aún es aproximada y es imposible que operaciones específicas accedan a atributos de sesión específicos
(4) Asociación de atributos de usuario a través de la anotación SessionAttributes de SpringMVC
La documentación de SpringMVC menciona el La anotación @SessionAttributes y @ ModelAttribute se pueden usar juntas para almacenar o recuperar un objeto específico con un nombre de atributo específico hacia o desde la sesión. La documentación indica que
Referencias
La anotación @SessionAttributes de nivel de tipo declara la anotación @SessionAttributes como una referencia a un objeto específico con el nombre de atributo especificado.
La anotación SessionAttributes declara los atributos de sesión utilizados por un controlador específico. Por lo general, enumera los nombres de los atributos del modelo que deben almacenarse de forma transparente en la sesión o en algún almacén de sesiones como formulario alternativo para solicitudes posteriores.
Obviamente, @. SessionAttributes se utiliza para crear atributos de sesión.
La respuesta es que podemos agregar @SessionAttributes en el controlador que necesita acceder a los atributos de la sesión, y luego agregar @ModelAttribute en el parámetro Usuario de la operación, y asegurarnos de que los nombres de los atributos sean los mismos. en ambos casos, SpringMVC convertirá automáticamente @SessionAttributes definidos por @SessionAttributes a @ModelAttribute. SpringMVC inyectará automáticamente las propiedades definidas por @SessionAttributes en el objeto ModelMap, y cuando configuramos la lista de parámetros de la acción, obtendremos dicho objeto de ModelMap y luego lo agregaremos a la lista de parámetros. Mientras no llamemos al método setComplete() de SessionStatus, el objeto permanecerá en la sesión, implementando así la información de la sesión. Información de la sesión ****disfrutada
El código del controlador es el siguiente
Código Java
@Controller
@SessionAttributes( currentUser )
Clase pública GreetingController{
@RequestMapping
public void hola(@ModelAttribute( currentUser ) Usuario usuario){
//usuario sayHello ()
}
//
}
En este caso, también necesitas agregar p:allowSessionOverride= true Agregar a la definición de ViewResolver en el archivo de configuración SpringMVC, de modo que si realiza cambios en el objeto Usuario, anulará las propiedades relevantes en la Sesión cuando se represente la Vista. Anular propiedades relevantes en la sesión
Ventajas
Tiene todas las ventajas de la segunda opción
Utiliza anotaciones para declarar el acceso a propiedades específicas de la sesión. Uso de anotaciones para declarar el acceso a propiedades específicas de la sesión Cada operación simplemente declara las propiedades de la sesión que requiere
Otros pueden aprender fácilmente qué dependencias requiere la operación en la lista de parámetros de la operación Otros pueden Es fácil saber qué dependencias de API tiene la operación requiere de la lista de parámetros de la operación
Desventajas
Cada operación requiere un objeto de sesión definido con las mismas propiedades
Esta solución no es la intención original de SpringMVC y por lo tanto, puede ser controvertido
Al observar los cuatro tipos de métodos, podemos ver que hemos configurado el control de acceso para las propiedades de la sesión. Tenemos configuraciones de control de acceso para las propiedades de la sesión, desde todos los servlets hasta variables miembro de un tipo específico de controlador, desde parámetros de un tipo específico de operación hasta objetos específicos de un tipo específico de operación. Cada uno de estos métodos tiene pros y contras. La segunda y tercera soluciones resuelven el problema de dependencia de la API de Servlet y brindan acceso a las propiedades de la sesión en los niveles de controlador y acción respectivamente, pero la granularidad de la inyección aún no es lo suficientemente fina y el acceso a propiedades específicas puede resultar engorroso. La cuarta opción es usar anotaciones, que no solo lo liberan de las dependencias de la API de Servlet, sino que también brindan acceso a propiedades de sesión específicas en la capa de operación, pero este acceso puede ser demasiado granular y requerir la misma declaración en muchas operaciones diferentes. anotación.
Sin embargo, este acceso puede ser demasiado detallado y requiere que se declare la misma anotación en muchas operaciones diferentes. Después de todo, este uso no es lo que SpringMVC espera o recomienda, y puede causar cierta controversia lishixinzhi/Article/program/Java/ky/ 201311. /28209