Marco SpringMVC -----> (5) Tecnología central SpringMVC (reenvío y redirección, manejo de excepciones, interceptor)

Tecnología central SpringMVC

1. Solicitar reenvío y redireccionamiento

  • Cuando el procesador completa el procesamiento de la solicitud y salta a otros recursos, existen dos métodos de salto: solicitud de reenvío y redirección. Según el tipo de recurso que se va a saltar, se puede dividir en dos categorías: saltar a la página y saltar a otros procesadores.

Tenga en cuenta que la página solicitada para ser reenviada puede ser una página en WEB-INF; mientras que una página redirigida no puede ser una página en WEB-INF. Porque la redirección es equivalente a que el usuario vuelva a realizar una solicitud y el usuario no puede acceder directamente a los recursos en WEB-INF.

Inserte la descripción de la imagen aquí

El marco SpringMVC encapsula las operaciones de reenvío y redirección de solicitudes en el Servlet original. Ahora puede utilizar métodos simples para lograr el reenvío y la redirección.

(1) Reenvío de solicitudes

  • hacia adelante:

Representa el reenvío, realiza request.getRequestDispatcher ("xx.jsp"). Forward ()

  • Características:

No trabaje con el solucionador de vistas, puede acceder a la página en WEB-INF

  • gramática:
setViewName("forward:视图文件完整路径")
@RequestMapping(value = "/doForward.do")
public ModelAndView doSome(){
    
    
    //处理some.do请求了。 相当于service调用处理完成了。
    ModelAndView mv  = new ModelAndView();
    mv.addObject("msg","欢迎使用springmvc做web开发");
    mv.addObject("fun","执行的是doSome方法");
    //使用forward显示转发
    //mv.setViewName("forward:/WEB-INF/view/show.jsp");
    mv.setViewName("forward:/hello.jsp");
    return mv;
}

(2) Solicitar redirección

  • redireccionar:

Representa la redirección, se da cuenta de response.sendRedirect ("xxx.jsp")

  • Características:

No funciona con el solucionador de vistas y no puede acceder a páginas en WEB-INF

  • gramática:
setViewName("redirect:视图完整路径")
/**
 * 框架对重定向的操作:
 * 1.框架会把Model中的简单类型的数据,转为string使用,作为hello.jsp的get请求参数使用。
 *   目的是在 doRedirect.do 和 hello.jsp 两次请求之间传递数据
 *
 * 2.在目标hello.jsp页面可以使用参数集合对象 ${param}获取请求参数值
 *    ${param.myname}
 *
 * 3.重定向不能访问/WEB-INF资源
 */
@RequestMapping(value = "/doRedirect.do")
public ModelAndView doWithRedirect(String name,Integer age){
    
    
    //处理some.do请求了。 相当于service调用处理完成了。
    ModelAndView mv  = new ModelAndView();
    //数据放入到 request作用域
    mv.addObject("myname",name);
    mv.addObject("myage",age);
    //重定向
    mv.setViewName("redirect:/hello.jsp");
    //http://localhost:8080/springmvc/hello.jsp?myname=lisi&myage=22

    //重定向不能访问/WEB-INF资源
    //mv.setViewName("redirect:/WEB-INF/view/show.jsp");
    return mv;
}

2. Manejo de excepciones

  • Todo el manejo de excepciones en el controlador se concentra en un solo lugar, y la idea de aop se adopta para separar la lógica empresarial y el código de manejo de excepciones para lograr el desacoplamiento.
Usa dos anotaciones

1) @ControllerAdvice: Definido en la clase para mejorar la función de manejo de excepciones para la clase del controlador. El escáner de componentes debe declararse en el archivo de configuración springmvc para especificar el nombre del paquete donde se encuentra la anotación.

2) @ExceptionHandler: definido en el método, el atributo de valor indica el tipo de excepción, y cuando ocurre tal excepción, el método actual maneja la excepción.

(1) Clase de excepción personalizada

  • Defina tres clases de excepción: NameException, AgeException, MyUserException. Entre ellos, MyUserException es la clase principal de las otras dos excepciones.
public class MyUserException extends Exception{
    
    

    public MyUserException() {
    
    
        super();
    }

    public MyUserException(String message) {
    
    
        super(message);
    }
}
/**
 * 表示用户姓名有异常,抛出异常
 */
public class NameException extends MyUserException {
    
    
    public NameException() {
    
    
        super();
    }

    public NameException(String message) {
    
    
        super(message);
    }
}
/**
 * 表示年龄有异常抛出异常
 */
public class AgeException extends MyUserException{
    
    
    public AgeException() {
    
    
        super();
    }

    public AgeException(String message) {
    
    
        super(message);
    }
}

(2) Definir la clase de manejo de excepciones globales

@ControllerAdvice
public class GlobalExceptionHandler {
    
    
    //定义方法,处理异常
    @ExceptionHandler(value = NameException.class)
    public ModelAndView doNameException(Exception exception){
    
    
        //处理NameException的异常
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","姓名必须是张三,其它用户不能访问");
        mv.addObject("ex",exception);
        mv.setViewName("nameError");
        return mv;
    }

    @ExceptionHandler(value = AgeException.class)
    public ModelAndView doAgeException(Exception exception){
    
    
        //处理AgeException的异常
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","年龄必须不能大于80");
        mv.addObject("ex",exception);
        mv.setViewName("ageError");
        return mv;
    }

    //处理其它异常
    @ExceptionHandler
    public ModelAndView doOtherException(Exception exception){
    
    
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","发生其它异常");
        mv.addObject("ex",exception);
        mv.setViewName("defaultError");
        return mv;
    }
}

(3) Declare el escáner de componentes en el archivo de configuración springmvc

<!--声明组件扫描器:@Controller所在包名-->
<context:component-scan base-package="com.hcz.controller" />
<!--声明组件扫描器:@ControllerAdvice所在包名-->
<context:component-scan base-package="com.hcz.handler"/>
<!--注解驱动-->
<mvc:annotation-driven/>

(4) Cree una página para manejar los resultados de la excepción

<body>
ageError.jsp<br/>
提示信息:${msg}<br>
系统异常信息:${ex.message}
</body>
<body>
    nameError.jsp<br/>
    提示信息:${msg}<br>
    系统异常信息:${ex.message}
</body>
<body>
    defaultError.jsp<br/>
    提示信息:${msg}<br>
    系统异常信息:${ex.message}
</body>

3. Interceptor

(1) Resumen de interceptores:

  • 1) Interceptor es una especie de springmvc y necesita implementar la interfaz HandlerInterceptor.
  • 2) El interceptor es similar al filtro, pero el enfoque de la dirección de la función es diferente. Los filtros se utilizan para filtrar parámetros de solicitud, establecer conjuntos de caracteres codificados y otras tareas. El interceptor intercepta la solicitud del usuario y realiza la solicitud de procesamiento de sentencia.
  • 3) El interceptor es global y puede interceptar múltiples controladores. Puede haber 0 o más interceptores en un proyecto e interceptan las solicitudes de los usuarios juntos.
  • 4) Los interceptores se utilizan comúnmente en: procesamiento de inicio de sesión de usuario, verificación de permisos y registro.

(2) Pasos para utilizar el interceptor:

1. Defina la clase para implementar la interfaz HandlerInterceptor
2. En el archivo de configuración springmvc, declare el interceptor para que el marco sepa la existencia del interceptor.

(3) Tiempo de ejecución del interceptor:

1) Antes de que se procese la solicitud, es decir, antes de que se ejecute el método en la clase de controlador, se intercepta.
2) El interceptor también se ejecutará después de que se ejecute el método del controlador.
3) El interceptor también se ejecutará después de que se complete el procesamiento de la solicitud.

(4) Interceptor personalizado

  • Necesita implementar la interfaz HandlerInterceptor, y la interfaz contiene tres métodos:
  • preHandle (solicitud, respuesta, controlador de objetos):

preHandle devuelve verdadero: el interceptor verifica la solicitud y el método del controlador se puede ejecutar


PreHandle del interceptor () de MyInterceptor
=Ejecute el método doSome en MyController=
Interceptor's MyInterceptor's postHandle ()
interceptor's MyInterceptor's afterCompletion ()

preHandle devuelve falso: la solicitud no pasa la verificación del interceptor, la solicitud finaliza cuando llega al interceptor y la solicitud no ha sido procesada

Características :
1. El método se ejecuta antes que el método del controlador (doSome of MyController). La solicitud del usuario llega primero a este método
2. En este método, la información solicitada se puede obtener para verificar si la solicitud cumple con los requisitos. Puede verificar si el usuario ha iniciado sesión y verificar si el usuario tiene permiso para acceder a una determinada dirección de conexión (url).
Si la verificación falla, la solicitud se puede truncar y no se puede procesar.
Si la verificación es exitosa, la solicitud se puede liberar y luego se puede ejecutar el método del controlador.

  • postHandle (solicitud, respuesta, controlador de objetos, modelAndView) :

Características :
1. El método se ejecuta después de que se ejecuta el método del procesador. Si el método del procesador no se ejecuta al final, el método no se ejecutará.
2. El parámetro del método contiene ModelAndView, por lo que el método puede modificar los datos del resultado del procesamiento del método del procesador y puede modificar la dirección del salto

  • afterCompletion (solicitud, respuesta, controlador de objetos, excepción ex) :

Cuando el método preHandle () devuelve verdadero, el método se colocará en una pila de métodos especial y el método se ejecutará después de que se complete todo el trabajo en respuesta a la solicitud. Generalmente, es el último método que se ejecuta para el recurso. recuperación.

(5) interceptor de registro springmvc

<!--声明拦截器: 拦截器可以有0或多个-->
<mvc:interceptors>
    <!--声明第一个拦截器-->
    <mvc:interceptor>
        <!--指定拦截的请求uri地址
            path:就是uri地址,可以使用通配符 **
                  ** : 表示任意的字符,文件或者多级目录和目录中的文件
            http://localhost:8080/myweb/user/listUser.do
            http://localhost:8080/myweb/student/addStudent.do
        -->
        <mvc:mapping path="/**"/>
        <!--声明拦截器对象-->
        <bean class="com.hcz.handler.MyInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

(6) Un diagrama de flujo de trabajo de un interceptor:

Inserte la descripción de la imagen aquí

(7) Diagrama de flujo de trabajo de múltiples interceptores:

Inserte la descripción de la imagen aquí

Como puede verse en la figura, siempre que un método preHandle () devuelva falso, la cadena de ejecución superior se desconectará y
sus métodos de procesador posteriores y los métodos postHandle () no se ejecutarán. Pero independientemente de la ejecución de la cadena de ejecución, siempre que haya métodos en la pila de métodos, es decir, siempre que el método preHandle () en la cadena de ejecución devuelva verdadero, el método afterCompletion () en la pila de métodos será ejecutado, y eventualmente se dará una respuesta.

(8) La diferencia entre interceptor y filtro

1. El filtro es el objeto en el servlet, el interceptor es el objeto en el marco; el filtro implementa el objeto de la interfaz Filter y el interceptor implementa el HandlerInterceptor
2. El filtro se usa para establecer los parámetros de solicitud y respuesta y atributos, centrándose en el filtrado de datos correcto; los interceptores se utilizan para verificar solicitudes y pueden interceptar solicitudes.
3. El filtro se ejecuta antes que el interceptor.
4. El filtro es el objeto creado por el servidor tomcat; el interceptor es el objeto creado en el contenedor springmvc
5. El filtro es un punto de tiempo de ejecución; el interceptor tiene tres puntos de tiempo de ejecución
6. El filtro puede procesar jsp, js, html, etc.; Interceptor se enfoca en interceptar el objeto del Controlador. Si el despachador central DispatcherServlet no puede recibir su solicitud, la solicitud no ejecutará el contenido del interceptor.
7. El interceptor intercepta la ejecución de métodos ordinarios y el filtro filtra la respuesta a la solicitud del servlet.

(9) El interceptor verifica el elemento de inicio de sesión

  • Caso: solo el usuario que inició sesión puede acceder al procesador; de lo contrario, volverá al mensaje "Sin acceso"

Pasos de implementación:
1. Crear un nuevo maven
2. Modificar web.xml para registrar el programador central
3. Crear un nuevo index.jsp para iniciar una solicitud
4. Crear un MyController para procesar la solicitud
5. Crear el resultado show.jsp
6 . Cree un login.jsp para simular el inicio de sesión (coloque La información del usuario se guarda en la sesión)
7. Cree un logout.jsp para simular la salida del sistema (elimine los datos de la sesión)
8. Cree un interceptor para obtener los datos de inicio de sesión del usuario de la sesión para verificar si se accede al sistema o no.
9. Cree un jsp de autenticación, si verifica la vista, dé un mensaje
10. Cree un archivo de configuración springmvc
1) Declare el escáner de componentes
2) Declare el interceptor

A. Cree una nueva página index.jsp
<body>
    <p>一个拦截器</p>
    <form action="some.do" method="post">
        姓名:<input type="text" name="name"> <br/>
        年龄:<input type="text" name="age"> <br/>
        <input type="submit" value="提交请求">
    </form>
</body>
B. Cree un controlador para procesar la solicitud
@Controller
public class MyController {
    
    

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(String name,Integer age)  {
    
    
        System.out.println("=====执行MyController中的doSome方法=====");
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",name);
        mv.addObject("myage",age);
        mv.setViewName("show");
        return mv;
    }
}
C. Cree la página de resultados show.jsp
<body>
    <h3>/WEB-INF/view/show.jsp从request作用域获取数据</h3><br/>
    <h3>myname数据:${myname}</h3><br/>
    <h3>myage数据:${myage}</h3>
</body>
D. Cree una página de inicio de sesión login.jsp
<body>
    模拟登录,zs登录系统
    <%
        session.setAttribute("name","zs");
    %>
</body>
E. Cree logout.jsp para salir del sistema
<body>
    退出系统
    <%
        session.removeAttribute("name");
    %>
</body>
F. Crear una clase de interceptor
/**
 * 拦截器类:拦截用户的请求
 */
public class MyInterceptor implements HandlerInterceptor {
    
    

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        System.out.println("111111-拦截器的MyInterceptor的preHandle()");
        String loginName = "";
        //从session中获取name数据
        Object attr = request.getSession().getAttribute("name");
        if (attr != null){
    
    
            loginName = (String)attr;
        }
        //判断登录的账号是否符合要求
        if (!"zs".equals(loginName)){
    
    
            //不能访问
            request.getRequestDispatcher("/tips.jsp").forward(request,response);
            return false;
        }
        return true;
    }
}
G. Cree una página de aviso que no haya iniciado sesión
<body>
  tips.jsp  非张三不能访问
</body>
H, modificar el archivo de configuración springmvc
<!--声明组件扫描器-->
<context:component-scan base-package="com.hcz.controller" />

<!--声明 springmvc框架中的视图解析器, 帮助开发人员设置视图文件的路径-->
<bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--前缀:视图文件的路径-->
    <property name="prefix" value="/WEB-INF/view/" />
    <!--后缀:视图文件的扩展名-->
    <property name="suffix" value=".jsp" />
</bean>

<!--声明拦截器: 拦截器可以有0或多个
    在框架中保存多个拦截器是ArrayList,
    按照声明的先后顺序放入到ArrayList
-->
<mvc:interceptors>
    <!--声明第一个拦截器-->
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <!--声明拦截器对象-->
        <bean class="com.hcz.handler.MyInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>
I. Prueba de proyectos

1) http: // localhost: 8080 / springmvc / index.jsp
Debido a que el usuario zs no ha iniciado sesión, no puede responder a la solicitud de página index.jsp
2) http: // localhost: 8080 / springmvc / login.jsp
3 ) http: // localhost: 8080 / springmvc / index.jsp
Debido a que el usuario zs ha iniciado sesión, puede responder a la solicitud de la página index.jsp y reenviarla a la página show.jsp
4) http: // localhost: 8080 /springmvc/login.jsp
5) http: / /localhost:8080/springmvc/logout.jsp
6) http: // localhost: 8080 / springmvc / index.jsp
Cuando los usuarios de zs cierran la sesión del sistema, ya no pueden responder a la página index.jsp

Supongo que te gusta

Origin blog.csdn.net/hcz666/article/details/113988586
Recomendado
Clasificación