SpringMVC helps you learn from entry to mastery

SpringMVC

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-GoRKIAzC-1678070111788)(note picture/image-20230213145340880.png)]

1. Overview of Spring MVC

Overview:

Spring MVC is a lightweight Web development framework based on the MVC design pattern provided by Spring, which is essentially equivalent to Servlet. Spring MVC has a clear role division and a detailed division of labor. Since Spring MVC itself is part of the Spring framework, it can be said that it is seamlessly integrated with the Spring framework. It has inherent advantages in terms of performance, and is the most mainstream web development framework and the most popular development skill in the industry today. A good framework should reduce the burden on developers to deal with complex issues, have good internal extensions, and have a strong user group that supports it, exactly what Spring MVC has done. ,

1. Overview of the MVC design pattern

The MVC design pattern generally refers to the MVC framework, M (Model) refers to the data model layer, V (View) refers to the view layer, and C (Controller) refers to the control layer. The purpose of using MVC is to separate the implementation codes of M and V, so that the same program can have different expressions. Among them, the definition of View is relatively clear, which is the user interface.

for example:

In the development of Web projects, it is very important to be able to respond to user requests in a timely and correct manner. The user clicks a URL path on the web page, which is equivalent to the user sending a request to the web server. After obtaining the request, how to parse the user's input, execute relevant processing logic, and finally jump to the correct page to display the feedback result, these tasks are often completed by the control layer (Controller). During the request process, the user's information is encapsulated in the User entity class, which belongs to the data model layer (Model) in the Web project. In the request display stage, the redirected result web page belongs to the view layer (View).

View layer (View) : Responsible for formatting data and presenting them to users, including data display, user interaction, data validation, interface design and other functions

Control layer (Controller): responsible for receiving and forwarding the request, after processing the request, specifying the view and sending the response result to the client.

Data model layer (Model) : The model object has the most processing tasks and is the main part of the application. It is responsible for the processing of data logic (business rules) and the realization of data operations (ie, accessing data in the database).

2. Advantages and disadvantages of SpringMVC

There are pros and cons to any one thing, let's take a look at the pros and cons of MVC.

advantage

1. Multiple views share a model, greatly improving code reusability

2. The three modules of MVC are independent of each other, loosely coupled architecture

3. Controllers increase application flexibility and configurability

4. Conducive to software engineering management

  总之,我们通过 MVC 设计模式最终可以打造出一个松耦合+高可重用性+高可适用性的完美架构。

shortcoming

1. The principle is complex

2. Increased the complexity of the system structure and implementation

3. View's inefficient access to model data

​ MVC is not suitable for small or even medium-sized projects. Spending a lot of time applying MVC to small-scale applications is usually not worth the candle. Therefore, the use of MVC design patterns should be determined according to specific application scenarios.

3. Overview of Spring's MVC pattern

  1. It is a lightweight Web development framework based on the MVC design pattern provided by Spring, which is essentially equivalent to Servlet.
  2. It is the implementation of Servlet+JSP+JavaBean with the clearest structure, and it is a typical textbook-style MVC framework, unlike other frameworks such as Struts that are variants or not completely based on the MVC system.
  3. The roles are clearly divided, the division of labor is detailed, and it is seamlessly integrated with the Spring framework. Spring MVC is the most mainstream web development framework and the most popular development skill in the industry today.
  4. The Controller replaces the Servlet to assume the responsibility of the controller, which is used to receive the request, call the corresponding Model for processing, and return the processing result after the processor completes the business processing. The Controller calls the corresponding View and renders the processing result, and finally the client gets the response information.
  5. The framework adopts a loosely coupled and pluggable component structure, which is highly configurable and more scalable and flexible than other MVC frameworks
  6. Spring MVC's annotation-driven and REST-style support is seamlessly integrated with the Spring framework, and has inherent advantages in performance. For developers, the development efficiency is also higher than other Web frameworks.

2. Build Spring MVC

1. Build a complete Spring framework

2. Introduce related SpringMVC dependencies

<!-- Spring-web开发和集成MVC开发的相关依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>

<!-- spring集成junit的单元测试包 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>

<!--日志-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.21</version>
</dependency>

<!--J2EE-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

<!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>

<!-- 文件上传和下载 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>



3. Create a web configuration file under the spring project

insert image description here

4. Add configuration tomcat

insert image description here
insert image description here

1. If there is no war explode package added to the tomcat option to configure packaging

insert image description here

After the above steps are completed, you must reconfigure tomcat

5. Configure the front controller (DispatcherServlet)

DispatcherServlet needs to be deployed in web.xml when developing Spring MVC applications

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- 项目名称(最好可以和tomcat中配置的上下文名称一致) -->
    <display-name>demoMVC</display-name>
    <!-- 部署 DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <!-- 框架的前端控制器类 -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 表示容器再启动时立即加载servlet -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!-- 处理所有URL -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>


</web-app>

6. Create a SpringMVC configuration file (Spring configuration items can also be written)

The name is: springmvc-servlet.xml, placed in the resource directory

web.xml configuration

 <!-- 部署 DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <!-- 框架的前端控制器类 -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置一个初始化参数 -->
        <init-param>
            <!-- 加载本地的springMVC配置文件!!!!!!!!! -->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>

        <!-- 表示容器再启动时立即加载servlet -->
        <load-on-startup>1</load-on-startup>
    </servlet>

1. Make a simple attempt, set up a controller to request and respond to the jump page

controller class

package com.huawei.SpringDemo2023.classtest.controller;

//import org.springframework.stereotype.Controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 模块名称:登录模块
 * 模块类型:控制器(C)
 * 编码人:高靖博
 * 创建时间:2023/2/13
 * 联系电话:18587388612
 */
public class LoginController implements Controller {
    
    

    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
    
    
        System.out.println("----接收到请求");

        return new ModelAndView("/WEB-INF/views/index.jsp");//将响应转发到视图
    }

}

springmvc configuration file configuration

<!-- name设置的是请求controller的url路径,且不要和其他的bean的name设置重复 -->
        <bean name="/login" class="com.huawei.SpringDemo2023.classtest.controller.LoginController" />

3. View resolver

View Resolver (ViewResolver) is an important part of Spring MVC, responsible for resolving logical view names into specific view objects.

1. View resolver type

1. InternalResourceViewResolver

Configured in the springmvc configuration file

<!-- 视图解析器 -->
       <!-- 内部资源视图解析器 -->
       <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!-- 视图路径前缀 -->
              <property name="prefix" value="/WEB-INF/views/" />
              <!-- 视图路径后缀 -->
              <property name="suffix" value=".jsp" />
       </bean>

If the jstl expression is used in the jsp page in the future, the view parser configured above will report an error

Solution: Directly introduce jstl-related dependencies

<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

4. Spring MVC execution process

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-gThatj88-1678070111801) (note picture/image-20230214110129798.png)]

The execution flow of SpringMVC is as follows :

  1. The user clicks on a request path to initiate an HTTP request request, which will be submitted to DispatcherServlet (front controller);
  2. DispatcherServlet requests one or more HandlerMapping (processor mapper), and returns an execution chain (HandlerExecutionChain).
  3. DispatcherServlet sends the Handler information returned by the execution chain to HandlerAdapter (processor adapter);
  4. HandlerAdapter finds and executes the corresponding Handler (often called Controller) according to the Handler information;
  5. After the Handler is executed, it will return a ModelAndView object to the HandlerAdapter (the underlying object of Spring MVC, including the Model data model and View view information);
  6. After the HandlerAdapter receives the ModelAndView object, it returns it to the DispatcherServlet;
  7. After DispatcherServlet receives the ModelAndView object, it will request ViewResolver (view resolver) to resolve the view;
  8. ViewResolver matches the corresponding view result according to View information, and returns it to DispatcherServlet;
  9. After receiving the specific View view, DispatcherServlet renders the view, fills the model data in the Model into the request field in the View view, and generates the final View (view);
  10. Views are responsible for displaying results to the browser (client).

5. @Controller annotation and @RequestMapping annotation

1. @Controller annotation

Function: Implement a controller class to add instances to the IOC container by scanning

To use this annotation, Spring automatic package scanning needs to be enabled

<!-- 自动包扫描实例注入 -->
       <context:component-scan base-package="com.huawei.mvcdemo2023" />

Controller class case

// 不需要实现Controller接口
@Controller
public class LoginController {
    
    

}

2. @RequestMapping annotation

@RequestMapping is responsible for mapping the request to the corresponding controller method.

In the annotation-based controller class, you can write the corresponding processing method for each request.

Use the @RequestMapping annotation to match the request with the processing method one by one.

The @RequestMapping annotation can be used on classes or methods . Used on a class, it means that all methods in the class that respond to requests use this address as the parent path.

Simple case:

@Controller
public class LoginController {
    
    
    // 可以通过http://localhost:8080/demo/doLogin访问 且请求类型要求为GET请求
    @RequestMapping(value = "/doLogin",method = RequestMethod.GET)
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }
}

1. @RequestMapping annotation parameters

1. value parameter

The value attribute is the default attribute of the @RequestMapping annotation, so if there is only the value attribute, the attribute name can be omitted, and if there are other attributes, the value attribute name must be written.

Explicit declaration:

	// http://localhost:8080/demo/doLogin能访问
    @RequestMapping(value = "/doLogin")
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

The value attribute can be implicitly declared

// http://localhost:8080/demo/doLogin能访问
@RequestMapping("/doLogin")
public void aa(){
    
    
    System.out.println("doLogin被调用!!!!!");
}

Use of wildcards

// http://localhost:8080/demo/doLogin/aa/bb/cc 能访问
    @RequestMapping(value = "/doLogin/*")
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

2. path parameter

Its function is exactly the same as value, with the only difference: path cannot be implicitly declared, and the implicitly declared value will be assigned to the value attribute

// http://localhost:8080/demo/doLogin/aa/bb/cc 能访问
    @RequestMapping(path = "/doLogin/*")
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

3. name parameter

Function: Describe the requested function

Multi-parameter writing, separated by commas

@RequestMapping(path = "/doLogin/*",name="测试使用")
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

4.method parameters

Function: Specify the type of request that is allowed to access, if it is unqualified, a 405 error will be thrown

Type writing:

GET request: RequestMethod.GET

POST request: RequestMethod.POST

PUT request; RequestMethod.PUT

DELETE request: RequestMethod.DELETE

Generally, the request type must be specified, otherwise it means that all request types can be accessed

// http://localhost:8080/demo/doLogin,且为GET请求能访问
    @RequestMapping(value = "/doLogin",method = RequestMethod.GET)
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

5. params parameter

Function: specify the parameters that must be included in the request, and even specify what values ​​the parameters must carry

Usage 1: It is stipulated that a specified parameter must be carried

// http://localhost:8080/demo/doLogin?type=1,必须要有type参数,且为GET请求能访问
    @RequestMapping(value = "/doLogin",params = "type",method = RequestMethod.GET)
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

Usage 2: It is stipulated that a certain parameter must be carried and what is the value

// http://localhost:8080/demo/doLogin?type=1,必须要有type且值为1,且为GET请求能访问
    @RequestMapping(value = "/doLogin",params = "type=1",method = RequestMethod.GET)
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

6. header parameters

Control the parameters and values ​​that the request header must carry

@RequestMapping(value = "/doLogin",headers = "Referer=http://www.xxx.com",method = RequestMethod.GET)
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

7.consumers parameters

Control the value of request content-Type

// 描述请求的数据必须为json,注意是!!!请求!!!!
@RequestMapping(value = "/doLogin",consumes = "application/json",method = RequestMethod.GET)
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

3. Use annotation configuration to realize the jump of logical view

When the controller method does not return any logical view name, the url mapping path will be interpreted as the logical view name, such as:

@RequestMapping(value = "/doLogin",method = RequestMethod.GET)
    public void aa(){
    
    
        System.out.println("doLogin被调用!!!!!");
    }

// 则会跳转到 /WEB-INF/views/doLogin.jsp

Standard writing:

/**
     * 返回值为String的方法,是用于跳转逻辑视图的
     * @return String返回值:就是返回逻辑视图名称即可
     */
    @RequestMapping(value = "/testclass/toLogin")
    public String toLogin(){
    
    
        System.out.println("--- 跳转到登录页面");
        return "login";//返回逻辑视图名
    }

Function module parent path writing method

@Controller
@RequestMapping("/testclass")
public class LoginController {
    
    

    /**
     * 返回值为String的方法,是用于跳转逻辑视图的
     * @return String返回值:就是返回逻辑视图名称即可
     访问该方法:/testclass/toLogin
     */
    @RequestMapping(value = "/toLogin")
    public String toLogin(){
    
    
        System.out.println("--- 跳转到登录页面");
        return "login";//返回逻辑视图名
    }

    @RequestMapping(value = "/toRegister")
    public String toRegister(){
    
    
        System.out.println("--- 跳转到登录页面");
        return "login";//返回逻辑视图名
    }

}

4.Controller method parameters

1. The formal parameters in the method are used to receive the parameters passed by the request

/**
     * 返回值为String的方法,是用于跳转逻辑视图的
     * @return String返回值:就是返回逻辑视图名称即可
     */
    @RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public String toLogin(String userName,String pwd){
    
    
        System.out.println("--- 跳转到登录页面");
        System.out.println("用户名:"+userName);
        System.out.println("密码:"+pwd);
        return "login";//返回逻辑视图名
    }

Test request:

http://localhost:8080/mvc/testclass/toLogin?userName=admin&pwd=123

2. Objects in Servlet API can be injected

request, response, session

@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public String toLogin(HttpSession session, HttpServletRequest request){
    
    
        System.out.println("--- 跳转到登录页面");
        System.out.println(session.getId());
        System.out.println(request.getParameter("userName"));
        return "login";//返回逻辑视图名
    }

3. The method parameter is Model (data model)

Function: The data of the model and the view will be returned to the view layer for rendering

controller:

// Model:相当于一个数据包
    @RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public String toLogin(Model model){
    
    
        System.out.println("--- 跳转到登录页面");
        // 在jsp页面中可以使用${键的名称}取出值
        model.addAttribute("name","高靖博");
        return "login";//返回逻辑视图名
    }

jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    登录页面
    ${name}
</body>
</html>

5. The return value of the Controller method

  1. ModelAndView (returns data and view)
  2. Model (Define Model in parameters)
  3. A Map containing model properties
  4. A String representing the logical view name (jump page)
  5. void
  6. any other Java type

1. ModelAndView

@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public ModelAndView toLogin(){
    
    
        System.out.println("--- 跳转到登录页面");

        ModelAndView mv = new ModelAndView();
        mv.setViewName("login");//设置逻辑视图名称
        mv.addObject("name","高启强");//给model数据包添加数据返回到视图层渲染

        return mv;
    }

2.Model returns data (model is defined in the parameter)

// Model:相当于一个数据包
    @RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public String toLogin(Model model){
    
    
        System.out.println("--- 跳转到登录页面");
        // 在jsp页面中可以使用${键的名称}取出值
        model.addAttribute("name","高靖博");
        return "login";//返回逻辑视图名
    }

4. The return value is String to represent the page jump

@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public String toLogin(String userName,String pwd){
    
    
        System.out.println("--- 跳转到登录页面");
        
        return "login";//返回逻辑视图名
    }

5.void has no return value

The redirected view is the view with the same name as the url mapping path

@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public void toLogin(String userName,String pwd){
    
    
        System.out.println("--- 跳转到登录页面");
    }
//跳转到 toLogin.jsp

6. Spring MVC passes parameters (Controller method receives parameters - associated 5-4-1 content)

There are many ways for Spring MVC Controller to receive request parameters, some are suitable for get request, some are suitable for post request, and some are suitable for both. There are mainly the following methods: Receive request parameters through the entity bean Receive request parameters through the formal parameters of the processing method Receive request parameters through HttpServletRequest (ancestor-servlet) Receive request parameters in the URL through @PathVariable Receive request parameters through @RequestParam through @ ModelAttribute receives request parameters (may not be mastered)

1. Use Entity Bean to receive

Scope of use: both GET and POST requests can be used (PUT, DELETE)

@RequestMapping(value = "/test",method = RequestMethod.POST)
    // 形参处使用自定义对象(VO对象)
    public String test(UserDto user){
    
    
        System.out.println("-- 测试方法");
        System.out.println(user);
        return "main";
    }

2. Receive request parameters by enumerating formal parameters

Scope of use: both GET and POST requests can be used (PUT, DELETE)

@RequestMapping(value = "/test",method = RequestMethod.POST)
    // 形参处使用自定义对象(VO对象)
    public String test(String name,int age){
    
    
        System.out.println("-- 测试方法");
        System.out.println(user);
        return "main";
    }

4. @PathVariable receives the request parameters in the URL

Such as: http://localhost:8080/mvc/test/admin

I need to cut out the "admin" in the path and map it to the parameter

Pros: Keep parameter names private

Scope of use: both GET and POST requests can be used (PUT, DELETE)

Note: Formal parameters can only use String and other basic data types and wrapper types

@RequestMapping(value = "/test/{name}/{pwd}",method = RequestMethod.POST)
    public String test(@PathVariable String name,@PathVariable String pwd){
    
    
        System.out.println("-- 测试方法");

        System.out.println(name);
        System.out.println(pwd);

        return "main";
    }

5. @RequestParam receives request parameters

@RequestParam use:

value attribute: realize the association of parameters with different names

required: Whether it is required, the default is true, which means that the corresponding parameter name must be included in the request, and an exception will be thrown if it does not exist

defaultValue: parameter default value

Scope of use: both GET and POST requests can be used (PUT, DELETE)

Note: @RequestParam parameters can only use String and other basic data types and wrapper types

@RequestMapping(value = "/test",method = RequestMethod.POST)
    public String test(@RequestParam(value = "userName",defaultValue = "妈耶!") String name, String pwd){
    
    
        System.out.println("-- 测试方法");

        System.out.println(name);
        System.out.println(pwd);

        return "main";
    }

7. SpringMVC request forwarding and redirection

1. Request forwarding

1. Simple case:

@RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test(){
    
    
        System.out.println("-- 测试方法");
        
        return "forward:/testclass/test2";// forward:开头加上另一个controller方法的路径
    }

2. Passing of forwarding process parameters

During the forwarding process, the parameters will also be passed together

@RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test(String name){
    
    // 假设接收name=123
        System.out.println("-- 测试方法");
        System.out.println(name); // 123
        return "forward:/testclass/test2";
    }

    @RequestMapping(value = "/test2",method = RequestMethod.GET)
    public String test2(String name){
    
    
        System.out.println("-- 测试方法2");
        System.out.println(name); //123
        return "main";
    }

3. Pass the ServletAPI object during the forwarding process

During the forwarding process, related API objects will also be passed along

Note: When forwarding, the method of sending forwarding and the method of receiving forwarding, the request type of the constraint must be the same, otherwise 405 will occur

@RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test(HttpServletRequest request){
    
    
        System.out.println("-- 测试方法");
        request.setAttribute("name","123");
        return "forward:/testclass/test2";
    }

    @RequestMapping(value = "/test2",method = RequestMethod.GET)
    public String test2(HttpServletRequest request){
    
    
        System.out.println("-- 测试方法2");
        request.getAttribute("name");
        return "main";
    }

2. Request redirection

Request and response objects cannot be shared, because the client will re-request

Note: Request redirection sends a get request, so it cannot be redirected to a post request

@RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test(String name){
    
    
        System.out.println("-- 测试方法");

        return "redirect:/testclass/test2";
    }

3. Forward or access non-view resolver resources (static resources)

Configure loading static resources

xmlns:mvc="http://www.springframework.org/schema/mvc"

<!-- 静态资源目录 -->
       <mvc:annotation-driven />
       <mvc:resources location="/static/" mapping="/static/**" /><!-- 可以写多个 -->

Test forwarding to a static page

@RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test(){
    
    
        System.out.println("-- 测试方法");
        return "forward:/static/404.html";// 转发、重定向静态资源时只能是GET请求
    }

8. SpringMVC-@Service annotation and @Autowired, @Resource annotation

The significance of using the @Service annotation is to realize the three-tier architecture model of the project: C (Controller Controller), S (Service Business Layer), D (Dao Persistence Layer)

The purpose is to achieve three-layer decoupling, and use the method of interface-oriented programming

Controller layer case

@Controller
@RequestMapping("/testclass")
public class LoginController {
    
    

    // 推荐使用resource注解根据实现类的name注入
    // 实现控制层与业务层的解耦
    @Resource(name = "testClassServiceImpl")
    private TestClassService testClassService;
    
    @RequestMapping(value="/doLogin",method = RequestMethod.POST)
    public String doLogin(UserDto dto,HttpSession session){
    
    
        System.out.println("--- 进行登录验证");

        // 控制器层直接面向接口调用即可
        MyResult result = testClassService.doLogin(dto);

        //忽略登录验证
        session.setMaxInactiveInterval(60 * 30);
        session.setAttribute("userName",dto.getUserName());
        
        return "main";
    }
    
}

Service interface

// 业务接口层定义业务实现的方法,建议统一返回相同结果类型,如我们课程中定义的MyResult类型
public interface TestClassService {
    
    

    MyResult doLogin(UserDto dto);

}

service implementation

// 描述-这是一个业务实现层
    // <bean id="testClassServiceImpl" class="xxxx.TestClassServiceImpl">
// service注解可添加参数(""),参数字符串描述的就是实例bean的name,提供给注入时连线使用
@Service
public class TestClassServiceImpl implements TestClassService {
    
    

    public MyResult doLogin(UserDto dto) {
    
    

        String sys_name = "admin";
        String sys_pwd = "123456";

        MyResult result = new MyResult();

        if(sys_name.equals(dto.getUserName())&&sys_pwd.equals(dto.getPwd())){
    
    
            result.setMsg("登录成功!");
        }else{
    
    
            result.setCode("9999");
            result.setMsg("用户名或密码错误!");
        }

        return result;
    }
}

9. Data type converter Converter

Function: When the controller method receives parameters, it can convert data of different types

Type conversion occurs when views and controllers pass data to and from each other. The Spring MVC framework has already done basic type conversion for basic types (such as int, long, float, double, boolean, and char, etc.). Note: When using the built-in type converter, the input value of the request parameter must be compatible with the type of the received parameter, otherwise a 400 error will be reported.

Many converters have been built in SpringMVC, such as implementing the method of converting String to int. These converters are called "scalar converters".

insert image description here
insert image description here

1. Custom type converter

Implementation process:

  1. Create entity classes.
  2. Create a controller class.
  3. Create a custom type converter class.
  4. Register type converters.
  5. Create related views.

Realization case: For example, users are required to enter information in a page form to create product information. When "gaojingbo, 27, 2.3" is entered, it means that a new User is automatically created in the program, and the value of "gaojingbo" is automatically assigned to the name attribute, the value of "27" is automatically assigned to the age attribute, and the value of "2.3" is automatically assigned Give the height property.

Entity class:

@Data
public class PersonDto implements Serializable {
    
    

   private String name;
   private int age;
   private double height;

}

controller method

@RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test(@RequestParam("dto") PersonDto dto){
    
    
        System.out.println("-- 测试方法");
        System.out.println(dto);
        return "main";
    }

converter

/**
 * 模块名称:字符串转换为Person对象的类型转换器
 * 模块类型:类型转换器
 * 编码人:高靖博
 * 创建时间:2023/2/15
 * 联系电话:18587388612
 */
public class StringToPersonConverter implements Converter<String, PersonDto> {
    
    

    public PersonDto convert(String source) {
    
    //gaojingbo,18,2.8

        //数据格式校验
        // 1. 长度校验
        String[] arr = source.split(",");
        if(arr.length!=3){
    
    
            System.err.println("转换的数据格式不正确,请以:名称,年龄,身高  来传递.");
        }
        // 2. 验证数据类型是否正确
        String age = arr[1];
        boolean numeric = StringUtils.isNumeric(age);
        if(!numeric){
    
    
            System.err.println("数据类型不正确,年龄不能是字符串文字");
        }

        String height = arr[2];
        try{
    
    
            Double dd = new Double(height);
        }catch (Exception e){
    
    
            System.err.println("数据类型不正确,身高不能是字符串文字");
        }

        PersonDto dto = new PersonDto();

        dto.setName(arr[0]);
        dto.setAge(Integer.valueOf(arr[1]));
        dto.setHeight(Double.valueOf(arr[2]));

        return dto;
    }
}

springmvc configuration file registration converter

<!-- 注册类型转换器 -->
       <mvc:annotation-driven conversion-service="conversionService" />
       <!-- 注册转换器工厂类 -->
       <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
              <property name="converters">
                     <list>
                            <bean class="com.huawei.mvcdemo2023.testClass.converters.StringToPersonConverter" />
                     </list>
              </property>
       </bean>

test interface

http://localhost:8080/mvc/testclass/test?dto=admin,18,7.8

10. Data formatting Formatter

The Formatter of the Spring MVC framework, like Converter<S, T>, is also an interface that can convert one data type into another data type. The difference is that the source type of Formatter must be String type, while the source type of Converter can be any data type. Formatter is more suitable for Web layer, while Converter can be in any layer. So for cases where user input in a form needs to be converted, Formatter should be chosen instead of Converter. In the web application, the request data sent by HTTP is obtained in the controller as String type, so it is more reasonable to choose Formatter than Converter<S, T> in web application.

1. Built-in format converter

  1. NumberFormatter: realize the parsing and formatting between Number and String.
  2. CurrencyFormatter: Parsing and formatting between Number and String (with currency symbol).
  3. PercentFormatter: Parsing and formatting between Number and String (with percentage symbol).
  4. DateFormatter: to achieve parsing and formatting between Date and String.

2. Steps to use

Create a formatting class and implement the Formatter interface


/**
 * 模块名称:时间格式化工具
 * 模块类型:格式化转换
 * 编码人:高靖博
 * 创建时间:2023/2/15
 * 联系电话:18587388612
 */
public class MyDateFormatter implements Formatter<Date> {
    
    

    /**
     * 将String---》Date
     * @param text 参数字符串
     * @param locale 本机配置参数
     * @return
     * @throws ParseException
     */
    public Date parse(String text, Locale locale){
    
    

        // 时间格式化工具
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Date parse = null;
        try {
    
    
            parse = sdf.parse(text);
        } catch (ParseException e) {
    
    
            System.err.println("日期格式必须为:yyyy-MM-dd");
        }

        return parse;
    }

    /**
     * Date--->String
     * @param object Date对象
     * @param locale
     * @return 日期字符串
     */
    public String print(Date object, Locale locale) {
    
    

        // 时间格式化工具
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        String format = sdf.format(object);

        return format;
    }
}

Register formatter

<!-- 注册格式化工具 -->
       <bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
              <property name="formatters">
                     <set>
                            <bean class="com.huawei.mvcdemo2023.testClass.formatters.MyDateFormatter" />
                     </set>
              </property>
       </bean>
       <mvc:annotation-driven conversion-service="formattingConversionService" />

controller method test call

@RequestMapping(value = "/test",method = RequestMethod.GET)
    public String test(@RequestParam("date") Date date){
    
    
        System.out.println("-- 测试方法");
        System.out.println(date);
        return "main";
    }

11. @ModelAttribute annotation

Encapsulate the value of the parameter into the model and return to the function of view layer rendering

1. Use annotations on non-@RequestMapping methods and have no return value

The method modified by @ModelAttribute will be called before accessing the target controller method.

Note: There is no order of execution for multiple methods modified by @ModelAttribute. It is recommended that a class only need to write one method modified by this annotation

@Controller
@RequestMapping("/test")
public class TestController {
    
    

    // 可以拦截获取到目标请求的参数
    @ModelAttribute
    public void doModel(String name, Model model){
    
    
        System.out.println("1. 调用doModel方法");
        model.addAttribute("name",name);
    }

    @RequestMapping(value = "/toIndex",method= RequestMethod.GET)
    public String toTest(){
    
    
        System.out.println("2. toTest调用");
        return "testIndex";
    }

}

2. Use annotations on non-@RequestMapping methods with return values

@ModelAttribute
    public String doModel2(String name, Model model){
    
    
        System.out.println("1. 调用doModel2方法");
        
        return "123";// 等同于: model.addAttribute("string","123");
    }

3. Use the annotation in the parameters of the @RequestMapping method

Only write @ModelAttribute annotations, no parameters

Equal to: 1. A Model object is injected into the method, 2. The model.addAttribute method is called

  	3. 添加的数据:key:被修饰参数类型的首字母小写,value:参数对象
  	3.  然后返回视图
@RequestMapping(value = "/toIndex",method= RequestMethod.GET)
    public String toTest(@ModelAttribute UserDto dto){
    
    
        // model.addAttribute("userDto",dto);
        System.out.println("2. toTest调用");
        System.out.println(dto);
        return "testIndex";
    }

Write @ModelAttribute annotations and add parameters

 @RequestMapping(value = "/toIndex",method= RequestMethod.GET)
    public String toTest(@ModelAttribute("cxk") UserDto dto){
    
    
        // model.addAttribute("cxk",dto);
        System.out.println("2. toTest调用");
        System.out.println(dto);
        return "testIndex";
    }

4. Define the method that the controller inherits from other classes

The calling process is equivalent to the effect of defining the ModelAttribute method in the class, but the code is separated and decoupled by inheritance

ModelAttribute class

public class BaseController1{
    
    

    @ModelAttribute
    public void base1(){
    
    
        System.out.println("1-1 base1");
    }
}

controller class

@Controller
@RequestMapping("/test")
public class TestController extends BaseController1{
    
    


    @RequestMapping(value = "/toIndex",method= RequestMethod.GET)
    public String toTest(){
    
    
        System.out.println("2. toTest调用");
        return "testIndex";
    }

}

4.Model object and ModelAndView object

1. Model object

Represents a packet.

It is declared and used in the controller method parameter

Can only add data back to view layer rendering

 @RequestMapping(value = "/toIndex",method= RequestMethod.GET)
    public String toTest(Model model){
    
    
        model.addAttribute("cxk",dto);
        return "testIndex";
    }

2. ModelAndView object

Represents data packages and view objects (view and data are combined into one)

It is used in the return value of the controller method and needs to be created manually

It can not only add data back to the view layer rendering, but also specify who the returned view is

 @RequestMapping(value = "/toIndex",method= RequestMethod.GET)
    public ModelAndView toTest(){
    
    
        ModelAndView mv = new ModelAndView();
        mv.addAttribute("cxk",dto);//添加数据
        mv.setViewName("testIndex");// 指定返回的逻辑视图
    }

12. Data interaction of SpringMVC-JSON

1. Json data structure

1. Object structure

{
    
    
    name:"admin",// 字符串或字符类型使用单引号或双引号描述
    age:18,// 数值类型直接写数字
    height:2.7,
    isOk:true,
    arr:[],// 描述集合使用中括号
    arr2:[
        18,"aaa",18.9
    ],
    arr3:[
        {
    
    name:"张三",age:18},
        {
    
    name:"张三2",age:19}
    ]
}

2. Array structure

{
    
    
    11,12,13,"dasdas"
}

2. SpringMVC implements interactive conversion of Json data

In order to realize the JSON data interaction between the browser and the controller class, Spring MVC provides the MappingJackson2HttpMessageConverter implementation class to process the JSON format request response by default. This implementation class uses the Jackson open source package to read and write JSON data, converts Java objects into JSON objects and XML documents, and can also convert JSON objects and XML documents into Java objects.

Two important JSON format conversion annotations are needed when developing with annotations, namely @RequestBody and @ResponseBody.

@RequestBody : Used to bind the data in the request body to the formal parameters of the method, and this annotation is applied to the formal parameters of the method.

@ResponseBody : Used to directly return the return object, this annotation is applied to the method. The method with this annotation will no longer implement the logical view jump function

1. Import jsckson dependencies

<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.12.3</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.12.3</version>
    </dependency>

As long as the import is successful, the @ResponseBody@RequestBody annotation can be used normally for json conversion and response json functions

2. @RequestBody annotation

When using this annotation to verify parameters, be sure to ensure that it is a post request

1. Respond to a json object\process a json request parameter

Login case:

front-end code

// 复杂json参数格式时,要使用json字符串方式提交
        var param = {
    
    
            userName:$("#userName").val(),
            pwd:$("#pwd").val(),
            arr:["张三","李四"]
        };

        $.ajax({
    
    
            url:"<%=basePath%>/testclass/doLogin",
            dataType:"json",//预计后端返回json数据
            type:"POST",
            async:true,
            data:JSON.stringify(param),// 发送的是一个json字符串
            contentType:"application/json;charset=UTF-8",// 设置请求头描述数据内容是一个json
            success:function(data){
    
    
                //data 后端响应的数据报文
                if(data.code=="9999"){
    
    
                    $("#msg").html(data.msg);
                }else{
    
    
                    $("#msg").html('');
                }
            },
            error:function(){
    
    
                alert("请求错误");
            }
        });

controller

@RequestMapping(value="/doLogin",method = RequestMethod.POST)
    @ResponseBody
// @RequestBody 保证前端发送的是json字符串才能映射,否则就会抛出415错误
    public MyResult doLogin(@RequestBody UserDto dto, HttpSession session){
    
    
        System.out.println("--- 进行登录验证");
        MyResult result = new MyResult();

        result = testClassService.doLogin(dto);

        //忽略登录验证
        session.setMaxInactiveInterval(60 * 30);
        session.setAttribute("userName",dto.getUserName());
        
        return result;
    }

Complete case to achieve login (verification code, login verification, login verification)

Implementation process:

1. Related classes: verification code controller, login controller, login entity dto, login business layer interface, login business layer implementation

2. Login function process:

1. The user fills in the form (username, password, verification code)

2. Submit the form (submit the form using the ajax method), first perform form verification, the user name, password, and verification code must be filled in, and the data must be submitted to the backend for processing after the required fields are guaranteed

​ 3. Back-end verification logic: first verify whether the verification code is correct, return the front-end error message if the verification code is incorrect, and enter the user name and password verification process if it is correct (the verification process of the user name and password is completed at the business implementation layer, and the user name and password are dead. Code verification does not need to connect to the database)

4. The verification is over: if it is correct, it will jump to the homepage jsp, if it is wrong, it will refresh asynchronously and prompt the error message

3. Verify user login process:

1. It is necessary to verify whether the user login information is saved in the session before calling the controller target method. If the session fails, return to the login interface to prompt an error message. If the session exists, continue the process

front-end jsp

Login page (login.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%
    String basePath = request.getScheme() +"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
%>
<html>
<head>
    <title>登录页面</title>
    <script type="text/javascript" src="<%=basePath%>/static/lib/jquery-3.5.1.min.js" ></script>
</head>
<body>
<form>
    <label>用户名</label>
    <input id="userName" name="userName" placeholder="请输入用户名.." /><br/>
    <label>密码</label>
    <input id="pwd" name="pwd" placeholder="请输入密码.." /><br/>
    <input id="reqCode" name="reqCode" placeholder="请输入验证码.." />
    <img id="reqCodeImg" src="" title="点击切换验证码" style="cursor:pointer;" οnclick="getReqCode()" /><br/>
    <button type="button" οnclick="doLogin()">登录</button>
    <span id="msg" style="color:red;"></span>
</form>
</body>
<script>

    $(function(){
        //1. 请求验证码
        getReqCode();
    });

    //进行登录
    function doLogin(){

        // 复杂json参数格式时,要使用json字符串方式提交
        var param = {
            userName:$("#userName").val(),
            pwd:$("#pwd").val(),
            reqCode:$("#reqCode").val()
        };

        //表单校验....

        $.ajax({
            url:"<%=basePath%>/testclass/doLogin",
            dataType:"json",//预计后端返回json数据
            type:"POST",
            async:true,
            data:JSON.stringify(param),// 发送的是一个json字符串
            contentType:"application/json;charset=UTF-8",// 设置请求头描述数据内容是一个json
            success:function(data){
                //data 后端响应的数据报文
                if(data.code=="9999"){
                    $("#msg").html(data.msg);
                }else if(data.code=="9998"){
                    getReqCode();//刷新验证码
                    $("#msg").html('验证码过期,已刷新,请从新填写验证码');
                }else{// 登录成功
                    $("#msg").html('');
                    location.href = "<%=basePath%>/testclass/toMain";
                }
            },
            error:function(){
                alert("请求错误");
            }
        });
    }

    //获取验证码
    function getReqCode(){
        $.ajax({
            url:"<%=basePath%>/req/getCode",
            dataType:"json",//预计后端返回json数据
            type:"GET",
            async:true,
            success:function(data){
                //data 后端响应的数据报文
                if(data.code=="9999"){
                    $("#msg").html(data.msg);
                }else{
                    $("#reqCodeImg").attr("src",data.data);
                }
            },
            error:function(){
                alert("请求错误");
            }
        });
    }


</script>
</html>

Homepage (main.jsp)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
   主页-欢迎<%= session.getAttribute("userName")%>

    // 请求其他数据的ajax

</body>
</html>

backend code

login controller

package com.huawei.mvcdemo2023.testClass.controller;

import com.huawei.mvcdemo2023.core.dto.MyResult;
import com.huawei.mvcdemo2023.testClass.dto.UserDto;
import com.huawei.mvcdemo2023.testClass.service.TestClassService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

/**
 * 模块名称:登录模块
 * 模块类型:控制器(C)
 * 编码人:高靖博
 * 创建时间:2023/2/14
 * 联系电话:18587388612
 */
// 不需要实现Controller接口
@Controller
@RequestMapping("/testclass")
public class LoginController {
    
    

    @Resource(name = "testClassServiceImpl")
    private TestClassService testClassService;
    
    /**
     * 跳转到登录页面
     * @return
     */
    @RequestMapping(value = "/toLogin",method = RequestMethod.GET)
    public String toLogin(){
    
    
        System.out.println("-- 跳转到登录页面");
        return "login";
    }


    /**
     * 跳转到主页页面
     * @return
     */
    @RequestMapping(value = "/toMain",method = RequestMethod.GET)
    public String toMain(){
    
    
        System.out.println("-- 跳转到主页页面");
        return "main";
    }
    
    @RequestMapping(value="/doLogin",method = RequestMethod.POST)
    @ResponseBody
    public MyResult doLogin(@RequestBody UserDto dto, HttpSession session){
    
    
        System.out.println("--- 进行登录验证");
        MyResult result = new MyResult();

        Object reqCode = session.getAttribute("reqCode");
        if(reqCode==null){
    
    
            result.setMsg("验证码过期请刷新!");
            result.setCode("9998");
            return result;
        }else{
    
    

            String reqCodeStr = (String) reqCode;

            if(!reqCodeStr.equalsIgnoreCase(dto.getReqCode())){
    
    
                result.setMsg("验证码错误!");
                result.setCode("9999");
                return result;
            }
        }


        result = testClassService.doLogin(dto);

        if(result.getCode().equals("0000")){
    
    //登录成功时再设置session
            session.setMaxInactiveInterval(60 * 30);
            session.setAttribute("userName",dto.getUserName());
        }
        
        return result;
    }
    
    /**
     * 跳转到注册页面
     * @return
     */
    @RequestMapping(value = "/toRegister",method = RequestMethod.GET)
    public String toRegister(){
    
    
        System.out.println("-- 跳转到注册页面");
        return "register";
    }
}

13. SpringMVC-Integrate Restful

The springmvc 5.2.3 version has implemented the restful specification

If a put or delete request does not enter the corresponding method

A filter needs to be configured in the web.xml file

insert image description here

14. SpringMVC-filter

What is a filter?

Depends on the servlet container . In terms of implementation , based on function callbacks , almost all requests can be filtered , but the disadvantage is that a filter instance can only be called once when the container is initialized .

The purpose of using filters is to do some filtering operations to obtain the data we want to obtain, such as: modify the character encoding in the filter; modify some parameters of HttpServletRequest in the filter, including: filter vulgar text, dangerous characters, etc.

In short, the filter is actually to filter all requests, obtain the data carried by the request or modify some parameters of the request.

1. Built-in filter - charset filter

Configuration in web.xml

<!-- springMVC自带过滤器- 实现参数、响应编解码一致的过滤器 -->
    <filter>
        <description>字符集过滤器</description>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <!-- forceEncoding:true
                    请求、响应都会进行字符编码集的转换
                       request.setCharacterEncoding(“”);
                       response.setCharacterEncoding(“”);
                  forceEncoding:false (默认)
                      只在请求时转换字符编码集
                  request.setCharacterEncoding(“”);
               -->
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!-- 所有的请求都会进入字符集过滤器 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

2. Custom Filters

  1. Define a class that implements the Filter interface
  2. Three methods to implement the filter interface: initialization method, dofilter method and destruction method
  3. Configure filters in web.xml

chain.doFilter(request, response); The call of this method acts as a watershed. In fact, calling the Servlet's doService() method is performed in this method.

filter case

public class MyTestFilter implements Filter {
    
    
    //初始化方法
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
        System.out.println("--- MyTestFilter初始化");
        String what = filterConfig.getInitParameter("what");//可以获取web.xml 中filter标签里配置的初始化参数
        System.out.println(what);
    }

    //执行拦截方法
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        System.out.println("--- 进入过滤器:MyTestFilter");

        //胡作非为(请求添加参数、改变contentType、改变head)
        servletRequest.setAttribute("name","cxk");

        //控制请求是否放行
        filterChain.doFilter(servletRequest,servletResponse);//放行
    }

    //销毁方法
    public void destroy() {
    
    
        System.out.println("--- MyTestFilter被销毁");
    }
}

configure filter

<!-- 自定义过滤器 -->
    <filter>
        <description>自定义过滤器</description>
        <filter-name>myFilter1</filter-name>
        <filter-class>com.huawei.mvcdemo2023.testClass.filters.MyTestFilter</filter-class>
        <init-param>
            <param-name>what</param-name>
            <param-value>123456</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>myFilter1</filter-name>
        <url-pattern>/test/*</url-pattern>
    </filter-mapping>

15. SpringMVC-Interceptor

What is an interceptor?

It is implemented based on Java's jdk dynamic generation and implements the HandlerInterceptor interface. Does not depend on the servlet container , the interceptor is aimed at the controller method , and can obtain all classes, implement interception on all methods in the class , the granularity is smaller , the interceptor can inject service , and can also call business logic.

Implementation of the interceptor

Defined by implementing the HandlerInterceptor interface or an implementation class that inherits the HandlerInterceptor interface (such as HandlerInterceptorAdapter);

Defined by implementing the WebRequestInterceptor interface or an implementation class that inherits the WebRequestInterceptor interface

Method Description

HandlerInterceptor interface, and implements the three methods in the interface, as follows:

preHandle( ) : This method is executed before the processing request method of the controller . Its return value indicates whether to interrupt the subsequent operation . Returning true indicates that the execution continues downward, and returning false indicates that the subsequent operation is interrupted .

postHandle( ) : This method is executed after the controller's processing request method is called and before the view is parsed. This method can be used to further modify the model and view in the request domain.

afterCompletion( ) : This method is executed after the processing request method of the controller is executed , that is, it is executed after the view rendering is completed . Through this method, some tasks such as resource cleaning and log information recording can be realized.

Interceptor code:

public class MyTestInterceptor implements HandlerInterceptor {
    
    

    // 在调用目标controller方法“前”会被调用
    // 返回值:true代表放行,false代表拦截住不继续往下执行
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        System.out.println("拦截器:preHandle");
        return true;
    }

    // 在调用目标controller方法“后”,解析视图之"前"
    // 可以让编程者,控制最终视图的走向、以及视图中携带的数据内容是否发生更改
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
    
        System.out.println("拦截器:postHandle");
    }

    // 在调用目标controller方法“后”,以及视图渲染完成,数据返回成功才执行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
    
        System.out.println("拦截器:afterCompletion");
    }
}

In the springmvc configuration file

mvc:interceptors : This element is used to configure a set of interceptors.

: This element is a child element of mvc:interceptors, which is used to define a global interceptor, which intercepts all requests.

mvc:interceptor : This element is used to define the interceptor for the specified path.

mvc:mapping : This element is a child element of mvc:interceptor, which is used to configure the path of the interceptor, which is defined in its attribute path. When the attribute value of path is /**, it means to intercept all paths, and when the value is /gotoTest, it means to intercept all paths ending with /gotoTest. If the request path contains content that does not need to be intercepted, it can be configured through the < mvc :exclude-mapping> sub-element

<!-- 拦截器的配置 -->
       <mvc:interceptors>
              <!-- 定义一个拦截器 -->
              <mvc:interceptor>
                     <!-- 哪些路径进入拦截器 -->
                     <mvc:mapping path="/**"></mvc:mapping>
                     <!-- 描述自定义拦截器实例 -->
                     <bean class="com.huawei.mvcdemo2023.testClass.interceptors.MyTestInterceptor" />
              </mvc:interceptor>
       </mvc:interceptors>

Filter and Interceptor Execution Process

Filter first, blocker second.

preHandler is the handler mapper callback; postHandler is the handlerApter callback

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-YmT9vKCL-1678070111804)(note picture/image-20230216171745106.png)]

16. SpringMVC file upload

2. Two implementation modes

1. Based on CommonsMultipartResolver

1. Import dependencies

<!-- 文件上传和下载 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

2. Configure the file upload parser in the springmvc configuration file

<!-- 文件上传解析器 -->
       <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
              <!-- 单个请求文件上传最大值 -->
              <property name="maxUploadSize" value="50000000000" />
              <!-- 文件上传字符编码集 -->
              <property name="defaultEncoding" value="UTF-8" />
       </bean>

1. Form submission and file upload

front-end code

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%
    String basePath = request.getScheme() +"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
%>
<html>
<head>
    <title>测试</title>
    <script type="text/javascript" src="<%=basePath%>/static/lib/jquery-3.5.1.min.js" ></script>
</head>
<body>
<form action="<%=basePath%>/test/fileUpload" method="POST" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" value="确定上传" />
</form>
</body>
</html>

2. Ajax submission file upload

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%
    String basePath = request.getScheme() +"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
%>
<html>
<head>
    <title>测试</title>
    <script type="text/javascript" src="<%=basePath%>/static/lib/jquery-3.5.1.min.js" ></script>
</head>
<body>
<form id="fileForm">
    <input type="file" name="file" />
    <input type="button" οnclick="doFileUpload()" value="确定上传" />
</form>
</body>
<script>

    function doFileUpload(){
        // ajax 模拟表单提交
        var formData = new FormData($("#fileForm")[0]);

        $.ajax({
            url:"<%=basePath%>/test/fileUpload",
            dataType:"json",
            type:"POST",
            async:true,
            cache:false,// 去除缓存影响
            processData: false, // 规定通过请求发送的数据是否转换为查询字符串,设置为否
            contentType:false,// 不设置任何的mime类型以二进制方式发送
            data:formData,
            success:function(data){
                console.dir(data);
            },
            error:function(){
                alert("请求错误");
            }
        });

    }

</script>
</html>

3. The back-end parses the file and writes it to the disk to complete the upload

The path to write to disk can be written in the configuration file

web.xml 配置文件中配置:
<context-param>
        <param-name>uploadPath</param-name>
        <param-value>F:\\sysFile</param-value>
    </context-param>

controller method

@RequestMapping(value = "/fileUpload",method = RequestMethod.POST)
    @ResponseBody
    public MyResult fileUpload(MultipartFile file, HttpServletRequest request){
    
    
        MyResult res = new MyResult();

        System.out.println("--- 文件上传!");
        //文件要上传的位置(通过配置文件加载)
        ServletContext servletContext = request.getServletContext();
        String uploadPath = servletContext.getInitParameter("uploadPath");

        //上传文件
        try {
    
    
            byte[] fileBytes = file.getBytes();

            //文件名称
            String originalFilename = file.getOriginalFilename();
            //文件后缀
            String fileSub = originalFilename.substring(originalFilename.lastIndexOf("."));

            //加密的文件名称
            String fileID = UUID.randomUUID().toString().replaceAll("-", "");

            //要创建的文件路径
            String newFile = uploadPath + "\\" + fileID + fileSub;

            //写出
            file.transferTo(new File(newFile));

        } catch (IOException e) {
    
    
            e.printStackTrace();
            res.setMsg("文件上传出错!");
            res.setCode("9999");
            return res;
        }

        res.setMsg("文件上传成功!");

        return res;
    }

17. SpringMVC file download

1. Use the servlet method to download files

@RequestMapping(value = "/filedownload",method = RequestMethod.GET)
    @ResponseBody
    public void filedownload(HttpServletRequest request, HttpServletResponse response){
    
    

        System.out.println("--- 文件下载");

        //要下载的文件。带后缀(固定下载这个文件)
        String needDownLoad = "d10fb3edd4cc43b7be5da10aef985fcc.png";

        //设置响应头
        response.setHeader("Content-Type", "application/x-msdownload");//描述是文件下载
        try {
    
    
            response.setHeader("Content-Disposition", "attachment;filename="+this.toUTF8(needDownLoad));//下载文件的名称
        } catch (UnsupportedEncodingException e) {
    
    
            System.err.println("文件下载错误:文件名称编码错误!");
            e.printStackTrace();
        }


        //获取文件保存的文件夹
        ServletContext servletContext = request.getServletContext();
        String uploadPath = servletContext.getInitParameter("uploadPath");

        try {
    
    
            //读出来
            FileInputStream fileInputStream = new FileInputStream(uploadPath + "\\" + needDownLoad);

            byte [] fileByte = new byte[fileInputStream.available()];

            fileInputStream.read(fileByte);
            fileInputStream.close();

            //写出去(使用响应对象写出)
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(fileByte);
            outputStream.flush();
            outputStream.close();


        } catch (IOException e) {
    
    
            System.err.println("文件下载错误!");
            e.printStackTrace();
        }


    }

    // 将字符串进行utf-8编解码
    private String toUTF8(String tarStr) throws UnsupportedEncodingException {
    
    

        byte[] bytes = tarStr.getBytes("UTF-8");

        String s = new String(bytes, "UTF-8");

        return s;
    }

2. Mvc+commonse-io file download method

@RequestMapping(value = "/mvcDownload",method=RequestMethod.GET)
    public ResponseEntity<byte[]> mvcDownload(HttpServletRequest request){
    
    
        System.out.println("-- mvc文件下载");
        //要下载的文件。带后缀(固定下载这个文件)
        String needDownLoad = "d10fb3edd4cc43b7be5da10aef985fcc.png";

        //获取文件保存的文件夹
        ServletContext servletContext = request.getServletContext();
        String uploadPath = servletContext.getInitParameter("uploadPath");

        //设置响应头
        HttpHeaders httpHeaders = new HttpHeaders();

        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);//描述是文件下载
        httpHeaders.setContentDispositionFormData("attachment", needDownLoad);// 描述下载文件的名称

        ResponseEntity<byte[]> responseEntity = null;

        try {
    
    
            responseEntity = new ResponseEntity<byte[]>(
                    FileUtils.readFileToByteArray(new File(uploadPath + "\\" + needDownLoad)),// 将文件读取成byte数组
                    httpHeaders,//设置响应头
                    HttpStatus.CREATED // 设置Http响应的初始状态
            );
        } catch (IOException e) {
    
    
            System.err.println("mvc文件下载错误!");
            e.printStackTrace();
        }

        return responseEntity;

    }

Web project file management design

insert image description here

Guess you like

Origin blog.csdn.net/gjb760662328/article/details/129356600