Spring MVC explains the core technology in detail

Keywords: Java Spring Spring MVC

Chapter IV spring MVC core technology

1. Forwarding and redirection

forward: view full path

redirect: view full path

1.1 java code

@Controller
public class  MyController {

     * The controller method returns MOdelAndView Realize forwarding forward
     * grammar: mv.setViewName("forward:View full path")
     *
     * forward Features: does not work with the view parser. When there is no view parser in the project.
     *
     * The significance of this method is that when show.jsp Not under the path specified by the view parser, such as webapp It can be used under the directory forward To find
     * */
         
    @RequestMapping(value = "/doForward.do")
    public ModelAndView doForward(){
        System.out.println("Yes MyController of doSome method");

        ModelAndView mv = new ModelAndView();
//        Add data
        mv.addObject("msg","Handled some.do request");
        mv.addObject("fun","Yes doSome method");

//        mv.setViewName("forward:/WEB-INF/view/show.jsp");
        mv.setViewName("forward:/hello.jsp");
//        Return results
        return mv;

    }


     * When the controller sends a method, it returns ModelAndView Implement redirection
     * Syntax: mv.setViewName("redirect:View full path")
     * redirect Features: it does not work with the view parser, just as there is no view parser in the project
     *
     * Redirection provided by the framework
     * 1.The framework can realize the data transfer between two requests and transfer the data in the first request Model inside
     *   A simple type of data is converted into a string and attached to the back of the target page get Parameter passing.
     *   You can get the parameter value in the target page.
     *
     * 2.In the target page, you can use ${para.Parameter name} Gets the value of the parameter
     * */
         
    @RequestMapping("/doRedirect.do")
    public ModelAndView doRedirect(String name,Integer age){
        System.out.println("doRedirect,name=="+name+",age="+age);
        ModelAndView mv = new ModelAndView();
//        This cannot get a value because it is placed in the scope of the first request
        mv.addObject("myname",name);
        mv.addObject("myage",age);
//        This is the second request scope.
        mv.setViewName("redirect:/other.jsp");

//        http://localhost:8080/ch08_forward_redirect/other.jsp?myname=lisi&myage=22

//        Redirection cannot access / WEB-INF
//        mv.setViewName("redirect:/WEB-INF/view/other.jsp");
        return mv;
    }

}

1.2 jsp page other.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>show</title>
</head>

    other.jsp,display request Data in scope<br/>
    <H3>myname Data: ${myname}</H3>
    <h3>myage Data: ${myage}</h3>

    <H3>myname Data: ${param.myname}</H3>
    <h3>myage Data: ${param.myage}</h3>

    <h3>obtain get Parameters in request:<%=request.getParameter("myname")%></h3>

</body>
</html>

<html>
<head>
    <title>Request mode</title>
</head>
<body>
    <a href="doForward.do">launch doForward.do of get request</a>
    <br/>
    <br/>
    <p>redirect redirect</p>
    <form action="doRedirect.do" method="post">
        full name<input type="text" name="name"><br/>
        Age<input type="text" name="age"><br/>
        operation<input type="submit" value="Submit"><br/>
    </form>
</body>
</html>

2. Exception handling

A common way for the spring MVC framework to handle exceptions: use the @ ExceptionHandler annotation to handle exceptions.

The framework uses centralized exception handling. Collect the exceptions thrown in each controller to one place for processing. An exception handler is called an exception handler. Two annotations are used in the framework to complete the centralized processing of exceptions. In this way, each controller does not have to handle exceptions separately. The notes are:

  1. @ExceptionHandler: placed on the top of a method, indicating that this method can handle a certain type of exception. This method is executed when an exception occurs.

  2. @ControllerAdvice: placed on the top of the class, indicating that there are exception handling methods in this class. Equivalent to @ Aspect in aop

    @ControllerAdvice: regarded as Controller enhancement, it is to add exception (aspect) handling function to the Controller class.

  1. Modify spring MVC configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--    springmvc Configuration file for-->
<!--    Declaration component scanner-->
    <context:component-scan base-package="com.sunny.controller"/>
<!--    Declarative view parser: help with views-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--        Prefix: Specifies the path to the view file-->
        <property name="prefix" value="/WEB-INF/view/"/>
<!--        Suffix: extended name of the view file-->
        <property name="suffix" value=".jsp"/>
    </bean>

<!--    exception handling-->
    <context:component-scan base-package="com.sunny.handle"/>
<!--    Annotation driven-->
    <mvc:annotation-driven/>

</beans>
  1. Controller

@Controller
public class  MyController{

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(String name,Integer age) throws MyUserException {
        System.out.println("Yes MyController of doSome method");

//        Throw exception
        if(!"zs".equals(name)){
            throw new NameException("Incorrect name");
        }

        if(age == null|| age.intValue()>80){
            throw new AgeException("Too old");
        }

        ModelAndView mv = new ModelAndView();
//        Add data
        mv.addObject("myname",name);
        mv.addObject("myage",age);

//        mv.setViewName("forward:/WEB-INF/view/show.jsp");
        mv.setViewName("show");
//        Return results
        return mv;
    }

}

  1. exception
public class AgeException extends MyUserException {

    public AgeException() {
        super();
    }

    public AgeException(String message) {
        super(message);
    }
}
public class MyUserException extends Exception {
//    ctrl + 0

    public MyUserException() {
        super();
    }

    public MyUserException(String message) {
        super(message);
    }
}
public class NameException extends MyUserException {
//    ctrl + o overrides the method of the parent class
    public NameException() {
        super();
    }

    public NameException(String message) {
        super(message);
    }
}
  1. handle

package com.sunny.handle;

import com.sunny.exception.AgeException;
import com.sunny.exception.NameException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.naming.Name;


 *@ControllerAdvice :  Indicates that the current class is an exception handling class. to controller Increased functionality
 *              Location: above the class
 * */
@ControllerAdvice
public class GlobalExceptionHandler {
//    Define a method to handle exceptions. When an exception occurs, execute this method
//    Method definition and method definition in Controller class


     * handle NameException Exception of type
     * Parameters:
     *   Exception : express Controller Exception object thrown
     *
     * @ExceptionHandler: Indicates that this method handles exceptions
     *         Properties: value Indicates the exception type
     *         Location: above the method
     *
     * */
    @ExceptionHandler(value = NameException.class)
    public ModelAndView doNameException(Exception e){
        System.out.println("doNameException===="+e);
 
         * Exception occurred:
         *  1.Record the exception to the log file.
         *  2.Send notifications, emails, text messages, etc
         *  3.Give user-friendly tips
         * */
        ModelAndView mv = new ModelAndView();
        mv.addObject("tips","Name can only be zs");

        mv.setViewName("nameError");
        return mv;
    }

//    Handling AgeException
    @ExceptionHandler(value = AgeException.class)
    public ModelAndView doAgeException(Exception e){

        System.out.println("doAgeException===="+e);
    
         * Exception occurred:
         *  1.Record the exception to the log file.
         *  2.Send notifications, emails, text messages, etc
         *  3.Give user-friendly tips
         * */
        ModelAndView mv = new ModelAndView();
        mv.addObject("tips","Age cannot be greater than 80");

        mv.setViewName("ageError");
        return mv;
    }
//    Handle other exceptions. You can handle any exception without adding a value value
    @ExceptionHandler
    public ModelAndView doOtherException(Exception e){

        System.out.println("doOtherException===="+e);
    
         * Exception occurred:
         *  1.Record the exception to the log file.
         *  2.Send notifications, emails, text messages, etc
         *  3.Give user-friendly tips
         * */
        ModelAndView mv = new ModelAndView();
        mv.addObject("tips","Please try again later");

        mv.setViewName("defaultError");
        return mv;
    }
}

  1. jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ageError.jsp , ${tips}
</body>
</html>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Request mode</title>
</head>
<body>
    <a href="doForward.do">launch doForward.do of get request</a>
    <br/>
    <br/>
    <p>exception handling</p>
    <form action="some.do" method="post">
        full name<input type="text" name="name"><br/>
        Age<input type="text" name="age"><br/>
        operation<input type="submit" value="Submit"><br/>
    </form>
</body>
</html>

3. Interceptor

Interceptor: it is an object in the spring MVC framework and needs to implement the interface HandlerInterceptor. Intercept user requests. Request to connect to cintroller.

Function: intercept the user's request, process the request in advance, and decide whether to execute the controller. You can also define functions shared by multiple controllers to interceptors.

characteristic:

  1. Interceptors can be divided into system interceptors and custom interceptors.
  2. A project can have multiple interceptors. 0, or more custom interceptors.
  3. Interceptors focus on intercepting user requests.
  4. Interceptors are executed before request processing.

Definition of Interceptor:

  1. Create a class to implement the interceptor interface HandlerInterceptor and implement the methods in the interface (3).
  2. In the spring MVC configuration file, declare the interceptor object and specify the uri address of the interceptor.

3.1 first interceptor

package com.sunny.handler;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * Interceptor
 * */
public class MyInterceptor implements HandlerInterceptor {
//    ctrl+o


  
     * preHandler:Method of preprocessing requests. Main switch
     *    Parameters:
     *      Object handler : Intercepted controller object( MyController)
     *    Return value: boolean
     *      true: The request is correct and can be controller Handled.
     *          MyInterceptor Interceptor preHandle====
     *          Yes MyController of doSome method
     *          MyInterceptor Interceptor postHandle====
     *          MyInterceptor Interceptor afterCompletion====
     *
     *      false:The request cannot be processed and the controller method will not execute. The request ends here.
     *          MyInterceptor Interceptor preHandle====
     *
     * characteristic:
     *   1.The execution time of the preprocessing method: it is executed before the controller method.
     *   2.You can process requests, check login, judge permissions, statistics, etc.
     *   3.Decide whether to execute the request.
     * */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        System.out.println("MyInterceptor Interceptor preHandle====");
//        request.getRequestDispatcher("/tips.jsp").forward(request,response);
        return true;
    }

   
     * postHandler:Post processing method
     *    Parameters:
     *        Object handler : Intercepted controller object( MyController)
     *        ModelAndView mv: Return value of the controller method (execution result of the request)
     *
     *    characteristic:
     *        1.Executed after the controller method.
     *        2.The execution result of the controller method can be obtained. It can be modified to the original execution result.
     *          You can modify the data or the view.
     *        3.Secondary processing of requests can be.
     *
     *
     * */

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView mv) throws Exception {
        System.out.println("MyInterceptor Interceptor postHandle====");

//        Secondary processing of requests
        if(mv != null){
//            Modify data
            mv.addObject("mydate",new Date());
//            Modify view
            mv.setViewName("other");
        }

    }


     * afterCompletion:Method of final execution
     *  Parameters:
     *      Object handler :  Intercepted controller object( MyController)
     *      Exception ex; Exception object
     *
     *  characteristic:
     *      1.Executed after request processing is complete.
     *       The flag of request processing completion is that the view processing is completed. Execute on the view forward After operation.
     *
     *      2.You can do the last work of the program, free memory and clean up temporary variables.
     *
     *      3.Execution conditions of the method:
     *          1)His current interceptor preHandle()Method must be executed.
     *          2)preHandler()Must return true
     *
     * */

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        System.out.println("MyInterceptor Interceptor afterCompletion====");

//        get data
        HttpSession session = request.getSession();
        Object attr = session.getAttribute("attr");
        System.out.println("attr="+attr);

//        Delete data
        session.removeAttribute("attr");

//        Determines whether the data is deleted
        attr = session.getAttribute("attr");
        System.out.println("After deletion, check the data again==="+attr);
    }

}

Configuration file: added in springmvc.xml

<!--    Declaration interceptor-->
    <mvc:interceptors>
<!--        Declare first interceptor-->
        <mvc:interceptor>
<!--            Specifies the interception address of the interceptor
                path:Intercepted uri Address, using ** Wildcards.
                     For example: path = "/user/**"
                     http://localhost:8080/user/listUser.do
                     http://localhost:8080/user/query/queryUser.do
-->
            <mvc:mapping path="/**"/>
<!--            Specifies the interceptor to use-->
            <bean class="com.sunny.handler.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

1) Login authentication and permission judgment can be performed in the preHandle.

When your preHandle returns true, the execution result:

MyInterceptor Interceptor preHandle====
Yes MyController of doSome method
MyInterceptor Interceptor postHandle========
MyInterceptor Interceptor afterCompletion====

Execution order of requests: user some.do ---- preHandle-----doSome----postHandler----afterComplietion

When your preHandle returns false, the execution result:

false:The request cannot be processed and the controller method will not execute. The request ends here.
MyInterceptor Interceptor preHandle====
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        System.out.println("MyInterceptor Interceptor preHandle====");
        request.getRequestDispatcher("/tips.jsp").forward(request,response);
        return false;
    }

2) The postHandle handles the request twice

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView mv) throws Exception {
        System.out.println("MyInterceptor Interceptor postHandle====");

//        Secondary processing of requests
        if(mv != null){
//            Modify data
            mv.addObject("mydate",new Date());
//            Modify view
            mv.setViewName("other");
        }

    }

4) afterCompletion final execution

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        System.out.println("MyInterceptor Interceptor afterCompletion====");

//        get data
        HttpSession session = request.getSession();
        Object attr = session.getAttribute("attr");
        System.out.println("attr="+attr);

//        Delete data
        session.removeAttribute("attr");

//        Determines whether the data is deleted
        attr = session.getAttribute("attr");
        System.out.println("After deletion, check the data again==="+attr);
    }

MyInterceptor Interceptor preHandle====
Yes MyController of doSome method
MyInterceptor Interceptor postHandle====
MyInterceptor Interceptor afterCompletion====
attr=stay controller Temporary data added in
 After deletion, check the data again===null

3.2 multiple interceptors

Two interceptors are used, mainly depending on the execution order of the interceptor and controlling the execution of the request according to one method.

1) Two interceptors, the first preHandler=true, and the second interceptor preHandler=true

MyInterceptor111 Interceptor preHandle====
MyInterceptor222 Interceptor preHandle====
Yes MyController of doSome method
MyInterceptor222 Interceptor postHandle====
MyInterceptor111 Interceptor postHandle====
MyInterceptor222 Interceptor afterCompletion====
MyInterceptor111 Interceptor afterCompletion====

Order of execution of requests:

User some.do ------ preHandle of interceptor 1 ------ interceptor 2preHandle ------ controller doSome ------ interceptor 2postHandle ------ postHandle of interceptor 1 ------ afterCompletion of interceptor 2 ------ afterCompletion of interceptor 1.

2) Two interceptors, the first preHandler=true and the second prehandler = flash

MyInterceptor111 Interceptor preHandle====
MyInterceptor222 Interceptor preHandle====
MyInterceptor111 Interceptor afterCompletion====

3) Two interceptors, the first preHandler = false, and the second interceptor prehandler = true | false

MyInterceptor111 Interceptor preHandle====

Why use multiple interceptors?

  1. The verification function is distributed to independent interceptors, and each interceptor performs a single verification process.
  2. Combine multiple interceptors.

Summary:

Multiple interceptors, strung on a chain. Multiple interceptors and a controller object are on a chain. In the framework, a handler execution chain is used to represent an execution chain

public class HandlerExecutionChain {
    
    // Where the controller object is stored, MyController
    private final Object handler;
    @Nullable
    private HandlerInterceptor[] interceptors;// To store multiple interceptor objects. MyInterceptor 1, 2
    @Nullable
    private List<HandlerInterceptor> interceptorList;
    private int interceptorIndex;

    public HandlerExecutionChain(Object handler) {
        this(handler, (HandlerInterceptor[])null);
    }
}

How does the interceptor implement the execution order of 1,2,2,1 and traverse the HandlerInterceptor[] interceptors array

HandlerInterceptor[] interceptors = {MyInterceptor1,MyInterceptor2};
//Loop call method 1-2
for(int i =0;i<interceptors.length;i++){
    HandlerInterceptor obj =interceptors[i];
    obj.preHandle();
}

MyController.doSome();

// 2-1
for(int i =interceptors.length-1;i>=0;i--){
    HandlerInterceptor obj =interceptors[i];
    obj.postHandle();
}

Simple implementation of verification function

Most of the logic of this part is the same in the development process, and the part that may change is the part of judging the account number.

    /**
     * Verification function
     *
     * */

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        System.out.println("MyInterceptor111 Interceptor preHandle====");

//        Get login account information
        String username= "";
        Object attr = request.getSession().getAttribute("username");
        if(attr!=null){
            username = (String) attr;
        }

//        Judge account number
        if("zhangsan".equals(username)){
            return true;
        }else{
            request.getRequestDispatcher("/tips.jsp").forward(request,response);
            return false;
        }
    }

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Sign in</title>
</head>
<body>
    Login operation!!!
    <%
        session.setAttribute("username","zhangsan");
    %>
</body>
</html>
    
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Exit operation</title>
</head>
<body>
    Exit the system!!!
    <%
        session.removeAttribute("username");
    %>
</body>
</html>    

3.3 comparison of interceptors and filters

  1. Interceptors are objects in the spring MVC framework. Filters are objects in servlet s.

  2. The interceptor object is created by the framework container, and the filter object is created by tomcat.

  3. Interceptors focus on judging and processing requests, and can truncate requests. The filter focuses on setting values for request and response objects. For example, request.setCharacterEncoding("utf-8")

  4. There are three execution times for interceptors, before the controller method, after the request is completed. The filter is before the request.

  5. The interceptor intercepts requests for controller and dynamic resources. Filters can filter all requests, both dynamic and static.

  6. Interceptors and filters are executed together. The first filter is executed, followed by the central scheduler, followed by interceptors, followed by controller methods.

Posted by vargefaret on Fri, 12 Nov 2021 16:35:12 -0800