[Marco SSM] Introducción a SpringMVC

1. ¿Qué es SpringMVC?

1. Información general

Spring MVC es parte de Spring Framework y es un marco web liviano basado en Java que implementa MVC.

Consulte la documentación oficial: Spring MVC

Ventajas de Spring MVC:

  1. Ligero y fácil de aprender.
  2. Marco MVC eficiente, basado en solicitud-respuesta
  3. Buena compatibilidad con Spring e integración perfecta.
  4. Convención sobre configuración
  5. Potentes funciones: RESTful, validación de datos, formateo, localización, temas, etc.
  6. Sencillo y flexible

El marco web de Spring está diseñado en torno a DispatcherServlet [servlet de programación]

La función de DispatcherServlet es distribuir solicitudes a diferentes procesadores. A partir de Spring 2.5, los usuarios que usan Java 5 o superior pueden desarrollar en base a anotaciones, lo cual es muy simple;

2. Controlador central

El marco web de Spring está diseñado en torno a DispatcherServlet. La función de DispatcherServlet es distribuir solicitudes a diferentes procesadores. A partir de Spring 2.5, los usuarios de Java 5 o superior pueden utilizar una declaración de controlador basada en anotaciones.

El marco Spring MVC, como muchos otros marcos MVC, está controlado por solicitudes , envía solicitudes y proporciona otras funciones alrededor de un servlet central . DispatcherServlet es un servlet real (hereda de la clase base HttpServlet) .

El diagrama de clases de DispatcherServlet es el siguiente:

imagen-20220516163849517

El principio de SpringMVC se muestra en la siguiente figura:

Cuando se inicia una solicitud, la solicitud es interceptada por el controlador anterior, se genera una solicitud de proxy basada en los parámetros de la solicitud, se encuentra el controlador real correspondiente a la solicitud, el controlador procesa la solicitud, crea un modelo de datos y accede a la base de datos. , responde al modelo al controlador central y controla El procesador usa el modelo y la vista para representar los resultados de la vista, devuelve los resultados al controlador central y luego devuelve los resultados al solicitante.

imagen-20220516164434657

3. Principio de ejecución de SpringMVC

imagen-20220516170509457

La imagen muestra un diagrama de flujo más completo de SpringMVC: la línea continua indica la tecnología proporcionada por el marco SpringMVC, que no requiere que los desarrolladores la implementen, y la línea de puntos indica que requiere que los desarrolladores la implementen.

Analice brevemente el proceso de ejecución.

  1. DispatcherServlet representa el controlador frontal y es el centro de control de todo SpringMVC. Cuando el usuario realiza una solicitud, DispatcherServlet recibe la solicitud e intercepta la solicitud.

    • Suponemos que la URL solicitada es: http://localhost:8080/SpringMVC/hello

    • La URL anterior se divide en tres partes:

    • http://localhost: nombre de dominio del servidor 8080

    • Sitio web SpringMVC implementado en el servidor

    • hola significa controlador

    • A través del análisis, la URL anterior se expresa como: solicitando el controlador de saludo del sitio SpringMVC ubicado en el servidor localhost:8080

  2. HandlerMapping es el asignador del procesador . DispatcherServlet llama a HandlerMapping y HandlerMapping encuentra a Handler de acuerdo con la URL de solicitud.

  3. HandlerExecution representa un controlador específico. Su función principal es encontrar el controlador en función de la URL. Como se muestra arriba, la URL a buscar para el controlador es: hola

  4. HandlerExecution pasa la información analizada a DispatcherServlet, como el análisis de la asignación del controlador, etc.

  5. HandlerAdapter representa el adaptador de procesador , que ejecuta Handler de acuerdo con reglas específicas.

  6. El controlador permite ejecutar un controlador específico

  7. El controlador devuelve información de ejecución específica a HandlerAdapter, como ModelAndView

  8. HandlerAdapter pasa el nombre lógico o modelo de la vista a DispatcherServlet

  9. DispatcherServlet llama al solucionador de vistas (ViewResolver) para resolver el nombre de la vista lógica pasado por HandlerAdapter

  10. El solucionador de vistas pasa el nombre de la vista lógica resuelta a DispatcherServlet

  11. DispatcherServlet llama a vistas específicas en función de los resultados de la vista analizados por el analizador de vistas.

  12. La vista final se presenta al usuario.

2. El primer programa mvc

1. Versión de configuración

  1. ¡Cree un nuevo Moudle, springmvc-02-hello y agregue soporte web!

  2. ¡Asegúrese de haber importado las dependencias de SpringMVC!

  3. Configure web.xml y registre 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. ¡Escriba el archivo de configuración SpringMVC! Nombre: springmvc-servlet.xml: [nombre de servlet]-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. Para escribir el controlador empresarial que queremos operar, debemos implementar la interfaz del controlador o agregar anotaciones; necesitamos devolver un ModelAndView, cargar los datos y sellar la vista;

    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. Asigne su propia clase al contenedor SpringIOC y registre el bean

    <!--  Handler  -->
        <bean id="/test" class="com.sue.controller.HelloController"/>
    
  7. Escriba la página jsp a saltar para mostrar los datos almacenados en ModellandView y nuestra página normal;

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    	${msg}
    </body>
    </html>
    
  8. Configura tocmat y comienza a probar

    imagen-20220515224820194

2. Versión comentada

  1. Crea un nuevo Moudle, springmvc-03-annotation. ¡Agregue soporte web!

    [Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo anti-leeching. Se recomienda guardar la imagen y cargarla directamente (img-gp3nLofr-1663577047298) (C:\Users\Genius Sue\AppData\Roaming\Typora \typora-user-images \image-20220915105218597.png)]

  2. Dado que Maven puede tener problemas de filtrado de recursos, completaremos la configuración.

    <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. Introduzca dependencias relevantes en el archivo pom.xml: principalmente biblioteca central de Spring framework, Spring MVC, servlet, JSTL, etc. ¡Ya lo hemos introducido en la dependencia principal!

  4. Configurar 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>
    

    La diferencia entre / y /*:

    • < url-pattern > / </ url-pattern > no coincidirá con .jsp, solo para la solicitud que escribimos, es decir: .jsp no ingresará a la clase DispatcherServlet de Spring
    • <url-pattern> /*</url-pattern> coincidirá con *.jsp. Al regresar a la vista jsp, ingresará nuevamente a la clase DispatcherServlet de Spring, lo que provocará que no se encuentre el controlador correspondiente y se informe un error 404.
  5. Agregar el archivo de configuración SpringMVC

    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>
    

    En el analizador de vistas, almacenamos todas las vistas en el directorio /WEB-INF/, lo que garantiza la seguridad de las vistas, porque el cliente no puede acceder directamente a los archivos de este directorio.

  6. Crear controlador

    @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 escanea automáticamente el contenedor Spring IOC cuando se inicializa.
    • @RequestMapping es mapear la ruta de la solicitud. Dado que aquí solo se mapea el método, debe ser /hello cuando se accede.
    • El parámetro de tipo de modelo se declara en el método para llevar los datos de la Acción a la vista.
    • El resultado devuelto por el método es el nombre hola de la vista, más el sufijo y el sufijo en el archivo de configuración para convertirse en WEB-INF/jsp/hello.jsp
  7. Crea la capa de vista hello.jsp

    Cree hello.jsp en el directorio WEB-INF/jsp. La vista puede extraer y mostrar directamente la información recuperada del Controlador.

    El valor u objeto almacenado en el Modelo se puede recuperar mediante expresiones EL;

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

Tres piezas principales que deben configurarse para usar springMVC:

Mapeador de procesador, adaptador de procesador, resolución de vista

Por lo general, solo necesitamos configurar manualmente el solucionador de vistas , y el asignador del procesador y el adaptador del procesador solo necesitan habilitar el controlador de anotaciones .

3. Tranquilo y controlador

1 、 Controlador

  • El controlador es responsable de proporcionar acceso al comportamiento de la aplicación, generalmente a través de dos métodos: definición de interfaz o definición de anotaciones.
  • El controlador es responsable de analizar la solicitud del usuario y convertirla en un modelo.
  • Una clase de controlador en SpringMVC puede contener múltiples métodos
  • Hay muchas formas de configurar controladores en SpringMVC

1.1 Implementar la interfaz del Controlador

  1. Crea un nuevo Moudle, springmvc-04-controller

  2. Configurar 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. Agregar el archivo de configuración de Spring 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. Escriba el front-end test.jsp, preste atención para escribirlo en el directorio WEB-INF/jsp, correspondiente a nuestro analizador de vistas.

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

    //只要实现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. Registre el bean solicitado en el archivo de configuración de Spring

    <bean id="/test1" class="com.sue.controller.ControllerTest1"/>
    
  7. Configurar Tomcat y probar

ilustrar:

  • Implementar la interfaz Controlador para definir un controlador es un enfoque más antiguo
  • La desventaja es: solo hay un método en un controlador. Si desea varios métodos, debe definir varios controladores, y el método de definición es más problemático;

1.2 Utilice la anotación @Controller

El tipo de anotación @Controller se utiliza para declarar que una instancia de una clase Spring es un controlador.

  1. Según lo anterior, anote los beans en el archivo de configuración de Spring, agregue el escaneo y haga que las anotaciones surtan efecto.

    (Spring puede usar el mecanismo de escaneo para encontrar todas las clases de controlador basadas en anotaciones en la aplicación. Para garantizar que Spring pueda encontrar su controlador, el escaneo de componentes debe declararse en el archivo de configuración).

    <!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
     <context:component-scan base-package="com.sue.controller"/>
    
  2. Se agregó 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";
        }
    }
    

Se puede encontrar que nuestras dos solicitudes pueden apuntar a una vista, pero los resultados de la página son diferentes, de esto se puede ver que la vista se reutiliza y existe una relación de acoplamiento débil entre el controlador y la vista.

¡El método de anotación es el método más utilizado!

2 、 Solicitud de mapeo

  • La anotación @RequestMapping se utiliza para asignar URL a controladores o a un método de procesamiento específico. Se puede utilizar en clases o métodos. Se utiliza para clases, lo que indica que todos los métodos de la clase que responden a solicitudes utilizan esta dirección como ruta principal.

  • Se agregó ControllerTest3.java

    Solo anótelo en el método.

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

    Ruta de acceso: http://localhost:8080/test2

  • Anotar clases y métodos simultáneamente.

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

Ruta de acceso: http://localhost:8080/c3/test3

3. Estilo descansado

concepto

Restful es un estilo de posicionamiento y operación de recursos. No es una norma ni un protocolo, sólo un estilo. El software diseñado en base a este estilo puede ser más simple, más jerárquico y más fácil de implementar mecanismos como el almacenamiento en caché.

Función

Recursos: todo lo que hay en Internet se puede resumir en recursos.

Operaciones de recursos: use POST, DELETE, PUT, GET y use diferentes métodos para operar recursos

Decibel corresponde a agregar, eliminar, modificar y consultar

Manipular recursos de manera tradicional : lograr diferentes efectos a través de diferentes parámetros, método único, publicar y obtener

  • http://127.0.0.1/item/queryItem.action?id=1 Consulta, OBTENER
  • http://127.0.0.1/item/saveItem.action Nuevo, POST
  • http://127.0.0.1/item/updateItem.action actualización, POST
  • http://127.0.0.1/item/deleteItem.action?id=1 Eliminar, OBTENER o PUBLICAR

Utilice RestFul para operar recursos: se pueden lograr diferentes efectos a través de diferentes métodos de solicitud, de la siguiente manera: la dirección de solicitud es la misma, pero las funciones pueden ser diferentes

  • http://127.0.0.1/item/1 Consulta, OBTENER
  • http://127.0.0.1/item Nuevo, PUBLICAR
  • http://127.0.0.1/actualización del artículo, PUT
  • http://127.0.0.1/item/1 eliminar,ELIMINAR

prueba de estudio

  1. Crea una nueva clase 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. Inicie Tomcat y acceda a la prueba.

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

    imagen-20220518220855977

  3. Agregar un nuevo método de solicitud restFul

    //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. Inicie Tomcat y acceda a la prueba.

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

    imagen-20220518221050967

  5. Utilice el método de publicación para solicitar y agregar un.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. Agregar un método de publicación

    @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. También se puede abreviar como anotación @PostMapping. Si el método y la ruta son los mismos, PostMapping y RequestMapping no pueden existir al mismo tiempo, lo que provocará ambigüedad.

    @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. Inicie Tomcat y verifique

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

    imagen-20220518222134372

resumen

La anotación @RequestMapping de SpringMVC puede manejar métodos de solicitud HTTP, como GET, PUT, POST, DELETE y PATCH.

Todas las solicitudes de la barra de direcciones serán del tipo HTTP GET de forma predeterminada.

Las variantes de anotaciones a nivel de método son las siguientes: Anotaciones combinadas

@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping

@GetMapping es una anotación combinada que se usa comúnmente.

Actúa como un atajo para @RequestMapping(método =RequestMethod.GET).

pensar

¿Cuáles son los beneficios de utilizar variables de ruta?

  • Haz que los caminos sean más concisos
  • Es más conveniente obtener parámetros y el marco realizará automáticamente la conversión de tipos.
  • Los parámetros de acceso pueden restringirse por el tipo de variable de ruta. Si los tipos son diferentes, no se puede acceder al método de solicitud correspondiente. Por ejemplo, la ruta a la que se accede aquí es /commit/1/a, entonces la ruta no coincide con el método y no será un parámetro. La conversión falló

4. Procesamiento de datos y salto.

1 、 Modelo y vista

Configure el objeto ModelAndView, salte a la página especificada según el nombre de la vista y el analizador de vistas.

Página: {ver prefijo de resolución} + verNombre + {ver sufijo de resolución}

Configurar la resolución de vistas

<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 Implementar el reenvío y la redirección a través de SpringMVC: no se requiere resolución de vista

Antes de realizar la prueba, debe comentar el solucionador de vistas.

@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 Implementar reenvío y redirección a través de SpringMVC - con resolución de vista

La redirección no requiere resolución de vistas, la esencia es volver a solicitar un nuevo lugar, así que preste atención al problema de la ruta.

    @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. Procesamiento de datos

2.1 Procesamiento de los datos enviados

  1. El nombre de dominio enviado es coherente con el nombre del parámetro del método de procesamiento.

    @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. El nombre de dominio enviado no coincide con el nombre del parámetro del método de procesamiento.

    // 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. La sumisión es un objeto.

    Usuario.java

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

    Agregar método

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

2.2 Los datos se muestran en la interfaz

  1. víaModelAndView

    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. Por ModelMap

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

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

Comparado

En términos simples para principiantes, la diferencia es:

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

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

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

Utilice el 80% de su tiempo para sentar una base sólida, el 18% restante de su tiempo para estudiar el marco y el 2% de su tiempo para aprender algo de inglés. La documentación oficial del marco es siempre el mejor tutorial.

3. Problema de código confuso

  1. Crear un nuevo formulario.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. Cree una nueva clase de procesamiento correspondiente en el backend

    @Controller
    public class EncodingController {
          
          
        @PostMapping("/e/t")
        public String test(String name, Model model){
          
          
    
            model.addAttribute("msg", name);
    
            return "test";
        }
    }
    
  3. Inicie Tomcat, ingrese chino y busque caracteres confusos

Insertar descripción de la imagen aquí

3.1. Filtros personalizados

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() {
    
    

    }
}

Registrar filtros en 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 Filtros propios de SpringMVC

SpringMVC nos proporciona un filtro que se puede configurar en web.xml. ¡Modificó el archivo xml y necesita reiniciar el servidor!

<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 Otros métodos

  1. Modifique el archivo de configuración de Tomcat: ¡establezca la codificación!

    <Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
              connectionTimeout="20000"
              redirectPort="8443" />
    
  2. Filtros personalizados más potentes

    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;
        }
    }
    

    Filtro de registro

    <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>
    

    Esto también está escrito por algunos expertos que encontré en línea. En circunstancias normales, el procesamiento confuso predeterminado de SpringMVC ya puede resolverlo muy bien.

    El problema de los caracteres confusos requiere más atención: siempre que sea posible, la codificación debe establecerse en la codificación unificada UTF-8.

Cinco, procesamiento interactivo json

La era de la separación de front-end y back-end

Front-end: implementado de forma independiente y responsable de representar datos de back-end

Backend: implemente el backend, envíe la interfaz y proporcione datos

1. ¿Qué es JSON?

  • JSON (JavaScript Object Notation, JS Object Markup) es un formato de intercambio de datos liviano que se usa ampliamente en la actualidad.
  • Almacene y represente datos en un formato de texto completamente independiente de los lenguajes de programación.
  • La simplicidad y la estructura jerárquica clara hacen de JSON un lenguaje de intercambio de datos ideal
  • Es fácil de leer y escribir para las personas, y también es fácil de analizar y generar para las máquinas, y mejora efectivamente la eficiencia de transmisión de la red.

En el lenguaje JavaScript, todo es un objeto. Por tanto, cualquier tipo soportado por JavaScript puede representarse mediante JSON, como cadenas, números, objetos, matrices, etc. Eche un vistazo a sus requisitos y formato de sintaxis:

  • Los objetos se representan como pares clave-valor, con datos separados por comas.
  • Las llaves sostienen objetos
  • Los corchetes contienen matrices

Los pares clave-valor JSON son una forma de guardar objetos JavaScript. Están escritos de forma muy similar a los objetos JavaScript. Los nombres de las claves en la combinación de pares clave/valor se escriben delante y entre comillas dobles "", separadas por dos puntos. :, y luego siguió el valor:

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

Mucha gente no comprende la relación entre los objetos JSON y JavaScript, ni siquiera quién es quién. De hecho, se puede entender así:

JSON es la representación de cadena de objetos JavaScript y utiliza texto para representar la información de un objeto JS, que es esencialmente una cadena.

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

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

Convierta objetos JSON y JavaScript entre sí

Para convertir una cadena JSON en un objeto JavaScript, utilice el método JSON.parse()

Para convertir un objeto JavaScript en una cadena JSON, utilice el método JSON.stringify()

<!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. El controlador devuelve datos json

2.1 、 Jackson

Jackson debería ser una mejor herramienta de análisis json en la actualidad.

Por supuesto, existen más que estas herramientas, como fastjson de Alibaba, etc.

Usamos Jackson aquí

  1. Paquete de guía

    <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. Configuración requerida para configurar 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. clase de entidad

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

    @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 y comience a probar

Si encontramos que hay un problema de código confuso, podemos solucionarlo mediante el atributo produce de @RequestMaping y modificar el código.

@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;
    }

}

¡Empiece de nuevo y el código confuso se resolverá!

Solución uniforme para caracteres confusos.

El método anterior es más problemático. Si hay muchas solicitudes en el proyecto, se deben agregar cada una. Puede especificarlas de manera uniforme a través de la configuración de Spring, para que no tenga que lidiar con ellas cada vez.

¡Podemos agregar una configuración de conversión de mensaje StringHttpMessageConverter al archivo de configuración springmvc!

<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>

Devuelve una cadena json para una solución unificada

Utilice @RestController directamente en la clase . De esta manera, todos los métodos en ella solo devolverán cadenas json. ¡No es necesario agregar @ResponseBody a cada uno! En nuestro desarrollo front-end y back-end por separado, generalmente usamos @RestController, ¡lo cual es muy conveniente!

@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);
    }
}

Objeto de tiempo de salida

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

    Date date = new Date();

    return objectMapper.writeValueAsString(date);
}
  • El formato de fecha predeterminado se convertirá en un número, que es el número de milisegundos desde el 1 de enero de 1970 hasta la fecha actual.
  • Jackson convertirá la hora en marcas de tiempo de forma predeterminada.

Solución 1: formatéelo primero, luego conviértalo a json y devuélvalo

@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));
}

Solución 2: cancelar el formato de las marcas de tiempo y personalizar el formato de hora

  @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);
    }

Método de formato aquí extraemos una clase de herramienta.

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 es un paquete desarrollado por Alibaba específicamente para el desarrollo de Java, que puede convertir fácilmente objetos json y objetos JavaBean, convertir objetos JavaBean y cadenas json, y convertir objetos json y cadenas json. Hay muchas formas de convertir json y el resultado final es el mismo.

Paquete de guía

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

fastjson tiene tres clases principales:

  • JSONObject representa el objeto json

    • JSONObject implementa la interfaz Map y se supone que las operaciones subyacentes de JSONObject las implementa Map.
    • JSONObject corresponde al objeto json. Puede obtener los datos en el objeto json a través de varias formas de métodos get(). También puede usar métodos como size() e isEmpty() para obtener el número de pares "clave: valor". y determinar si están vacíos. Su esencia es implementar la interfaz Map y llamar a los métodos en la interfaz.
  • JSONArray representa una matriz de objetos json

    • Internamente, existen métodos en la interfaz Lista para completar la operación.
  • JSON representa la conversión de JSONObject y JSONArray

    • Análisis y uso del código fuente de la clase JSON
    • Observe estos métodos con atención, principalmente implementan la conversión mutua entre objetos json, matrices de objetos json, objetos javabean y cadenas json.

imagen-20220520152646273

imagen-20220520152711619

Para probar el código, creamos una nueva clase FastJsonDemo.

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);
    }
}

Solo necesitamos dominar el uso de este tipo de herramientas y, al utilizarlas, debemos encontrar la implementación correspondiente según el negocio específico. Al igual que el conjunto de herramientas commons-io anterior, ¡simplemente úselo!

6. Integrar SSM

Requisitos medioambientales

ambiente:

  • IDEA
  • MySQL 8.0.30
  • Gato 9
  • Maven 3.8.6

Requerir:

  • Es necesario dominar la base de datos MySQL, conocimientos de Spring, JavaWeb y MyBatis y conocimientos simples de front-end.

Entorno de base de datos

Crear una tabla de base de datos para almacenar datos de libros

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,'从进门到进牢');

Configuración básica del entorno

  1. ¡Crea un nuevo proyecto Maven! ssmbuild, agregar soporte web

  2. Importar dependencias pom relacionadas

    <!--  依赖 :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. configuración de filtrado de recursos maven

    <!--    静态资源导出问题-->
    <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. Establecer una estructura básica y un marco de configuración.

    • com.sue.pojo

    • com.sue.mapper

    • com.sue.servicio

    • 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>
      
    • aplicaciónContext.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>
      

Escritura de capa Mybatis

  1. Archivo de configuración de base de datos base de datos.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 de base de datos relacional

Insertar descripción de la imagen aquí

  1. Escriba el archivo de configuración principal mybatis-config.xml de 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. Escriba la clase de entidad Libros correspondiente a la tabla de la base de datos.

    El complemento Lombok se utiliza aquí.

    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. Escribe la interfaz del mapeador de la capa dao.

    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. Escriba el archivo Mapper.xml (BookMapper.xml) correspondiente a la interfaz, debe importar el paquete mybatis.

    <?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. Escriba la interfaz y la clase de implementación de la capa de servicio.

    LibroServicio.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);
    }
    

    LibroServiceImpl.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);
        }
    }
    

capa de primavera

  1. Configure Spring para integrar mybatis. Nuestra fuente de datos aquí utiliza el grupo de conexiones c3p0.

  2. Escribamos el archivo de configuración spring-dao.xml que integra spring con 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 integra la capa de servicio 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>
    

capa SpringMVC

  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. primavera-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. archivo de integración de configuración de Spring 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>
    

¡Archivo de configuración, finalizado temporalmente! Escritura de capa de vista y controlador

  1. Escritura del controlador del libro

    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. Escribir página de inicio 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. Página de lista de libros 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. Agregar página de libro 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. Modificar la página del libro 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>
    

Estructura general del proyecto:

Insertar descripción de la imagen aquí

7、ajax

Introducción

  • AJAX = JavaScript y XML asincrónicos (JavaScript y XML asincrónicos)
  • AJAX es una tecnología que puede actualizar partes de una página web sin recargar toda la página
  • AJAX no es un lenguaje de programación nuevo, sino una tecnología para crear aplicaciones web mejores, más rápidas y más interactivas.
  • En 2005, Google hizo popular AJAX con su Google Suggest. Google Suggest puede ayudarle automáticamente a completar los términos de búsqueda
  • Google Suggest utiliza AJAX para crear una interfaz web altamente dinámica: cuando ingresa palabras clave en el cuadro de búsqueda de Google, JavaScript enviará estos caracteres al servidor y luego el servidor devolverá una lista de sugerencias de búsqueda.
  • Al igual que el cuadro de búsqueda nacional de Baidu
  • Para las páginas web tradicionales (es decir, páginas web que no utilizan tecnología Ajax), si desea actualizar o enviar un formulario, debe volver a cargar toda la página web.
  • Las páginas web que utilizan tecnología Ajax pueden lograr actualizaciones parciales asincrónicas intercambiando una pequeña cantidad de datos en el servidor en segundo plano.
  • Con Ajax, los usuarios pueden crear interfaces de usuario web directas, de alta disponibilidad, más ricas y más dinámicas, cercanas a las aplicaciones de escritorio nativas.

ajax falso

Podemos usar una etiqueta en la parte frontal para simular una apariencia ajax. etiqueta de marco flotante

  1. Cree un nuevo módulo: springmvc-06-ajax, importe soporte web

  2. Escriba un iframe .html y utilícelo para probar y sentir el efecto.

    <!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>
    

Usando ajax puedes hacer:

  • Al registrarse, ingrese el nombre de usuario para detectar automáticamente si el usuario ya existe.
  • Al iniciar sesión, me indica que el nombre de usuario y la contraseña son incorrectos.
  • Al eliminar una fila de datos, la ID de la fila se envía al fondo y el fondo la elimina en la base de datos. Una vez que la base de datos se elimina correctamente, la fila de datos también se elimina en la página DOM.
  • 。。。

jQuery.ajax

Aquí no explicaremos la implementación nativa JS pura de Ajax, usaremos directamente la proporcionada por jquery, que es conveniente para el aprendizaje y el uso y evita reinventar la rueda. ¡Los estudiantes interesados ​​​​pueden aprender sobre XMLHttpRequest nativo de JS!

El núcleo de ajax es el objeto XMLHttpRequest (XHR). XHR proporciona una interfaz para enviar solicitudes al servidor y analizar las respuestas del servidor. Capacidad de obtener nuevos datos del servidor de forma asincrónica.

jQuery proporciona varios métodos relacionados con AJAX.

Con los métodos jQuery AJAX, puede solicitar texto, HTML, XML o JSON desde un servidor remoto utilizando HTTP Get y HTTP Post, y puede cargar estos datos externos directamente en elementos seleccionados de la página web.

jQuery no es un productor, es un portero de la naturaleza.

La esencia de jQuery Ajax es XMLHttpRequest, que está encapsulado para facilitar las llamadas.

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 将自动替换 ? 为正确的函数名,以执行回调函数

Hagamos una prueba sencilla, utilizando el procesamiento HttpServletResponse más original, el más simple y versátil.

  1. Configurar los archivos de configuración web.xml y springmvc

    <?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. Escribir un controlador Ajax

    @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. Para importar jquery, puede utilizar un CDN en línea o descargarlo e importarlo.

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

    <%@ 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>
    

Implementación de SpringMVC

  1. Usuario de clase de entidad

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
          
          
        private int id;
        private String name;
        private int age;
    }
    
  2. Obtengamos un objeto de colección y mostrémoslo en el método de adición del controlador de la página frontal.

    @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. Página de inicio

    <%@ 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. prueba

Insertar descripción de la imagen aquí

Efecto de solicitud de registro

Probemos una pequeña demostración nuevamente y pensemos en cómo lograr el aviso en tiempo real detrás del cuadro de entrada cuando normalmente nos registramos; cómo optimizarlo.

Escribamos un controlador

@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;
    }

Página de inicio 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>

[Recuerde solucionar el problema de json confuso]

<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>

Pruebe el efecto, respuesta de solicitud dinámica, actualización parcial, ¡eso es todo!

Insertar descripción de la imagen aquí

8. interceptor

Descripción general

El interceptor de procesador de SpringMVC es similar al filtro en el desarrollo de servlets, que se utiliza para preprocesar y posprocesar el procesador. Los desarrolladores pueden definir algunos interceptores para implementar funciones específicas.

La diferencia entre filtros e interceptores:

  • filtrar

    • Como parte de la especificación del servlet, se pueden utilizar funciones javaweb de tarea.
    • Después de configurar /* en el patrón de URL, se pueden interceptar todos los recursos a los que se accede.
  • Interceptador

    • El interceptor es propio del marco SpringMVC y solo puede ser utilizado por proyectos que utilizan el marco springmv.
    • El interceptor solo interceptará el método del controlador al que se accede. Si el acceso es jsp html css image js, no será interceptado.

interceptor personalizado

Si desea personalizar el interceptor, debe implementar la interfaz HandlerInterceptor

  1. Cree un nuevo módulo, springmvc-07-Interceptor y agregue soporte web

  2. Configurar archivos web.xml y springmvc-servlet.xml

  3. Escribe un 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 el interceptor en el archivo de configuración springmvc

    <!--关于拦截器的配置-->
    <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. Escriba un controlador para recibir solicitudes

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

Verificar si el usuario ha iniciado sesión (usuario autenticado)

Ideas de implementación

  1. Hay una página de inicio de sesión y necesita escribir un controlador para acceder a la página.
  2. La página de inicio de sesión tiene una acción para enviar el formulario. Debe manejarse en el controlador. Determine si el nombre de usuario y la contraseña son correctos. Si es correcto, escriba la información del usuario en la sesión. Volver a iniciar sesión correctamente
  3. Intercepte las solicitudes de los usuarios y determine si el usuario ha iniciado sesión. Si el usuario ya ha iniciado sesión. Suelte, si el usuario no ha iniciado sesión, salte a la página de inicio de sesión

lograr

  1. Escribe una página de inicio de sesión 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. Escribir un controlador para manejar solicitudes

    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. Escriba una página de inicio main.jsp después de iniciar sesión correctamente

    <%@ 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. ¡Pruebe el salto en la página de índice! Inicie la prueba de Tomcat y podrá ingresar a la página de inicio sin iniciar sesión

  5. Escribir un interceptor de inicio de sesión de usuario

    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. Registre el interceptor en el archivo de configuración Springmvc

    <mvc:interceptor>
        <mvc:mapping path="/user/**"/>
        <bean class="com.sue.config.LoginInterceptor"/>
    </mvc:interceptor>
    
  7. Reinicie tocat y pruebe

9. Carga y descarga de archivos

Preparación

La carga de archivos es una de las funciones más comunes en el desarrollo de proyectos. SpringMVC puede admitir muy bien la carga de archivos, pero MultipartResolver no está instalado de forma predeterminada en el contexto SpringMVC, por lo que no puede manejar la carga de archivos de forma predeterminada. Si desea utilizar la función de carga de archivos de Spring, debe configurar MultipartResolver en el contexto.

Requisitos del formulario de front-end: para cargar archivos, el método del formulario debe configurarse en POST y el tipo de cifrado debe configurarse en multipart/form-data. Sólo en este caso el navegador enviará el archivo seleccionado por el usuario al servidor como datos binarios;

Dé una explicación detallada del atributo enctype en el formulario:

  • application/x-www=form-urlencoded: el método predeterminado solo procesa el valor del atributo de valor en el campo del formulario. Un formulario que utiliza este método de codificación procesará el valor en el campo del formulario en codificación URL.
  • multipart/form-data: este método de codificación procesará los datos del formulario en una secuencia binaria. Este método de codificación también encapsulará el contenido del archivo especificado en el campo del archivo en los parámetros de solicitud y no codificará los caracteres.
  • Excepto para convertir espacios en signos "+", otros caracteres no están codificados. Este método es adecuado para enviar correos electrónicos directamente a través del formulario.
<form action="" enctype="multipart/form-data" method="post">
   <input type="file" name="file"/>
   <input type="submit">
</form>

Una vez que el enctype se establece en multipart/form-data, el navegador utilizará una secuencia binaria para procesar los datos del formulario, mientras que el procesamiento de cargas de archivos implica analizar la respuesta HTTP original en el lado del servidor. En 2003, la Apache Software Foundation lanzó el componente de código abierto Commons FileUpload, que rápidamente se convirtió en la mejor opción para que los programadores de Servlet/JSP cargaran archivos.

  • La especificación Servlet3.0 ya proporciona métodos para manejar la carga de archivos, pero esta carga debe completarse en el Servlet.
  • Spring MVC proporciona una encapsulación más simple
  • Spring MVC proporciona soporte directo para la carga de archivos, que se implementa utilizando MultipartResolver plug-and-play.
  • Spring MVC utiliza la tecnología Apache Commons FileUpload para implementar una clase de implementación MultipartResolver
  • CommonsMultipartResolver. Por lo tanto, la carga de archivos de SpringMVC también debe depender del componente Apache Commons FileUpload.

Subir archivo

  1. Importe el paquete jar para cargar archivos, commons-fileupload. Maven nos ayudará automáticamente a importar su paquete dependiente commons-io.

    <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. Bean de colocación: multipartResolver

    [ Nota ] Las configuraciones escritas aquí son todas fijas, no las cambie a voluntad.

    <!--文件上传配置-->
    <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>
    

    Métodos comunes de CommonsMultipartFile:

    • String getOriginalFilename(): obtiene el nombre original del archivo cargado
    • InputStream getInputStream(): obtiene la secuencia del archivo
    • void transferTo(Destino del archivo): guarda el archivo cargado en un archivo de directorio

    Vamos a probarlo.

  3. Escribir páginas de inicio

    <%@ 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. Controlador

    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";
        }
    }
    
    

Utilice file.Transto para guardar los archivos cargados

  1. Controlador de escritura

        /*
         * 采用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";
        }
    

Descargar Documento

Pasos para descargar el archivo:

  1. Establecer encabezado de respuesta
  2. Lectura de archivos – InputStream
  3. Escribir archivo – OutputStream
  4. realizar operaciones
  5. Cerrar la transmisión (primero abrir y luego cerrar)

Código:

@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;
}

Supongo que te gusta

Origin blog.csdn.net/Daears/article/details/126937089
Recomendado
Clasificación