[SSM Framework] Getting Started with SpringMVC

1. What is SpringMVC

1 Overview

Spring MVC is part of the Spring Framework and is a lightweight web framework based on Java that implements MVC.

Check out the official documentation: Spring MVC

Advantages of Spring MVC:

  1. Lightweight and easy to learn
  2. Efficient, request-response based MVC framework
  3. Good compatibility with Spring and seamless integration
  4. Convention over configuration
  5. Powerful functions: RESTful, data validation, formatting, localization, themes, etc.
  6. Simple and flexible

Spring's web framework is designed around DispatcherServlet [Scheduling servlet]

The role of DispatcherServlet is to distribute requests to different processors. Starting from Spring 2.5, users using Java 5 or above can develop based on annotations, which is very simple;

2. Central controller

Spring's web framework is designed around DispatcherServlet. The role of DispatcherServlet is to distribute requests to different processors. Starting from Spring 2.5, users of Java 5 or above can use annotation-based controller declaration.

The Spring MVC framework, like many other MVC frameworks, is request-driven , dispatching requests and providing other functions around a central Servlet . DispatcherServlet is an actual Servlet (it inherits from the HttpServlet base class) .

The DispatcherServlet class diagram is as follows:

image-20220516163849517

The principle of SpringMVC is shown in the figure below:

When a request is initiated, the request is intercepted by the preceding controller, a proxy request is generated based on the request parameters, the actual controller corresponding to the request is found, the controller processes the request, creates a data model, accesses the database, responds to the model to the central controller, and controls The processor uses the model and view to render the view results, returns the results to the central controller, and then returns the results to the requester.

image-20220516164434657

3. SpringMVC execution principle

image-20220516170509457

The picture shows a more complete flow chart of SpringMVC. The solid line indicates the technology provided by the SpringMVC framework, which does not require developers to implement it, and the dotted line indicates that it requires developers to implement it.

Briefly analyze the execution process

  1. DispatcherServlet represents the front controller and is the control center of the entire SpringMVC. When the user makes a request, DispatcherServlet receives the request and intercepts the request.

    • We assume that the requested url is: http://localhost:8080/SpringMVC/hello

    • The above url is split into three parts:

    • http://localhost:8080 server domain name

    • SpringMVC web site deployed on the server

    • hello means controller

    • Through analysis, the above URL is expressed as: requesting the hello controller of the SpringMVC site located on the server localhost:8080

  2. HandlerMapping is the processor mapper . DispatcherServlet calls HandlerMapping, and HandlerMapping finds Handler according to the request Url.

  3. HandlerExecution represents a specific Handler. Its main function is to find the controller based on the URL. As shown above, the URL to be searched for the controller is: hello

  4. HandlerExecution passes the parsed information to DispatcherServlet, such as parsing controller mapping, etc.

  5. HandlerAdapter represents the processor adapter , which executes Handler according to specific rules.

  6. Handler lets specific Controller execute

  7. Controller returns specific execution information to HandlerAdapter, such as ModelAndView

  8. HandlerAdapter passes the view logical name or model to DispatcherServlet

  9. DispatcherServlet calls the view resolver (ViewResolver) to resolve the logical view name passed by HandlerAdapter

  10. The view resolver passes the resolved logical view name to DispatcherServlet

  11. DispatcherServlet calls specific views based on the view results parsed by the view parser.

  12. The final view is presented to the user

2. The first mvc program

1. Configuration version

  1. Create a new Moudle, springmvc-02-hello, and add web support!

  2. Make sure you have imported the SpringMVC dependencies!

  3. Configure web.xml and register DispatcherServlet

    <?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">
    
    <!--  配置DispatchServlet:这个是SpringMVC的核心:请求分发器、前端控制器(官方名)  -->
    
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--    DispatchServlet要绑定Spring(MVC)的配置文件 【servlet-name】-servlet.xml   -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
            <!--启动级别:1 和服务器一起启动-->
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!--
        在SpringMVC中
        /   匹配所有的请求;(不包括.jsp)
        /*  匹配所有的请求;(包括.jsp)-->
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
  4. Write the SpringMVC configuration file! Name: springmvc-servlet.xml: [servletname]-servlet.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <!--  处理器映射器  -->
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    
        <!--  处理器适配器  -->
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
        <!--
           视图解析器:DispatcherServlet给他的ModelAndView
           1. 获取了ModelAndView的数据
           2. 解析ModelAndView视图的名字
           3. 拼接视图名字,找到对应的视图 /WEB-INF/jsp/hello.jsp
           4. 将数据渲染到这个视图上!
        -->
        <!--  模板引擎:thymeleaf Freemarker  -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
        <!--  Handler
            这里/hello代表的是URL地址
        -->
        <bean id="/test" class="com.sue.controller.HelloController"/>
            
    </beans>
    
  5. To write the business Controller we want to operate, we must either implement the Controller interface or add annotations; we need to return a ModelAndView, load the data, and seal the view;

    public class HelloController implements Controller {
          
          
        @Override
        public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
          
          
            //ModelAndView 模型和视图
            ModelAndView modelAndView = new ModelAndView();
    
            //业务代码
            String result = "HelloSpringMVC";
    
            //封装对象,放在ModelAndView中。Model
            modelAndView.addObject("msg", result);
    
            //视图跳转
            //封装要跳转的视图,放在ModelAndView中
            //  /WEB-INF/jsp/test.jsp
            modelAndView.setViewName("test");
    
            return modelAndView;
        }
    }
    
  6. Give your own class to the SpringIOC container and register the bean

    <!--  Handler  -->
        <bean id="/test" class="com.sue.controller.HelloController"/>
    
  7. Write the jsp page to be jumped to display the data stored in ModellandView and our normal page;

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    	${msg}
    </body>
    </html>
    
  8. Configure tocmat and start testing

    image-20220515224820194

2. Annotated version

  1. Create a new Moudle, springmvc-03-annotation. Add web support!

    [External link image transfer failed. The source site may have an anti-leeching mechanism. It is recommended to save the image and upload it directly (img-gp3nLofr-1663577047298) (C:\Users\Genius Sue\AppData\Roaming\Typora\typora-user-images \image-20220915105218597.png)]

  2. Since Maven may have resource filtering problems, we will complete the configuration

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
    
  3. Introduce relevant dependencies in the pom.xml file: mainly Spring framework core library, Spring MVC, servlet, JSTL, etc. We have already introduced it in the parent dependency!

  4. Configure web.xml

    <?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">
        <!--    注册DispatcherServlet-->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
            <!-- 启动顺序,数字越小,启动越早 -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <!--所有请求都会被springmvc拦截 -->
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    

    The difference between / and /*:

    • < url-pattern > / </ url-pattern > will not match .jsp, only for the request we wrote; that is: .jsp will not enter spring's DispatcherServlet class
    • < url-pattern > /* </ url-pattern > will match *.jsp. When returning to the jsp view, you will enter the spring's DispatcherServlet class again, resulting in the corresponding controller not being found and a 404 error being reported.
  5. Add SpringMVC configuration file

    springmvc-servlet.xml

    <?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">
    
    
        <!--    自动扫描包,让指定包下的注解生效,有IOC容器统一管理-->
        <context:component-scan base-package="com.zyy.controller"/>
    
        <!--   让Spring MVC不处理静态资源 .css .js .html .mp3 .mp4-->
        <mvc:default-servlet-handler/>
    
        <!--
       支持mvc注解驱动
           在spring中一般采用@RequestMapping注解来完成映射关系
           要想使@RequestMapping注解生效
           必须向上下文中注册DefaultAnnotationHandlerMapping
           和一个AnnotationMethodHandlerAdapter实例
           这两个实例分别在类级别和方法级别处理。
           而annotation-driven配置帮助我们自动完成上述两个实例的注入。
        -->
        <mvc:annotation-driven/>
    
        <!--
        视图解析器:DispatcherServlet给他的ModelAndView
        1. 获取了ModelAndView的数据
        2. 解析ModelAndView视图的名字
        3. 拼接视图名字,找到对应的视图 /WEB-INF/jsp/hello.jsp
        4. 将数据渲染到这个视图上!
        -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
    </beans>
    

    In the view parser, we store all views in the /WEB-INF/ directory, which ensures the security of the views, because the files in this directory cannot be directly accessed by the client.

  6. CreateController

    @Controller
    public class HelloController {
          
          
    
        //真实访问地址:项目名/HelloController/hello
        @RequestMapping("/hello")
        public String hello(Model model){
          
          
            //封装数据
            //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
            model.addAttribute("msg", "Hello,SpringMVCAnnotation");
            
            //WEB-INF/jsp/hello.jsp
            return "hello";//会被视图解析器处理,拼接
        }
    }
    
    • @Controller is to automatically scan the Spring IOC container when it is initialized.
    • @RequestMapping is to map the request path. Since only the method is mapped here, it should be /hello when accessed.
    • The Model type parameter is declared in the method to bring the data in the Action to the view.
    • The result returned by the method is the name hello of the view, plus the suffix and suffix in the configuration file to become WEB-INF/jsp/hello.jsp
  7. Create the view layer hello.jsp

    Create hello.jsp in the WEB-INF/ jsp directory. The view can directly take out and display the information brought back from the Controller.

    The value or object stored in the Model can be retrieved through EL expressions;

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    	${msg}
    </body>
    </html>
    

Three major pieces that must be configured to use springMVC:

Processor mapper, processor adapter, view resolver

Usually, we only need to manually configure the view resolver , and the processor mapper and processor adapter only need to enable the annotation driver .

3. RestFul and Controller

1、Controller

  • The controller is responsible for providing access to the application's behavior, usually through two methods: interface definition or annotation definition.
  • The controller is responsible for parsing the user's request and converting it into a model
  • A controller class in SpringMVC can contain multiple methods
  • There are many ways to configure controllers in SpringMVC

1.1. Implement the Controller interface

  1. Create a new Moudle, springmvc-04-controller

  2. Configure web.xml

    <?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">
    
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    </web-app>
    
  3. Add Spring configuration file springmvc-servlet.xml

    <?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">
    
    
    <!--    <context:component-scan base-package="com.sue.controller"/>-->
    <!--    <mvc:default-servlet-handler/>-->
    <!--    <mvc:annotation-driven/>-->
    
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
        
        
        <bean id="/test1" class="com.sue.controller.ControllerTest1"/>
    
    </beans>
    
  4. Write the front-end test.jsp, pay attention to write it in the WEB-INF/jsp directory, corresponding to our view parser

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    	${msg}
    </body>
    </html>
    
  5. Add Controller class

    //只要实现Controller接口的类,说明这就是个控制器了
    public class ControllerTest1 implements Controller {
          
          
        @Override
        public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
          
          
            ModelAndView modelAndView = new ModelAndView();
    
            modelAndView.addObject("msg", "ControllerTest1");
            modelAndView.setViewName("test");
    
            return modelAndView;
        }
    }
    
  6. Register the requested bean in the Spring configuration file

    <bean id="/test1" class="com.sue.controller.ControllerTest1"/>
    
  7. Configure tomcat and test

illustrate:

  • Implementing the interface Controller to define a controller is an older approach
  • The disadvantage is: there is only one method in a controller. If you want multiple methods, you need to define multiple Controllers; the definition method is more troublesome;

1.2. Use the annotation @Controller

The @Controller annotation type is used to declare that an instance of a Spring class is a controller

  1. Based on the above, annotate the beans in the Spring configuration file, add scanning, and make the annotations take effect.

    (Spring can use the scanning mechanism to find all annotation-based controller classes in the application. In order to ensure that Spring can find your controller, component scanning needs to be declared in the configuration file.)

    <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
     <context:component-scan base-package="com.sue.controller"/>
    
  2. Added ControllerTest2.java

    @Controller //代表这个类会被Spring接管,会自动添加到Spring上下文中
    // 这个注解的类中所有方法,如果返回值是String,
    // 并且有具体的页面可以跳转,那么就会被视图解析器解析
    public class ControllerTest2 {
          
          
        //映射访问路径
        @RequestMapping("/test2")
        public String test1(Model model) {
          
          
            //Spring MVC会自动实例化一个Model对象用于向视图中传值
            model.addAttribute("msg", "ControllerTest2");
            //返回视图名
            return "test";
        }
    }
    

It can be found that both of our requests can point to a view, but the page results are different. It can be seen from this that the view is reused, and there is a weak coupling relationship between the controller and the view.

The annotation method is the most commonly used method!

2、RequestMapping

  • The @RequestMapping annotation is used to map URLs to controllers or a specific processing method. Can be used on classes or methods. Used for classes, indicating that all methods in the class that respond to requests use this address as the parent path.

  • Added ControllerTest3.java

    Only annotate it on the method

    @Controller 
    public class ControllerTest2 {
          
          
        @RequestMapping("/test2")
        public String test1(Model model) {
          
          
            model.addAttribute("msg", "ControllerTest2");
            return "test";
        }
    }
    

    Access path: http://localhost:8080/test2

  • Annotate classes and methods simultaneously

    @Controller
    @RequestMapping("/c3")
    public class ControllerTest3 {
          
          
    
        @RequestMapping("/test3")
        public String test1(Model model){
          
          
            model.addAttribute("msg", "ControllerTest3");
    
            return "test";
        }
    }
    

Access path: http://localhost:8080/c3/test3

3. RestFul style

concept

Restful is a style of resource positioning and resource operation. Not a standard or a protocol, just a style. Software designed based on this style can be simpler, more hierarchical, and easier to implement mechanisms such as caching.

Function

Resources: All things on the Internet can be abstracted into resources

Resource operations: use POST, DELETE, PUT, GET, and use different methods to operate resources

Decibel corresponds to adding, deleting, modifying, and querying

Manipulate resources in traditional ways : achieve different effects through different parameters, single method, post and get

  • http://127.0.0.1/item/queryItem.action?id=1 Query, GET
  • http://127.0.0.1/item/saveItem.action New, POST
  • http://127.0.0.1/item/updateItem.action update, POST
  • http://127.0.0.1/item/deleteItem.action?id=1 Delete, GET or POST

Use RestFul to operate resources: different effects can be achieved through different request methods, as follows: the request address is the same, but the functions can be different

  • http://127.0.0.1/item/1 Query, GET
  • http://127.0.0.1/item New, POST
  • http://127.0.0.1/item update, PUT
  • http://127.0.0.1/item/1 delete,DELETE

study test

  1. Create a new class RestFulController.java

    @Controller
    public class RestFulController {
          
          
    
        //http://localhost:8080/add?a=1&b=2
        @RequestMapping("/add")
        public String add(int a, int b, Model model) {
          
          
            int res = a + b;
            model.addAttribute("msg", "add结果为" + res);
            return "test";
        }
     }
    
  2. Start tomcat and access the test

    http://localhost:8080/add?a=1&b=2

    image-20220518220855977

  3. Add a new restFul request method

    //http://localhost:8080/add/1/2
    @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.GET)
    public String add2(@PathVariable int a, @PathVariable int b, Model model) {
          
          
        int res = a + b;
        model.addAttribute("msg", "add2结果为" + res);
        return "test";
    }
    
  4. Start tomcat and access the test

    http://localhost:8080/add/1/2

    image-20220518221050967

  5. Use post method to request and add a.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
      <form action="/add/1/2" method="post">
        <input type="submit"/>
      </form>
      </body>
    </html>
    
  6. Add a post method

    @RequestMapping(value = "/add/{a}/{b}", method = RequestMethod.POST)
    public String add3(@PathVariable int a, @PathVariable int b, Model model) {
          
          
        int res = a + b;
        model.addAttribute("msg", "add3结果为" + res);
        return "test";
    }
    
  7. It can also be abbreviated as @PostMapping annotation. If the method is the same and the path is the same, PostMapping and RequestMapping cannot exist at the same time, which will cause ambiguity.

    @PostMapping(value = "/add/{a}/{b}")
    public String add4(@PathVariable int a, @PathVariable int b, Model model) {
          
          
        int res = a + b;
        model.addAttribute("msg", "add4结果为" + res);
        return "test";
    }
    
  8. Start tomcat and verify

    http://localhost:8080/add/1/2

    image-20220518222134372

summary

SpringMVC's @RequestMapping annotation can handle HTTP request methods, such as GET, PUT, POST, DELETE and PATCH

All address bar requests will be of type HTTP GET by default.

Variants of method-level annotations are as follows: Combined annotations

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

@GetMapping is a combination annotation, which is commonly used!

It acts as a shortcut for @RequestMapping(method =RequestMethod.GET).

think

What are the benefits of using path variables?

  • Make paths more concise
  • It is more convenient to obtain parameters, and the framework will automatically perform type conversion
  • Access parameters can be restricted by the type of the path variable. If the types are different, the corresponding request method cannot be accessed. For example, the path accessed here is /commit/1/a, then the path does not match the method and will not be a parameter. Conversion failed

4. Data processing and jump

1、ModelAndView

Set the ModelAndView object, jump to the specified page based on the name of the view, and the view parser

Page: {view resolver prefix} + viewName + {view resolver suffix}

Configure view resolver

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

1.1. Implement forwarding and redirection through SpringMVC - no view resolver required

Before testing, you need to comment out the view resolver

@Controller
public class ModelTest1 {
    
    

    @RequestMapping("/m1/t1")
    public String test1(HttpServletRequest request, HttpServletResponse response){
    
    

        HttpSession session = request.getSession();
        System.out.println(session.getId());

        return "/test";
    }

    @RequestMapping("/m1/t2")
    public String test2(Model model){
    
    

        //转发
       model.addAttribute("msg", "ModelTest1");
        return "forward:/WEB-INF/jsp/test.jsp";
    }

    @RequestMapping("/m1/t3")
    public String test3(Model model){
    
    

        //重定向
        model.addAttribute("msg", "ModelTest1");
        return "redirect:/index.jsp";
    }
}

1.2. Implement forwarding and redirection through SpringMVC - with view resolver

Redirection does not require a view resolver. The essence is to re-request a new place, so pay attention to the path issue.

    @RequestMapping(value = "/m1/t5")
    public String test5(Model model) {
    
    
        //转发
        model.addAttribute("msg", "ModelTest1...test5");
        return "test";
    }

    @RequestMapping(value = "/m1/t3")
    public String test3() {
    
    
        //重定向
        return "redirect:/index.jsp";
    }

2. Data processing

2.1. Processing submitted data

  1. The submitted domain name is consistent with the parameter name of the processing method

    @RequestMapping("/user")
    public class UserController {
          
          
    
        // http://localhost:8080/user/t1?name=***
        @GetMapping("/t1")
        public String test1(String name, Model model){
          
          
            //1.接收前端参数
            System.out.println("接收到前端的参数为:"+name);
    
            //2.将返回结果传递给前端
            model.addAttribute("msg", name);
    
            //3.跳转视图
            return "test";
        }
    
  2. The submitted domain name is inconsistent with the parameter name of the processing method

    // http://localhost:8080/user/t1?name=***
        @GetMapping("/t1")
        public String test1(@RequestParam("username") String name, Model model){
          
          
            //1.接收前端参数
            System.out.println("接收到前端的参数为:"+name);
    
            //2.将返回结果传递给前端
            model.addAttribute("msg", name);
    
            //3.跳转视图
            return "test";
        }
    
  3. Submission is an object

    User.java

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
          
          
        private int id;
        private String name;
        private int age;
    }
    

    Add method

       //前端接收的是一个对象:id,name,age
        /*
        * 1.接收前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用
        * 2.假设传递的是一个对象,,匹配对象中的字段名,一直则OK,否则匹配不到
        *
        * */
        @GetMapping("/t2")
        public String test2(User user){
          
          
            System.out.println(user);
            return "test";
        }
    

2.2. Data is displayed on the front end

  1. viaModelAndView

    public class HelloController implements Controller {
          
          
    
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
          
          
            //ModelAndView 模型和视图
            ModelAndView mv = new ModelAndView();
    
            //封装对象,放在ModelAndView中。Model
            mv.addObject("msg", "HelloSpringMVC!");
            //封装要跳转的视图,放在ModelAndView中
            //  /WEB-INF/jsp/hello.jsp
            mv.setViewName("test");
            return mv;
        }
    }
    
  2. by ModelMap

        @GetMapping("/t3")
        public String test3(User user, ModelMap map){
          
          
            System.out.println(user);
            map.addAttribute("msg", "t3");
            return "test";
        }
    
  3. byModel

    @GetMapping("/t2")
    public String test2(User user,Model model){
          
          
        System.out.println(user);
        model.addAttribute("msg", user.toString());
        return "test";
    }
    

Compared

In simple terms for novices, the difference is:

Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解,大部分使用Model;

ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;

ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

Please use 80% of your time to lay a solid foundation, the remaining 18% of your time to study the framework, and 2% of your time to learn some English. The official documentation of the framework is always the best tutorial.

3. Garbled code problem

  1. Create a new form.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    
        <form action="e/t" method="post">
            <input type="text" name="name">
            <input type="submit">
        </form>
    
    </body>
    </html>
    
    
  2. Create a new corresponding processing class in the backend

    @Controller
    public class EncodingController {
          
          
        @PostMapping("/e/t")
        public String test(String name, Model model){
          
          
    
            model.addAttribute("msg", name);
    
            return "test";
        }
    }
    
  3. Start tomcat, enter Chinese, and find garbled characters

Insert image description here

3.1. Custom filters

public class EncodingFilter implements Filter {
    
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");

        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
    
    

    }
}

Register filters in web.xml

<!--    自定义过滤器-->
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>com.sue.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3.2. SpringMVC’s own filters

SpringMVC provides us with a filter that can be configured in web.xml. Modified the xml file and you need to restart the server!

<filter>
    <filter-name>encoding</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>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3.3. Other methods

  1. Modify tomcat configuration file: set encoding!

    <Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
              connectionTimeout="20000"
              redirectPort="8443" />
    
  2. More powerful custom filters

    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.util.Map;
    
    /**
     * 解决get和post请求 全部乱码的过滤器
     */
    public class GenericEncodingFilter implements Filter {
          
          
    
        @Override
        public void destroy() {
          
          
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
          
          
            //处理response的字符编码
            HttpServletResponse myResponse=(HttpServletResponse) response;
            myResponse.setContentType("text/html;charset=UTF-8");
    
            // 转型为与协议相关对象
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            // 对request包装增强
            HttpServletRequest myrequest = new MyRequest(httpServletRequest);
            chain.doFilter(myrequest, response);
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
          
          
        }
    
    }
    
    //自定义request对象,HttpServletRequest的包装类
    class MyRequest extends HttpServletRequestWrapper {
          
          
    
        private HttpServletRequest request;
        //是否编码的标记
        private boolean hasEncode;
        //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
        public MyRequest(HttpServletRequest request) {
          
          
            super(request);// super必须写
            this.request = request;
        }
    
        // 对需要增强方法 进行覆盖
        @Override
        public Map getParameterMap() {
          
          
            // 先获得请求方式
            String method = request.getMethod();
            if (method.equalsIgnoreCase("post")) {
          
          
                // post请求
                try {
          
          
                    // 处理post乱码
                    request.setCharacterEncoding("utf-8");
                    return request.getParameterMap();
                } catch (UnsupportedEncodingException e) {
          
          
                    e.printStackTrace();
                }
            } else if (method.equalsIgnoreCase("get")) {
          
          
                // get请求
                Map<String, String[]> parameterMap = request.getParameterMap();
                if (!hasEncode) {
          
           // 确保get手动编码逻辑只运行一次
                    for (String parameterName : parameterMap.keySet()) {
          
          
                        String[] values = parameterMap.get(parameterName);
                        if (values != null) {
          
          
                            for (int i = 0; i < values.length; i++) {
          
          
                                try {
          
          
                                    // 处理get乱码
                                    values[i] = new String(values[i]
                                            .getBytes("ISO-8859-1"), "utf-8");
                                } catch (UnsupportedEncodingException e) {
          
          
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                    hasEncode = true;
                }
                return parameterMap;
            }
            return super.getParameterMap();
        }
    
        //取一个值
        @Override
        public String getParameter(String name) {
          
          
            Map<String, String[]> parameterMap = getParameterMap();
            String[] values = parameterMap.get(name);
            if (values == null) {
          
          
                return null;
            }
            return values[0]; // 取回参数的第一个值
        }
    
        //取所有值
        @Override
        public String[] getParameterValues(String name) {
          
          
            Map<String, String[]> parameterMap = getParameterMap();
            String[] values = parameterMap.get(name);
            return values;
        }
    }
    

    Register filter

    <filter>
        <filter-name>genericEncodingFilter</filter-name>
        <filter-class>com.sue.filter.GenericEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>genericEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    This is also written by some experts I found online. Under normal circumstances, SpringMVC's default garbled processing can already solve it very well!

    The problem of garbled characters requires more attention. Wherever possible, the encoding should be set to the unified encoding UTF-8!

5. json interactive processing

The era of separation of front-end and back-end

Front-end: independently deployed and responsible for rendering back-end data

Backend: Deploy the backend, submit the interface, and provide data

1. What is JSON

  • JSON (JavaScript Object Notation, JS Object Markup) is a lightweight data exchange format that is currently widely used
  • Store and represent data in a text format that is completely independent of programming languages
  • Simplicity and clear hierarchical structure make JSON an ideal data exchange language
  • It is easy for people to read and write, and it is also easy for machines to parse and generate, and effectively improves network transmission efficiency.

In the JavaScript language, everything is an object. Therefore, any type supported by JavaScript can be represented by JSON, such as strings, numbers, objects, arrays, etc. Take a look at his requirements and syntax format:

  • Objects are represented as key-value pairs, with data separated by commas
  • Curly braces hold objects
  • Square brackets hold arrays

JSON key-value pairs are a way to save JavaScript objects. They are written in much the same way as JavaScript objects. The key names in the key/value pair combination are written in front and wrapped in double quotes "", separated by colon:, and then followed value:

{
    
    "name":"土土","age":12,"sex":"男"}

Many people don't understand the relationship between JSON and JavaScript objects, or even who is who. In fact, it can be understood like this:

JSON is the string representation of JavaScript objects. It uses text to represent the information of a JS object, which is essentially a string.

var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的

var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串

Convert JSON and JavaScript objects to and from each other

To convert a JSON string into a JavaScript object, use the JSON.parse() method

To convert a JavaScript object to a JSON string, use the JSON.stringify() method

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <script type="text/javascript">
    //编写一个JavaScript对象
    var user = {
      
      
      name : "Genius Sue",
      age : 18,
      sex : "男"
    }

    //将JS对象转化为JSON对象
    var json = JSON.stringify(user);
    console.log(json);

    //将JSON对象转化为js对象
    var obj = JSON.parse(json);
    console.log(obj);
  </script>
</head>
<body>

</body>
</html>

2. Controller returns json data

2.1、Jackson

Jackson should be a better json parsing tool at present.

Of course, there are more than just these tools, such as Alibaba's fastjson and so on.

We use Jackson here

  1. Guide package

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
    </dependencies>
    
  2. Configuration required to configure SpringMVC

    web.xml

    <?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">
    
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    
        <filter>
            <filter-name>encoding</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>
        </filter>
        <filter-mapping>
            <filter-name>encoding</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    </web-app>
    
  3. springmvc-servlet.xml

    <?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">
    
        <context:component-scan base-package="com.sue.controller"/>
    
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
    
    </beans>
    
  4. Entity class

    //需要导入lombok包
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
          
          
        private int id;
        private String name;
        private int age;
    }
    
  5. controller

    @Controller
    public class UserController {
          
          
        @RequestMapping(value = "/j1")
        //加了@ResponseBody就不会走视图解析器,直接返回一个字符串
        @ResponseBody
        public String json() throws JsonProcessingException {
          
          
    
            //创建一个jackson的对象映射器,用来解析数据
            ObjectMapper mapper = new ObjectMapper();
    
            //创建一个对象
            User user = new User("Genius Sue",18,"男");
    
            String str = mapper.writeValueAsString(user);
    
            return str;
        }
    
    }
    
  6. Configure tomcat and start testing

If we find that there is a garbled code problem, we can achieve it through the produces attribute of @RequestMaping and modify the code.

@Controller
public class UserController {
    
    
    @RequestMapping(value = "/j1")
    //加了@ResponseBody就不会走视图解析器,直接返回一个字符串
    @ResponseBody
    public String json() throws JsonProcessingException {
    
    

        //创建一个jackson的对象映射器,用来解析数据
        ObjectMapper mapper = new ObjectMapper();

        //创建一个对象
        User user = new User("Genius Sue",18,"男");

        String str = mapper.writeValueAsString(user);

        return str;
    }

}

Start it again and the garbled code is resolved!

Uniform solution to garbled characters

The previous method is more troublesome. If there are many requests in the project, each one must be added. You can specify them uniformly through Spring configuration, so that you don’t have to deal with them every time!

We can add a message StringHttpMessageConverter conversion configuration to the springmvc configuration file!

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <constructor-arg value="UTF-8"/>
        </bean>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="failOnEmptyBeans" value="false"/>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

Return json string for unified solution

Use @RestController directly on the class . In this way, all methods in it will only return json strings. There is no need to add @ResponseBody to each one! In our separate front-end and back-end development, we generally use @RestController, which is very convenient!

@RestController
public class UserController {
    
    
    @RequestMapping(value = "/j1")
    public String json() throws JsonProcessingException {
    
    
        //创建一个jackson的对象映射器,用来解析数据
        ObjectMapper mapper = new ObjectMapper();
        //创建一个对象
        User user = new User("Genius Sue",18,"男");

        String str = mapper.writeValueAsString(user);

        return str;
    }

    //测试集合输出
    @RequestMapping(value = "/j2")
    public String json2() throws JsonProcessingException {
    
    
        ObjectMapper objectMapper = new ObjectMapper();

        List<User> userList = new ArrayList<User>();
        User user = new User("Genius Sue01",18,"男");
        User user2 = new User("Genius Sue02",18,"男");
        User user3 = new User("Genius Sue03",18,"男");
        User user4 = new User("Genius Sue04",18,"男");

        userList.add(user);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        return objectMapper.writeValueAsString(userList);
    }
}

Output time object

@RequestMapping(value = "/j3")
public String json3() throws JsonProcessingException {
    
    
    ObjectMapper objectMapper = new ObjectMapper();

    Date date = new Date();

    return objectMapper.writeValueAsString(date);
}
  • The default date format will become a number, which is the number of milliseconds from January 1, 1970 to the current date!
  • Jackson will convert time into timestamps by default.

Solution 1: Format it first, then convert it to json and return it

@RequestMapping(value = "/j3")
public String json3() throws JsonProcessingException {
    
    
    ObjectMapper objectMapper = new ObjectMapper();

    Date date = new Date();

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    return objectMapper.writeValueAsString(sdf.format(date));
}

Solution 2: Cancel the timestamps format and customize the time format

  @RequestMapping(value = "/j3")
    public String json3() throws JsonProcessingException {
    
    
        ObjectMapper objectMapper = new ObjectMapper();
        //不使用时间戳的方式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        //自定义日期格式对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        objectMapper.setDateFormat(sdf);

        Date date = new Date();

        return objectMapper.writeValueAsString(date);
    }

Formatting method here we extract a tool class

public class JsonUtil {
    
    

    public static String getJson(Object object) {
    
    
        return getJson(object, "yyyy-MM-dd HH:mm:ss");
    }

    public static String getJson(Object object, String dateFormat) {
    
    

        ObjectMapper objectMapper = new ObjectMapper();

        //不使用时间戳的方式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        //自定义日期格式对象
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        objectMapper.setDateFormat(sdf);

        try {
    
    
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
    
    
            e.printStackTrace();
        }

        return null;
    }
}

2.2、FastJson

fastjson.jar is a package developed by Alibaba specifically for Java development. It can easily convert json objects and JavaBean objects, convert JavaBean objects and json strings, and convert json objects and json strings. There are many ways to convert json, and the final result is the same.

Guide package

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
</dependency>

fastjson has three main classes:

  • JSONObject represents json object

    • JSONObject implements the Map interface. It is assumed that the underlying operations of JSONObject are implemented by Map.
    • JSONObject corresponds to the json object. You can obtain the data in the json object through various forms of get() methods. You can also use methods such as size() and isEmpty() to obtain the number of "key: value" pairs and determine whether they are empty. . Its essence is to implement the Map interface and call the methods in the interface.
  • JSONArray represents an array of json objects

    • Internally, there are methods in the List interface to complete the operation.
  • JSON represents the conversion of JSONObject and JSONArray

    • JSON class source code analysis and use
    • Observe these methods carefully, they mainly implement the mutual conversion between json objects, json object arrays, javabean objects, and json strings.

image-20220520152646273

image-20220520152711619

For code testing, we create a new FastJsonDemo class

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zyy.pojo.User;

import java.util.ArrayList;
import java.util.List;

public class FastJsonDemo {
    
    
    public static void main(String[] args) {
    
    
        //创建一个对象
        User user1 = new User(1, "秦疆1号", 18);
        User user2 = new User(2, "秦疆2号", 18);
        User user3 = new User(3, "秦疆3号", 18);
        User user4 = new User(4, "秦疆4号", 18);
        List<User> list = new ArrayList<User>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);

        System.out.println("*******Java对象 转 JSON字符串*******");
        String str1 = JSON.toJSONString(list);
        System.out.println("JSON.toJSONString(list)==>" + str1);
        String str2 = JSON.toJSONString(user1);
        System.out.println("JSON.toJSONString(user1)==>" + str2);

        System.out.println("****** JSON字符串 转 Java对象*******");
        User jp_user1 = JSON.parseObject(str2, User.class);
        System.out.println("JSON.parseObject(str2,User.class)==>" + jp_user1);

        System.out.println("****** Java对象 转 JSON对象 ******");
        JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
        System.out.println("(JSONObject) JSON.toJSON(user2)==>" + jsonObject1.getString("name"));

        System.out.println("****** JSON对象 转 Java对象 ******");
        User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
        System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>" + to_java_user);
    }
}

We only need to master the use of this kind of tool, and when using it, we need to find the corresponding implementation according to the specific business. Just like the previous commons-io toolkit, just use it!

6. Integrate SSM

Environmental requirements

environment:

  • IDEA
  • MySQL 8.0.30
  • Tomcat 9
  • Maven 3.8.6

Require:

  • Need to be proficient in MySQL database, Spring, JavaWeb and MyBatis knowledge, simple front-end knowledge

Database environment

Create a database table to store book data

CREATE DATABASE `ssmbuild`;

USE `ssmbuild`;

DROP TABLE IF EXISTS `books`;

CREATE TABLE `books` (
`bookID` INT(10) NOT NULL AUTO_INCREMENT COMMENT '书id',
`bookName` VARCHAR(100) NOT NULL COMMENT '书名',
`bookCounts` INT(11) NOT NULL COMMENT '数量',
`detail` VARCHAR(200) NOT NULL COMMENT '描述',
KEY `bookID` (`bookID`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT  INTO `books`(`bookID`,`bookName`,`bookCounts`,`detail`)VALUES
(1,'Java',1,'从入门到放弃'),
(2,'MySQL',10,'从删库到跑路'),
(3,'Linux',5,'从进门到进牢');

Basic environment setup

  1. Create a new Maven project! ssmbuild, add web support

  2. Import related pom dependencies

    <!--  依赖 :junit,数据库驱动,连接池,servlet,jsp,mybatis,mybatis-spring,spring -->
        <dependencies>
    <!--    junit    -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
    <!--    数据库驱动    -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.30</version>
            </dependency>
    <!--   连接池    -->
            <dependency>
                <groupId>com.mchange</groupId>
                <artifactId>c3p0</artifactId>
                <version>0.9.5.5</version>
            </dependency>
    <!--   servlet   -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
            </dependency>
    <!--    jsp    -->
            <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>
    <!--    Mybatis    -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.10</version>
            </dependency>
    <!--    Mybatis-spring    -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>2.0.7</version>
            </dependency>
    <!--    Spring    -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.3.22</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>5.3.22</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.24</version>
            </dependency>
        </dependencies>
    
  3. maven resource filtering settings

    <!--    静态资源导出问题-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
    
  4. Establish basic structure and configuration framework

    • com.sue.pojo

    • com.sue.mapper

    • com.sue.service

    • com.sue.controller

    • mybatis-config.xml

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
      
      </configuration>
      
    • applicationContext.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans.xsd">
          
      </beans>
      

Mybatis layer writing

  1. Database configuration file database.properties

    jdbc.driver = com.mysql.cj.jdbc.Driver
    jdbc.url = jdbc:mysql://localhost:3306/ssmbuild?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
    jdbc.username  = root
    jdbc.password =123456
    
  2. idea relational database

Insert image description here

  1. Write the core configuration file mybatis-config.xml of mybatis

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
    
    <!--  配置数据源,交给Spring去做  -->
    
        <typeAliases>
            <typeAlias alias="books" type="com.sue.pojo.Books" />
        </typeAliases>
    
        <mappers>
            <mapper class="com.sue.mapper.BookMapper"/>
        </mappers>
    
    </configuration>
    
  2. Write the entity class Books corresponding to the database table

    The lombok plug-in is used here

    package com.sue.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SSMBuild
     * @Package : com.sue.pojo
     * @ClassName : .java
     * @createTime : 2022/9/16 14:05
     * @Email : [email protected]
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Books {
          
          
        private int bookID;
        private String bookName;
        private int bookCounts;
        private String detail;
    }
    
    
  3. Write the mapper interface of the dao layer

    package com.sue.mapper;
    
    import com.sue.pojo.Books;
    import org.apache.ibatis.annotations.Param;
    
    import java.awt.print.Book;
    import java.util.List;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SSMBuild
     * @Package : com.sue.mapper
     * @ClassName : .java
     * @createTime : 2022/9/16 14:12
     * @Email : [email protected]
     */
    public interface BookMapper {
          
          
        //增加一本书
        int addBook(Books books);
        //删除一本书
        int deleteBookById(@Param("bookID") int id);
        //更新一本书
        int updateBook(Books books);
        //查询一本书
        Books queryBookById(@Param("bookID") int id);
        //查询所有书
        List<Books> queryAllBooks();
        //根据书名查找书籍
        Books queryBookByName(@Param("bookName") String bookName);
    }
    
    
  4. Write the Mapper.xml file (BookMapper.xml) corresponding to the interface. You need to import the mybatis package.

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.sue.mapper.BookMapper">
    
        <!--增加一本书-->
        <insert id="addBook" parameterType="books">
            insert into ssmbuild.books(bookName, bookCounts, detail)
            values (#{bookName}, #{bookCounts},#{detail});
        </insert>
        <!--删除一本书-->
        <delete id="deleteBookById" parameterType="int">
            delete
            from ssmbuild.books
            where bookID = #{bookID};
        </delete>
        <!--更新一本书-->
        <update id="updateBook" parameterType="books">
            update ssmbuild.books
            set bookName = #{bookName} ,bookCounts = #{bookCounts} ,detail = #{detail}
            where bookID = #{bookID};
        </update>
        <!--查询一本书-->
        <select id="queryBookById" resultType="books">
            select *
            from ssmbuild.books
            where bookID = #{bookID};
        </select>
        <!--查询所有书-->
        <select id="queryAllBooks" resultType="books">
            select *
            from ssmbuild.books;
        </select>
        <!--根据书名查找书籍-->
        <select id="queryBookByName" resultType="books">
            select *
            from ssmbuild.books
            where bookName=#{bookName};
        </select>
    </mapper>
    
  5. Write the interface and implementation class of the service layer

    BookService.java

    package com.sue.service;
    
    import com.sue.pojo.Books;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SSMBuild
     * @Package : com.sue.service
     * @ClassName : .java
     * @createTime : 2022/9/16 14:31
     * @Email : [email protected]
     */
    public interface BookService {
          
          
        //增加一本书
        int addBook(Books books);
        //删除一本书
        int deleteBookById(int id);
        //更新一本书
        int updateBook(Books books);
        //查询一本书
        Books queryBookById(int id);
        //查询所有书
        List<Books> queryAllBooks();
        //根据书名查找书籍
        Books queryBookByName(String bookName);
    }
    

    BookServiceImpl.java

    package com.sue.service;
    
    import com.sue.mapper.BookMapper;
    import com.sue.pojo.Books;
    
    import java.util.List;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SSMBuild
     * @Package : com.sue.service
     * @ClassName : .java
     * @createTime : 2022/9/16 14:32
     * @Email : [email protected]
     */
    public class BookServiceImpl implements BookService{
          
          
        //service调dao层(mapper):组合dao->私有,创建对象
        private BookMapper bookMapper;
    
        public void setBookMapper(BookMapper bookMapper) {
          
          
            this.bookMapper = bookMapper;
        }
    
        @Override
        public int addBook(Books books) {
          
          
            return bookMapper.addBook(books);
        }
    
        @Override
        public int deleteBookById(int id) {
          
          
            return bookMapper.deleteBookById(id);
        }
    
        @Override
        public int updateBook(Books books) {
          
          
            return bookMapper.updateBook(books);
        }
    
        @Override
        public Books queryBookById(int id) {
          
          
            return bookMapper.queryBookById(id);
        }
    
        @Override
        public List<Books> queryAllBooks() {
          
          
            return bookMapper.queryAllBooks();
        }
    
        @Override
        public Books queryBookByName(String bookName) {
          
          
            return bookMapper.queryBookByName(bookName);
        }
    }
    

Spring layer

  1. Configure spring to integrate mybatis. Our data source here uses the c3p0 connection pool.

  2. Let's write the configuration file spring-dao.xml that integrates spring with mybatis.

    <?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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--  1.关联数据库配置文件  -->
        <context:property-placeholder location="classpath:database.properties"/>
    
    <!--  2.连接池
            dbcp:半自动化操作,不能自动连接
            c3p0:自动化操作(可以自动加载配置文件,并且可以自动配置到对象中!)
            druid:hikari
    -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="user" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
    
            <!-- c3p0连接池的私有属性 -->
            <property name="maxPoolSize" value="30"/>
            <property name="minPoolSize" value="2"/>
            <!-- 关闭连接后不自动commit -->
            <property name="autoCommitOnClose" value="false"/>
            <!-- 获取连接超时时间 -->
            <property name="checkoutTimeout" value="10000"/>
            <!-- 当获取连接失败重试次数 -->
            <property name="acquireRetryAttempts" value="2"/>
        </bean>
    
    <!--  3.sqlSessionFactory  -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
    <!--    绑定mybatis配置文件    -->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
        </bean>
    
    
    <!--  4.配置dao接口扫描包,动态的实现了dao接口可以注入到Spring容器中  -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!--    注入sqlSessionFactory    -->
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    <!--    扫描要扫描的dao包    -->
            <property name="basePackage" value="com.sue.mapper"/>
        </bean>
    </beans>
    
  3. Spring integrates service layer spring-service.xml

    <?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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
    
        <!--1.扫描service下的包-->
        <context:component-scan base-package="com.sue.service"/>
    
        <!--2.将我们的所有的业务类,注入到spring,可以通过配置或者注解实现-->
        <bean id="bookServiceImpl" class="com.sue.service.BookServiceImpl">
            <property name="bookMapper" ref="bookMapper"/>
        </bean>
    
        <!--3.声明式事务配置-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!-- 注入数据库连接池 -->
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!--4.aop事务支持 这里省略-->
    
    </beans>
    

SpringMVC layer

  1. web.xml

    <?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">
    
        <!--1.配置dispatcherServlet-->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <!--一定要注意:我们这里加载的是总的配置文件,否则可能找不到bean-->
                <param-value>classpath:applicationContext.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
        <!--2.乱码问题-->
        <filter>
            <filter-name>encodingFilter</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>
        </filter>
        <filter-mapping>
            <filter-name>encodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <!--3.session设置-->
        <session-config>
            <session-timeout>15</session-timeout>
        </session-config>
    </web-app>
    
  2. spring-mvc.xml

    <?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">
    
        <!--1..开启SpringMVC注解驱动-->
        <mvc:annotation-driven/>
        <!--2.静态资源过滤
        默认servlet配置 https://blog.csdn.net/codejas/article/details/80055608-->
        <mvc:default-servlet-handler/>
        <!--3.扫描web相关的bean   controller-->
        <context:component-scan base-package="com.sue.controller"/>
        <!--4.视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    
    </beans>
    
  3. spring configuration integration file applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <import resource="classpath:spring-dao.xml"/>
        <import resource="classpath:spring-service.xml"/>
        <import resource="classpath:spring-mvc.xml"/>
    
    </beans>
    

Configuration file, temporarily ended! Controller and view layer writing

  1. BookController writing

    package com.sue.controller;
    
    import com.sue.pojo.Books;
    import com.sue.service.BookService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SSMBuild
     * @Package : com.sue.controller
     * @ClassName : .java
     * @createTime : 2022/9/16 15:48
     * @Email : [email protected]
     */
    @Controller
    @RequestMapping("/book")
    public class BookController {
          
          
        //controller层调service层
        private BookService bookService;
    
        @Autowired
        @Qualifier("bookServiceImpl")
        public void setBookService(BookService bookService) {
          
          
            this.bookService = bookService;
        }
        //查询全部的书籍,并且返回到一个书籍展示页面
        @RequestMapping("/allBook")
        public String list(Model model){
          
          
            List<Books> booksList = bookService.queryAllBooks();
            model.addAttribute("booksList", booksList);
            return "allBook";
        }
        //跳转到增加书籍页面
        @RequestMapping("/toAddBook")
        public String toAddBook(){
          
          
            return "addBook";
        }
        //完成添加书籍的请求
        @RequestMapping("/addBook")
        public String AddBook(Books books){
          
          
            System.out.println(books);
            bookService.addBook(books);
            return "redirect:/book/allBook";//重定向到我们的 @RequestMapping("/allBook")请求,请求复用
        }
        //跳转到更新书籍的页面
        @RequestMapping("/toUpdateBook")
        public String toUpdateBook(int id,Model model){
          
          
            Books books = bookService.queryBookById(id);
            model.addAttribute("Qbooks",books);
            return "updateBook";
        }
        //完成更新书籍的请求
        @RequestMapping("/updateBook")
        public String updateBook(Books books){
          
          
            System.out.println(books);
            bookService.updateBook(books);
            return "redirect:/book/allBook";//重定向到我们的 @RequestMapping("/allBook")请求,请求复用
        }
        //完成删除书籍的请求
        @RequestMapping("/deleteBook/{bookID}")
        public String deleteBook(@PathVariable("bookID") int id){
          
          
            bookService.deleteBookById(id);
            return "redirect:/book/allBook";//重定向到我们的 @RequestMapping("/allBook")请求,请求复用
        }
        //完成删除书籍的请求
        @RequestMapping("/queryBookByName")
        public String queryBookByName(String queryBookName,Model model){
          
          
            Books books = bookService.queryBookByName(queryBookName);
            List<Books> booksList = new ArrayList<Books>();
            booksList.add(books);
    
            if (books==null){
          
          
                booksList = bookService.queryAllBooks();
                model.addAttribute("error","未查到");
            }
    
            model.addAttribute("booksList", booksList);
            return "allBook";
        }
    }
    
  2. Write home page index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>首页</title>
    
        <style>
          a{
            text-decoration: none;
            color: black;
            font-size: 18px;
          }
          h3{
            width: 180px;
            height: 38px;
            margin: 100px auto;
            text-align: center;
            line-height: 38px;
            background: deepskyblue;
            border-radius: 4px;
          }
        </style>
    
      </head>
      <body>
      <h3>
        <a href="${pageContext.request.contextPath}/book/allBook">进入书籍页面</a>
      </h3>
      </body>
    </html>
    
  3. Book list page allBook.jsp

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>书籍展示</title>
        <!-- 引入 Bootstrap -->
        <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
    <div class="container">
        <div class="row clearfix">
            <div class="col-md-12 colum">
                <div class="page-header">
                    <h1>
                        <small>书籍列表-----------------显示所有书籍</small>
                    </h1>
                </div>
            </div>
            <div class="row">
                <div class="col-md-4 colum">
                    <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增书籍</a>
                    <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">显示所有书籍</a>
    
                </div>
                <div class="col-md-8 column">
                    <%--查询书籍--%>
                    <form action="${pageContext.request.contextPath}/book/queryBookByName" method="post" class="form-inline" style="float: right">
                        <span style="color: red;font-weight: bold;">${error}</span>
                        <input type="text" class="form-control" id="bookName" name="queryBookName" placeholder="请输入要查询书籍的名称">
                        <input class="btn btn-primary" type="submit" value="查询">
                    </form>
                </div>
            </div>
        </div>
        <div class="row clearfix">
            <div class="col-md-12 colum">
                <table class="table table-hover table-striped">
                    <thead>
                    <tr>
                        <th>书籍编号</th>
                        <th>书籍名称</th>
                        <th>书籍数量</th>
                        <th>书籍详情</th>
                        <th>操作</th>
                    </tr>
                    </thead>
    <%--        书籍从数据库中查询出来,从这个list中便利出来:foreach        --%>
                    <tbody>
                    <c:forEach var="book" items="${booksList}">
                        <tr>
                            <td>${book.bookID}</td>
                            <td>${book.bookName}</td>
                            <td>${book.bookCounts}</td>
                            <td>${book.detail}</td>
                            <td>
                                <a href="${pageContext.request.contextPath}/book/toUpdateBook?id=${book.bookID}">修改</a>
                                &nbsp; | &nbsp;
                                <a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookID}">删除</a>
                            </td>
                        </tr>
                    </c:forEach>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    
  4. Add book page addBook.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>新增书籍</title>
        <!-- 引入 Bootstrap -->
        <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
    <div class="container">
        <div class="row clearfix">
            <div class="col-md-12 colum">
                <div class="page-header">
                    <h1>
                        <small>新增书籍</small>
                    </h1>
                </div>
            </div>
        </div>
        <form action="${pageContext.request.contextPath}/book/addBook" method="post">
            <div class="form-group">
                <label for="bookName">书籍名称</label>
                <%--required 必须添加值才可以提交表单--%>
                <input type="text" class="form-control" id="bookName" name="bookName" required>
            </div>
            <div class="form-group">
                <label for="bookCounts">书籍数量</label>
                <input type="text" class="form-control" id="bookCounts" name="bookCounts" required>
            </div>
            <div class="form-group">
                <label for="detail">书籍描述</label>
                <input type="text" class="form-control" id="detail" name="detail" required>
            </div>
            <div class="form-group">
                <input type="submit" class="form-control" value="添加"/>
            </div>
        </form>
    </div>
    </body>
    </html>
    
  5. Modify the book page updateBook.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>修改书籍</title>
      <!-- 引入 Bootstrap -->
      <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
    <div class="container">
      <div class="row clearfix">
        <div class="col-md-12 colum">
          <div class="page-header">
            <h1>
              <small>修改书籍</small>
            </h1>
          </div>
        </div>
      </div>
      <form action="${pageContext.request.contextPath}/book/updateBook" method="post">
        <input type="hidden" name="bookID" value="${Qbooks.bookID}" >
        <div class="form-group">
          <label>书籍名称</label>
          <%--required 必须添加值才可以提交表单--%>
          <input type="text" class="form-control" name="bookName" value="${Qbooks.bookName}" required>
        </div>
        <div class="form-group">
          <label>书籍数量</label>
          <input type="text" class="form-control" name="bookCounts" value="${Qbooks.bookCounts}" required>
        </div>
        <div class="form-group">
          <label>书籍描述</label>
          <input type="text" class="form-control" name="detail" value="${Qbooks.detail}" required>
        </div>
        <div class="form-group">
          <input type="submit" class="form-control" value="修改"/>
        </div>
      </form>
    </div>
    </body>
    </html>
    

Overall project structure:

Insert image description here

7、ajax

Introduction

  • AJAX = Asynchronous JavaScript and XML (Asynchronous JavaScript and XML)
  • AJAX is a technology that can update parts of a web page without reloading the entire page
  • AJAX is not a new programming language, but a technology for creating better, faster, and more interactive web applications.
  • In 2005, Google made AJAX popular with its Google Suggest. Google Suggest can automatically help you complete search terms
  • Google Suggest uses AJAX to create a highly dynamic web interface: when you enter keywords in Google's search box, JavaScript will send these characters to the server, and then the server will return a list of search suggestions
  • Just like the domestic Baidu search box
  • For traditional web pages (that is, web pages that do not use Ajax technology), if you want to update or submit a form, you need to reload the entire web page.
  • Web pages using Ajax technology can achieve asynchronous partial updates by exchanging a small amount of data on the background server.
  • Using Ajax, users can create direct, highly available, richer, and more dynamic web user interfaces that are close to native desktop applications.

fake ajax

We can use a tag on the front end to fake an ajax look. iframe tag

  1. Create a new module: springmvc-06-ajax, import web support

  2. Write an iframe .html and use iframe to test and feel the effect

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>iframe测试体验页面无刷新</title>
    
        <script>
            function go(){
            
            
                //所有的值变量,提前获取
                let value = document.getElementById("url").value;
                document.getElementById("iframe01").src=value;
            }
        </script>
    
    </head>
    <body>
    
    <div>
        <p>请输入地址:</p>
        <input type="text" id="url" value="https://blog.csdn.net/Daears/">
        <input type="button" value="提交" onclick="go()"/>
    </div>
    
    <div>
        <iframe id="iframe01" width="100%" height="500px"></iframe>
    </div>
    
    </body>
    </html>
    

Using ajax you can do:

  • When registering, enter the username to automatically detect whether the user already exists.
  • When logging in, it prompts that the username and password are incorrect.
  • When deleting a data row, the row ID is sent to the background, and the background deletes it in the database. After the database is deleted successfully, the data row is also deleted in the page DOM.
  • 。。。

jQuery.ajax

We will not explain the pure JS native implementation of Ajax here. We will directly use the one provided by jquery, which is convenient for learning and use and avoids reinventing the wheel. Interested students can learn about JS native XMLHttpRequest!

The core of ajax is the XMLHttpRequest object (XHR). XHR provides an interface for sending requests to the server and parsing server responses. Ability to get new data from the server asynchronously.

jQuery provides several methods related to AJAX.

With jQuery AJAX methods, you can request text, HTML, XML or JSON from a remote server using HTTP Get and HTTP Post - and you can load this external data directly into selected elements of the web page.

jQuery is not a producer, it is nature's porter.

The essence of jQuery Ajax is XMLHttpRequest, which is encapsulated for easy calling!

jQuery.ajax(...)
      部分参数:
            url:请求地址
           type:请求方式,GET、POST(1.9.0之后用method)
        headers:请求头
           data:要发送的数据
    contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
          async:是否异步
        timeout:设置请求超时时间(毫秒)
     beforeSend:发送请求前执行的函数(全局)
       complete:完成之后执行的回调函数(全局)
        success:成功之后执行的回调函数(全局)
          error:失败之后执行的回调函数(全局)
        accepts:通过请求头发送给服务器,告诉服务器当前客户端可接受的数据类型
       dataType:将服务器端返回的数据转换成指定类型
          "xml": 将服务器端返回的内容转换成xml格式
         "text": 将服务器端返回的内容转换成普通文本格式
         "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
       "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
         "json": 将服务器端返回的内容转换成相应的JavaScript对象
        "jsonp": JSONP 格式使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

Let's do a simple test, using the most original HttpServletResponse processing, the simplest and most versatile

  1. Configure web.xml and springmvc configuration files

    <?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">
    
        <!--自动扫描指定的包,将下面所有的注解类交给IOC容器-->
        <context:component-scan base-package="com.sue.controller"/>
    
        <!--静态资源过滤-->
        <mvc:default-servlet-handler/>
    
        <!--注解驱动-->
        <mvc:annotation-driven/>
    
        <!--视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <!--前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
    </beans>
    
  2. Write an AjaxController

    @RestController
    public class AjaxController {
          
          
        @RequestMapping("/a1")
        public void a1(String name, HttpServletResponse response) throws IOException {
          
          
            System.out.println("a1:param=>"+name);
            if (name.equals("sue")){
          
          
                response.getWriter().print("true");
            }else {
          
          
                response.getWriter().print("false");
            }
        }
    }
    
  3. To import jquery, you can use an online CDN or download and import it.

    <script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.1.js"></script>
    
  4. Write index.jsp test

    <%@ page contentType="text/html;charset=UTF-8"%>
    <html>
      <head>
        <title>$Title$</title>
        <script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.1.js"></script>
    
        <script>
    
          function a(){
            $.post({
              url:"${pageContext.request.contextPath}/a1",
              data:{"name":$("#username").val()},
              success:function (data,status){
                console.log("data=>"+data);
                console.log("status=>"+status);
              }
            })
          }
    
        </script>
      </head>
      <body>
      <%-- 失去焦点的时候发起一个请求(携带信息)到后台 --%>
      用户名:<input type="text" id="username" οnblur="a()"/>
      </body>
    </html>
    

Springmvc implementation

  1. Entity class User

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
          
          
        private int id;
        private String name;
        private int age;
    }
    
  2. Let's get a collection object and display it to the front-end page controller adding method

    @RequestMapping("/a2")
    public List<User> a2(){
          
          
        ArrayList<User> userArrayList = new ArrayList<>();
        //添加数据
        userArrayList.add(new User("Genius Sue",18,"男"));
        userArrayList.add(new User("GCD",18,"女"));
    
        return userArrayList;
    }
    
  3. Front-end page

    <%@ page contentType="text/html;charset=UTF-8" %>
    <html>
    <head>
        <title>Title</title>
        <script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.1.js"></script>
        <script>
            $(function (){
                $("#btn").click(function (){
                    /*
                    * $ post(url,param[可以省略],success)
                    * */
                    $.post("${pageContext.request.contextPath}/a2",function (data){
                        console.log(data);
                        var html = "";
                        for (let i = 0; i < data.length; i++) {
                            html += "<tr>" +
                                "<td>"+data[i].name+ "</td>"+
                                "<td>"+data[i].age+ "</td>"+
                                "<td>"+data[i].sex+ "</td>"+
                                "</tr>"
                        }
                        $("#content").html(html)
                    })
                })
            })
        </script>
    </head>
    <body>
    
    <input type="button" value="加载数据" id="btn">
    <div>
        <table>
            <tr>
                <td>姓名</td>
                <td>年龄</td>
                <td>性别</td>
            </tr>
            <tbody id="content">
            <%--数据:后台--%>
            </tbody>
        </table>
    </div>
    
    </body>
    </html>
    
  4. test

Insert image description here

Registration prompt effect

Let’s test a small Demo again and think about how to achieve the real-time prompt behind the input box when we usually register; how to optimize it

Let's write a Controller

@RequestMapping("/a3")
    public String a3(String name,String pwd){
    
    
        String msg="";
        if (name != null && name != "")
        {
    
    
            if("admin".equals(name)){
    
    
                msg = "ok";
            }else{
    
    
                msg = "用户名有误";
            }
        }
        if (pwd != null && pwd != ""){
    
    
            if("123456".equals(pwd)){
    
    
                msg = "ok";
            }else{
    
    
                msg = "密码有误";
            }
        }
        return msg;
    }

Front-end page login.jsp

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

    <script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.1.js"></script>


    <script>
        function a1(){
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{"name":$("#username").val()},
                success:function (data){
                    if(data.toString()==='ok'){
                        $("#userInfo").css("color","green");
                    }
                    else{
                        $("#userInfo").css("color","red");
                    }
                    $("#userInfo").html(data);
                }
            })
        }

        function a2(){
            $.post({
                url:"${pageContext.request.contextPath}/a3",
                data:{"pwd":$("#pwd").val()},
                success:function (data){
                    if(data.toString()==='ok'){
                        $("#pwdInfo").css("color","green");
                    }
                    else{
                        $("#pwdInfo").css("color","red");
                    }
                    $("#pwdInfo").html(data);
                }
            })
        }
    </script>
</head>
<body>

<p>
    用户名:<input type="text" id="username" οnblur="a1()">
    <span id="userInfo"></span>
</p>

<p>
    密码:<input type="text" id="pwd" οnblur="a2()">
    <span id="pwdInfo"></span>
</p>

</body>
</html>

[Remember to deal with the json garbled problem]

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
            <constructor-arg value="UTF-8"/>
        </bean>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="failOnEmptyBeans" value="false"/>
                </bean>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

Test the effect, dynamic request response, partial refresh, that's it!

Insert image description here

8. Interceptor

Overview

SpringMVC's processor interceptor is similar to the filter in servlet development, which is used to pre-process and post-process the processor. Developers can define some interceptors to implement specific functions.

The difference between filters and interceptors:

  • filter

    • Part of the servlet specification, task javaweb functions can be used
    • After configuring /* in the url-pattern, all resources to be accessed can be intercepted.
  • Interceptor

    • The interceptor is the SpringMVC framework's own and can only be used by projects that use the springmv framework.
    • The interceptor will only intercept the accessed controller method. If the access is jsp html css image js, it will not be intercepted.

Custom interceptor

If you want to customize the interceptor, you must implement the HandlerInterceptor interface

  1. Create a new Module, springmvc-07-Interceptor, and add web support

  2. Configure web.xml and springmvc-servlet.xml files

  3. Write an interceptor

    public class MyInterceptor implements HandlerInterceptor {
          
          
    
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          
          
            //返回 true :放行,可以处理下一个拦截器
            //返回 false :不放行,不可以处理下一个拦截器
            System.out.println("=========处理前=========");
            return true;
        }
    
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
          
          
            System.out.println("=========处理后=========");
        }
    
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
          
          
            System.out.println("=========清理=========");
        }
    }
    
  4. Configure the interceptor in the springmvc configuration file

    <!--关于拦截器的配置-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--/** 包括路径及其子路径-->
            <!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
            <!--/admin/** 拦截的是/admin/下的所有-->
            <mvc:mapping path="/**"/>
            <!--bean配置的就是拦截器-->
            <bean class="com.sue.config.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    
  5. Write a Controller to receive requests

    @RestController
    public class TestInterceptor {
          
          
        @RequestMapping("/t1")
        public String test(){
          
          
            System.out.println("MyInterceptor执行了");
            return "OK";
        }
    }
    

Verify whether the user is logged in (authenticated user)

Implementation ideas

  1. There is a login page and you need to write a controller to access the page.
  2. The login page has an action to submit the form. Need to be handled in controller. Determine whether the username and password are correct. If correct, write user information to the session. Return to login successfully
  3. Intercept user requests and determine whether the user is logged in. If the user is already logged in. Release, if the user is not logged in, jump to the login page

accomplish

  1. Write a login page login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登录</title>
    </head>
    <body>
    <%--在web-inf在的所有页面或者资源,只能通过controller或者servlet进行访问--%>
    <h1>登录页面</h1>
    <form action="${pageContext.request.contextPath}/user/login" method="post">
        用户名:<input type="text" name="username"/>
        密码:<input type="text" name="password"/>
        <input type="submit" value="提交">
    </form>
    </body>
    </html>
    
  2. Write a Controller to handle requests

    package com.sue.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpSession;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SpringMVC
     * @Package : com.sue.controller
     * @ClassName : .java
     * @createTime : 2022/9/19 15:29
     * @Email : [email protected]
     */
    @Controller
    @RequestMapping("/user")
    public class LoginController {
          
          
    
        @RequestMapping("/main")
        public String main(){
          
          
            return "main";
        }
    
        @RequestMapping("/toLogin")
        public String toLogin(){
          
          
            return "login";
        }
    
        @RequestMapping("/login")
        public String login(HttpSession session, String username, String password, Model model){
          
          
            //把用户信息存在session中
            session.setAttribute("userLoginInfo", username);
    
            model.addAttribute("username", username);
    
            return "main";
        }
    
        @RequestMapping("/goOut")
        public String goOut(HttpSession session){
          
          
            //移除session
            session.removeAttribute("userLoginInfo");
    
            return "main";
        }
    }
    
    
  3. Write a homepage main.jsp after successful login

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>首页</title>
    </head>
    <body>
    
    <h1>首页</h1>
    
    <span>${username}</span>
    
    <p>
        <a href="${pageContext.request.contextPath}/user/goOut">注销</a>
    </p>
    </body>
    </html>
    
    
  4. Test the jump on the index page! Start the Tomcat test and you can enter the homepage without logging in

  5. Writing a user login interceptor

    package com.sue.config;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SpringMVC
     * @Package : com.sue.config
     * @ClassName : .java
     * @createTime : 2022/9/19 15:40
     * @Email : [email protected]
     */
    public class LoginInterceptor implements HandlerInterceptor {
          
          
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          
          
    
            //哪些可以放行
            //第一次登录,也是没有session的
            if(request.getRequestURI().contains("toLogin")){
          
          
                return true;
            }
            if(request.getRequestURI().contains("login")){
          
          
                return true;
            }
    
            //已经登录成功的
            HttpSession session = request.getSession();
            if(session.getAttribute("userLoginInfo")!=null){
          
          
                return true;
            }
    
            //判断什么情况下没有登录
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
            return false;
        }
    }
    
    
  6. Register the interceptor in the Springmvc configuration file

    <mvc:interceptor>
        <mvc:mapping path="/user/**"/>
        <bean class="com.sue.config.LoginInterceptor"/>
    </mvc:interceptor>
    
  7. Restart tocat and test

9. File upload and download

Preparation

File upload is one of the most common functions in project development. SpringMVC can support file upload very well, but the MultipartResolver is not installed by default in the SpringMVC context, so it cannot handle file upload by default. If you want to use Spring's file upload feature, you need to configure the MultipartResolver in the context.

Front-end form requirements: In order to upload files, the form method must be set to POST and the enctype must be set to multipart/form-data. Only in this case will the browser send the file selected by the user to the server as binary data;

Give a detailed explanation of the enctype attribute in the form:

  • application/x-www=form-urlencoded: The default method only processes the value attribute value in the form field. A form using this encoding method will process the value in the form field into URL encoding.
  • multipart/form-data: This encoding method will process form data in a binary stream. This encoding method will also encapsulate the content of the file specified in the file field into the request parameters, and will not encode the characters.
  • Except for converting spaces into "+" signs, other characters are not encoded. This method is suitable for sending emails directly through the form.
<form action="" enctype="multipart/form-data" method="post">
   <input type="file" name="file"/>
   <input type="submit">
</form>

Once the enctype is set to multipart/form-data, the browser will use a binary stream to process form data, while processing file uploads involves parsing the original HTTP response on the server side. In 2003, the Apache Software Foundation released the open source Commons FileUpload component, which quickly became the best choice for Servlet/JSP programmers to upload files.

  • The Servlet3.0 specification already provides methods to handle file uploads, but this upload needs to be completed in the Servlet
  • Spring MVC provides simpler encapsulation
  • Spring MVC provides direct support for file uploads, which is implemented using the plug-and-play MultipartResolver
  • Spring MVC uses Apache Commons FileUpload technology to implement a MultipartResolver implementation class
  • CommonsMultipartResolver. Therefore, SpringMVC's file upload also needs to rely on the component of Apache Commons FileUpload.

File Upload

  1. Import the jar package for file upload, commons-fileupload. Maven will automatically help us import its dependency package commons-io package.

    <dependencies>
        <!--文件上传-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <!--servlet-api导入高版本的-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>
    
  2. Placement bean: multipartResolver

    [ Note ] The configurations written here are all fixed, do not change them at will.

    <!--文件上传配置-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
        <property name="defaultEncoding" value="utf-8"/>
        <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>
    

    Common methods of CommonsMultipartFile:

    • String getOriginalFilename(): Get the original name of the uploaded file
    • InputStream getInputStream(): Get the file stream
    • void transferTo(File dest): Save the uploaded file to a directory file

    Let's go and actually test it

  3. Write front-end pages

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
      <title>$Title$</title>
    </head>
    <body>
    <form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
      <input type="file" name="file"/>
      <input type="submit" value="上传">
    </form>
    </body>
    </html>
    
  4. Controller

    package com.sue.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.commons.CommonsMultipartFile;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.*;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @author : Genius Sue
     * @version : 1.0
     * @Project : SpringMVC
     * @Package : com.sue.controller
     * @ClassName : .java
     * @createTime : 2022/9/19 16:22
     * @Email : [email protected]
     */
    @RestController
    public class FileController {
          
          
        //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
        //批量上传CommonsMultipartFile则为数组即可
        @RequestMapping("/upload")
        public String fileUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
          
          
            System.out.println("=upload====");
    
            //获取文件名 : file.getOriginalFilename();
            String uploadFileName = file.getOriginalFilename();
    
            //如果文件名为空,直接回到首页!
            if ("".equals(uploadFileName)) {
          
          
                return "redirect:/index.jsp";
            }
            System.out.println("上传文件名 : " + uploadFileName);
    
            //上传路径保存设置
            String path = request.getServletContext().getRealPath("/upload");
            //如果路径不存在,创建一个
            File realPath = new File(path);
            if (!realPath.exists()) {
          
          
                realPath.mkdir();
            }
            System.out.println("上传文件保存地址:" + realPath);
    
            //文件输入流
            InputStream is = file.getInputStream();
            //文件输出流
            OutputStream os = new FileOutputStream(new File(realPath, uploadFileName));
    
            //读取写出
            int len = 0;
            byte[] buffer = new byte[1024];
            while ((len = is.read(buffer)) != -1) {
          
          
                os.write(buffer, 0, len);
            }
            os.flush();
            os.close();
            is.close();
            return "redirect:/index.jsp";
        }
    }
    
    

Use file.Transto to save uploaded files

  1. Write Controller

        /*
         * 采用file.Transto 来保存上传的文件
         */
        @RequestMapping("/upload2")
        public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
          
          
    
            //上传路径保存设置
            String path = request.getServletContext().getRealPath("/upload");
            File realPath = new File(path);
            if (!realPath.exists()){
          
          
                realPath.mkdir();
            }
            //上传文件地址
            System.out.println("上传文件保存地址:"+realPath);
    
            //通过CommonsMultipartFile的方法直接写文件(注意这个时候)
            file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
    
            return "redirect:/index.jsp";
        }
    

Download Document

File download steps:

  1. Set response response header
  2. Reading files – InputStream
  3. Write out file – OutputStream
  4. perform operations
  5. Close the stream (first open and then close)

Code:

@RequestMapping(value = "/download")
public String downloads(HttpServletResponse response, HttpServletRequest request) throws Exception {
    
    
    //要下载的图片地址
    String path = request.getServletContext().getRealPath("/upload");
    String fileName = "个人小汽车增量指标申请表.pdf";

    //1、设置response 响应头
    response.reset(); //设置页面不缓存,清空buffer
    response.setCharacterEncoding("UTF-8"); //字符编码
    response.setContentType("multipart/form-data"); //二进制传输数据
    //设置响应头
    response.setHeader("Content-Disposition",
                       "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));

    File file = new File(path, fileName);
    //2、 读取文件--输入流
    InputStream input = new FileInputStream(file);
    //3、 写出文件--输出流
    OutputStream out = response.getOutputStream();

    byte[] buff = new byte[1024];
    int index = 0;
    //4、执行 写出操作
    while ((index = input.read(buff)) != -1) {
    
    
        out.write(buff, 0, index);
        out.flush();
    }
    out.close();
    input.close();
    return null;
}

Guess you like

Origin blog.csdn.net/Daears/article/details/126937089