[SpringMVC desde la entrada hasta el tutorial de combate real] Capítulo 3 Desarrollo de anotaciones de SpringMVC

3. Desarrollo de anotaciones SpringMVC

3.1 Pasos básicos

3.1.1 Controlador frontal

<?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.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>/views/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

3.1.2 espacio de nombres mvc y especificación de etiquetas

<?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:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        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
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

</beans>

3.1.3 Escaneo de componentes

<!-- 开启组件扫描 -->
<context:component-scan base-package="com.newcapec.controller"/>

3.1.4 Impulsado por anotaciones MVC

    SpringMVC usa `<mvc:annotation-driven>` para cargar automáticamente RequestMappingHandlerMapping (mapeador de procesador) y RequestMappingHandlerAdapter (adaptador de procesador), y carga muchos métodos de vinculación de parámetros de forma predeterminada, como el analizador de conversión json. Puede usar `<mvc:annotation-driven>` en el archivo de configuración springmvc.xml para reemplazar la configuración de los procesadores y adaptadores de anotación.

<!-- 注解式的处理器映射器 -->
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>-->

<!-- 注解式的处理器适配器 -->
<!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->

<!--
    mvc注解驱动:默认加载了注解式的处理器映射器和处理器适配器,默认转化器的配置
-->
<mvc:annotation-driven/>

3.1.5 Ver resolución

    Configure el prefijo y el sufijo de la resolución de vista para simplificar la dirección de acceso de la vista.

<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!-- 配置视图地址的前缀和后缀:简化视图地址 -->
    <property name="prefix" value="/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>

Configure los cambios en las rutas de acceso de prefijos y sufijos de la resolución de vistas:

  • Nombre de la vista física: antes de la configuración, la ruta de acceso real de la vista es /views/success.jsp

  • Nombre de vista lógica: después de la configuración, la ruta de acceso simplificada de la vista es correcta

  • Nombre de vista física = prefijo + nombre de vista lógica + sufijo

3.1.6 Procesador

@Controller
public class UserController {

    /**
     * 新增请求
     *
     * @RequestMapping 位置:类和方法
     * 作用:将请求路径与处理请求的方法关联
     * 注意:在配置路径时,路径需要以/开头
     */
    @RequestMapping("/addUser.do")
    public ModelAndView addUser() {
        System.out.println("新增用户请求...");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", "add user");
        /**
         * 配置视图解析器的前后缀之后访问路径的变化:/views/ /views/success.jsp .jsp
         * 在ModelAndView对象中设置的视图地址:逻辑视图名称 != 视图访问路径(物理视图名称)
         * 视图访问地址 = 前缀 + 逻辑视图名称 + 后缀
         */
        //modelAndView.setViewName("/views/success.jsp");
        modelAndView.setViewName("success");
        return modelAndView;
    }

    @RequestMapping("/editUser.do")
    public ModelAndView editUser() {
        System.out.println("编辑用户请求...");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", "edit user");
        modelAndView.setViewName("success");
        return modelAndView;
    }

    @RequestMapping("/removeUser.do")
    public ModelAndView removeUser() {
        System.out.println("删除用户请求...");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", "remove user");
        modelAndView.setViewName("success");
        return modelAndView;
    }

    @RequestMapping("/findUser.do")
    public ModelAndView findUser() {
        System.out.println("查询用户请求...");
        //模拟数据
        List<String> list = new ArrayList<>();
        list.add("zhangsan");
        list.add("lisi");
        list.add("tom");
        list.add("jerry");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("list", list);
        modelAndView.setViewName("success");
        return modelAndView;
    }
}

3.1.7 Vistas

    Cree un subdirectorio de "vistas" en el directorio de la aplicación web y coloque todas las vistas en el subdirectorio "vistas".

índice.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>首页</h1>
        <p><a href="addUser.do">新增用户</a></p>
        <p><a href="editUser.do">编辑用户</a></p>
        <p><a href="removeUser.do">删除用户</a></p>
        <p><a href="findUser.do">查询用户</a></p>
        <p><a href="url.do">路径映射1</a></p>
        <p><a href="getUrl.do">路径映射2</a></p>
        <p><a href="test.do">路径映射3</a></p>
        <p><a href="api/add.do">路径前缀</a></p>
        <p><a href="api/find.do">请求方法的限制</a></p>
        <form action="api/find.do" method="post">
            <button type="submit">提交</button>
        </form>
        <p><a href="forwardPage.do">请求转发到视图</a></p>
        <p><a href="redirectPage.do">重定向到视图</a></p>
        <p><a href="forwardController.do">请求转发到Controller</a></p>
        <p><a href="redirectController.do">重定向到Controller</a></p>
        <p><a href="returnVoid.do">无返回值</a></p>
        <p><a href="modelParam.do">Model类型的形参</a></p>
        <p><a href="views/simple.jsp">简单类型的形参</a></p>
        <p><a href="requestParam.do?empno=20">@RequestParam</a></p>
        <p><a href="dateTimeFormat.do?date=2022-03-21">@DateTimeFormat</a></p>
        <p><a href="requestHeader.do">@RequestHeader</a></p>
        <p><a href="setCookie.do">设置Cookie</a></p>
        <p><a href="getCookie.do">获取Cookie</a></p>
        <p><a href="views/pojo.jsp">POJO类型的形参</a></p>
        <p><a href="getBirthday.do?birthday=1993-04-17">Converter</a></p>
        <p><a href="getPoint.do?myPoint=125,369">Formatter</a></p>
        <p><a href="views/array.jsp">数组类型的形参</a></p>
        <p><a href="views/list.jsp">集合类型的形参</a></p>
        <p><a href="getUser.do">SessionAttribute</a></p>
        <p><a href="views/login.jsp">登录</a></p>
    </div>
</body>
</html>

exito.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>响应页面</h1>
        <p>${message}</p>
        <ul>
            <c:forEach items="${list}" var="s">
                <li>${s}</li>
            </c:forEach>
        </ul>
    </div>
</body>
</html>

3.2 Anotación @RequestMapping

    Hay varios métodos para procesar solicitudes en un controlador, como agregar usuarios, modificar la información del usuario, eliminar usuarios específicos y obtener listas de usuarios según las condiciones, etc. en UserController. Cada método es responsable de diferentes operaciones de solicitud y @RequestMapping es responsable de asignar la solicitud al método de controlador correspondiente.

    En la clase de controlador basada en anotaciones, puede escribir el método de procesamiento correspondiente para cada solicitud. Utilice la anotación @RequestMapping para hacer coincidir la solicitud con el método de procesamiento uno por uno.

    La anotación @RequestMapping se puede usar en clases o métodos. Usado en una clase, significa que todos los métodos en la clase que responden a las solicitudes usan esta dirección como la ruta principal.

Los atributos comunes de la anotación @RequestMapping son los siguientes:

    1. El atributo de valor
        El atributo de valor es el atributo predeterminado de la anotación @RequestMapping, por lo que si solo existe el atributo de valor, se puede omitir el nombre del atributo y, si hay otros atributos, se debe escribir el nombre del atributo de valor.
            @RequestMapping(value="toUser")
            @RequestMapping("toUser")
        El atributo value admite coincidencias con comodines, como @RequestMapping(value="toUser/*") significa http://localhost:8080/toUser/1 o http :/ /localhost:8080/toUser/hahaha se puede acceder normalmente.
    
    2. El atributo de ruta
        Tanto el atributo de ruta como el atributo de valor se utilizan como mapeo. Es decir, tanto @RequestMapping(value="toUser") como @RequestMapping(path="toUser") pueden acceder al método toUser().
        
    3. El atributo de nombre
        El atributo de nombre es equivalente al comentario del método, lo que hace que el método sea más fácil de entender. Como @RequestMapping(value = "toUser", name = "Obtener información del usuario" ).
        
    4. El atributo del método
        El atributo del método se utiliza para indicar qué solicitudes HTTP admite el método. Si se omite el atributo de método, el método admite todas las solicitudes HTTP.
    
    5. atributo de parámetros
        El atributo params se utiliza para especificar los parámetros especificados en la solicitud.
            @RequestMapping(value = "toUser", params = "type") 
            El código anterior indica que la solicitud debe contener el parámetro de tipo antes de que se pueda ejecutar la solicitud. Es decir, http://localhost:8080/toUser?type=xxx puede acceder al método toUser() normalmente, pero http://localhost:8080/toUser no puede acceder al método toUser() normalmente.
            @RequestMapping(value = "toUser", params = "type=1")
            El código anterior indica que la solicitud debe contener el parámetro de tipo, y la solicitud solo se puede ejecutar cuando el parámetro de tipo es 1. Es decir, http://localhost:8080/toUser?type=1 puede acceder al método toUser() normalmente, pero http://localhost:8080/toUser?type=2 no puede acceder al método toUser() normalmente.
       
    6. El atributo de encabezado
        El atributo de encabezado indica que algunos valores de encabezado especificados deben incluirse en la solicitud.
        @RequestMapping(value = "toUser", headers = "Referer=http://www.xxx.com") indica que el encabezado de la solicitud debe contener el encabezado de solicitud "Referer" especificado, y el valor es "http://www .xxx.
        

        El atributo de consumidores se usa para especificar el tipo de contenido enviado (Tipo de contenido) para procesar la solicitud, por ejemplo: aplicación/json, texto/html. Como 
        @RequestMapping(valor = "aUsuario", consumidores = "aplicación/json").
        
    8. El atributo produce
        El atributo produce se utiliza para especificar el tipo de contenido devuelto, y el tipo de contenido devuelto debe ser el tipo incluido en el encabezado de la solicitud (Aceptar). Como @RequestMapping(value = "toUser", produce = "application/json").

        Además, el atributo produce también puede especificar la codificación del valor de retorno. Como @RequestMapping(value = "toUser", produce = "application/json, charset=utf-8"), lo que significa devolver la codificación utf-8.

    Utilice @RequestMapping para completar la asignación, incluidos cuatro elementos de información: URL de solicitud, parámetros de solicitud, método de solicitud y encabezado de solicitud.

3.2.1 Mapeo de URL

    Asigne el método de URL (ruta de solicitud) y controlador (procesador).

@Controller
public class RequestMappingController {

    /**
     * @RequestMapping
     * 位置:方法
     * 属性:value和path一致,都是配置映射的路径
     * 注意:value和path的类型为字符串数组,在注解的属性中,如果类型为数组并且数组中的数据只有一个
     *      可以不使用数组,仅使用数组中的数据类型
     *      并且,多个请求路径可映射到同一个处理请求的方法上
     */
    //@RequestMapping(path = "/url.do")
    @RequestMapping(value = {"/url.do", "/getUrl.do" ,"/test.do"})
    public ModelAndView url(){
        System.out.println("测试@RequestMapping注解中的url映射功能...");
        return new ModelAndView("success");
    }
}

Aviso:

  • El valor de value puede ser una cadena o una matriz de cadenas, y se pueden asignar varias direcciones URL al mismo método.

  • La barra inclinada de la ruta de solicitud se puede agregar o no. Si no se agrega, SpringMVC la agregará automáticamente al buscar el mapeo, pero se recomienda agregar una barra inclinada para indicar que esta cadena es una ruta.

3.2.2 Solicitud de prefijo

    Agregue @RequestMapping(url) a la clase del controlador del controlador para especificar un prefijo de solicitud general, restringiendo todos los métodos de esta clase para que las URL de solicitud comiencen con el prefijo de solicitud y clasifique y administre las URL a través de este método.

/**
 * @RequestMapping
 * 位置:类
 * 作用:在该处理器中所有的方法映射路径前,都添加前缀
 *
 * 以前的路径:/add.do
 * 添加前缀之后:/api/add.do
 *
 * 项目中使用:
 * 用户模块:
 * @RequestMapping("/user")
 * /user/add.do
 * /user/edit.do
 * /user/remove.do
 * /user/find.do
 */
@Controller
@RequestMapping("/api")
public class RequestMappingController {

    @RequestMapping("/add.do")
    public ModelAndView add(){
        System.out.println("测试@RequestMapping注解使用在处理器的类上...");
        return new ModelAndView("success");
    }
}

3.2.3 Limitar método de solicitud http

    Por razones de seguridad, se imponen restricciones de método en los enlaces http. Si la solicitud está restringida al método de publicación y se realiza una solicitud de obtención, se producirá un error.

  • Limitar el método GET

/**
 * @RequestMapping注解中的method属性
 * 作用:用于限制http的请求方法
 *
 * method = RequestMethod.GET标签当前方法只能接收GET请求,其他请求方法会拒绝访问
 * 响应状态码为405表示http请求的方式与处理请求方法的限制不匹配
 */
@RequestMapping(value = "/find.do", method = RequestMethod.GET)
public ModelAndView find(){
    System.out.println("测试@RequestMapping注解对http协议中的请求方法的限制");
    return new ModelAndView("success");
}

Si se accede a través de POST, se informará un error:

  • Limitar el método POST

@RequestMapping(value = "/find.do", method = RequestMethod.POST)
public ModelAndView find(){
    System.out.println("测试@RequestMapping注解对http协议中的请求方法的限制");
    return new ModelAndView("success");
}

Si se accede a través de GET, se informará un error:

  • Tanto GET como POST están bien

@RequestMapping(value = "/find.do", method = {RequestMethod.POST, RequestMethod.GET})
public ModelAndView find(){
    System.out.println("测试@RequestMapping注解对http协议中的请求方法的限制");
    return new ModelAndView("success");
}

3.3 Valor de retorno del método del controlador

3.3.1 Modelo y tipo de vista

    Cuando el método deba finalizar, defina ModelAndView y configure el modelo y la vista respectivamente.

3.3.2 Tipo de cadena

3.3.2.1 Solicitud de reenvío para ver

La cadena devuelta por el método del controlador puede ser un nombre de vista lógica, que se puede resolver en una dirección de vista física mediante la resolución de vista:

@Controller
public class MethodReturnController {
    /**
     * 返回值类型为字符串String
     *
     * 回顾前奏知识:JavaWeb阶段两种页面跳转
     * 请求转发:共享request对象,属于服务器行为,页面中url地址不会变化
     * 重定向:不同的request对象,属于客户端行为,页面中url地址发生变化
     *
     * 1.请求转发到视图(JSP页面)
     * 2.重定向到视图(JSP页面)
     * 3.请求转发到处理器方法
     * 4.重定向到处理器方法
     */
    /**
     * 1.请求转发到视图
     * 方法的返回字符串:就是将要跳转的逻辑视图名称
     */
    @RequestMapping("/forwardPage.do")
    public String forwardPage(HttpServletRequest request){
        System.out.println("请求转发到JSP...");
        request.setAttribute("message", "hello");
        return "ok"; //表示请求转发到/views/ok.jsp页面中
    }
}

ok.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>跳转成功--ok.jsp</h1>
        <p>从request域中获取数据为:${requestScope.message}</p>
    </div>
</body>
</html>

3.3.2.2 Redireccionamiento a Vistas

La cadena de retorno del método Controlador es: antes de saltar a la ruta de vista, agregue redirect:un prefijo

@Controller
public class MethodReturnController {
    /**
     * 2.重定向到视图
     * 在返回值字符串的前面添加redirect:的前缀
     */
    @RequestMapping("/redirectPage.do")
    public String redirectPage(HttpServletRequest request){
        System.out.println("重定向到JSP...");
        request.setAttribute("message", "hello");
        return "redirect:/views/ok.jsp";
    }
}

Nota: Los nombres de vistas lógicas no se pueden usar después de la redirección: prefijo, se deben usar nombres de vistas físicas.

3.3.2.3 Método de reenvío de solicitudes al controlador

La solicitud se reenvía al mismo u otro método del procesador, y el método del controlador devuelve una cadena de: agregue un prefijo antes de la ruta de vista de salto forward:.

@Controller
public class MethodReturnController {
    /**
     * 3.请求转发到处理器方法
     * 在返回值字符串的前面添加forward:的前缀
     *
     * 注意:在forward:前缀之后不能使用逻辑视图名,必须使用物理视图名
     */
    @RequestMapping("/forwardController.do")
    public String forwardController(HttpServletRequest request){
        System.out.println("请求转发到另一个Controller的方法中....");
        request.setAttribute("message", "hello other");
        return "forward:/other.do";
    }
}

OtroControlador.java:

@Controller
public class OtherController {

    @RequestMapping("/other.do")
    public String other(HttpServletRequest request){
        System.out.println("OtherController处理器执行了....");
        System.out.println("request域对象中的数据为:" + request.getAttribute("message"));
        return "ok";
    }
}

3.3.2.4 Método de redirección al controlador

En el método de redireccionamiento al mismo u otro controlador, la cadena de retorno del método Controlador es: antes de la ruta de vista de salto, agregue redirect:un prefijo.

@Controller
public class MethodReturnController {
    /**
     * 4.重定向到处理器方法
     * 在返回值字符串的前面添加redirect:的前缀
     *
     * 注意:在redirect:前缀之后不能使用逻辑视图名,必须使用物理视图名
     */
    @RequestMapping("/redirectController.do")
    public String redirectController(HttpServletRequest request){
        System.out.println("重定向到另一个Controller的方法中....");
        request.setAttribute("message", "helloworld");
        return "redirect:/other.do";
    }
}

3.3.3 void no tiene valor de retorno

El objeto de solicitud y el objeto de respuesta se pueden definir en el parámetro del método del controlador, y el resultado de la respuesta se puede especificar mediante solicitud o respuesta.

@RequestMapping("/returnVoid.do")
public void returnVoid(HttpServletRequest request, HttpServletResponse response) throws IOException {
    System.out.println("处理器中方法没有返回值...");
    // request.getRequestDispatcher("").forward(request, response);
    // response.sendRedirect("");
    response.getWriter().println("<html><body><h1>success...</h1></body></html>");
}

3.4 Enlace de parámetros

3.4.1 Proceso de vinculación de parámetros SpringMVC

    El cliente solicita datos de clave/valor y vincula los datos de clave/valor a los parámetros formales del método del controlador a través del enlace de parámetros.

Nota: En SpringMVC, los datos enviados por la página receptora se reciben a través de los parámetros (parámetros formales) del método, en lugar de las variables miembro (parámetros reales) definidas en la clase Controller.

3.4.2 Tipos admitidos por defecto

    Estos objetos se pueden usar definiendo los siguientes tipos directamente en los parámetros del método del controlador. En el proceso de enlace de parámetros, si encuentra los siguientes tipos, enlace directamente.

    HttpServletRequest, obtenga la información de la solicitud a través del objeto de solicitud.
    
    HttpServletResponse, procesa la información de respuesta a través de la respuesta.
    
    HttpSession, a través del objeto de sesión para obtener el objeto almacenado en la sesión.
    
    Model/ModelMap, Model es una interfaz y ModelMap es una implementación de interfaz. Función: Complete los datos del modelo en el campo de solicitud.

@Controller
public class ParameterController {
    /**
     * 默认支持的类型
     * Model替代request域对象
     */
    @RequestMapping("/modelParam.do")
    public String modelParam(Model model){
        System.out.println("modelParam方法执行了...");
        model.addAttribute("message", "hello model");
        return "ok";
    }
}

3.4.3 Tipos simples

    Reciba los parámetros de solicitud a través de los parámetros formales del método del procesador y conviértalos automáticamente al tipo especificado (datos básicos, clase contenedora, tipo de fecha).

@Controller
public class ParameterController {
    /**
     * 简单类型形参
     * 通过处理器方法的形参接收请求参数,并且自动将其转换为指定的类型(基本数据,包装类,日期类型)
     *
     * 注意:
     * 1.请求参数名称与形参名保持一致
     * 2.日期类型默认格式为yyyy/MM/dd
     * 3.如果类型转换出现问题,SpringMVC并不会抛出异常,而是一个警告日志,客户端会收到400的响应状态码
     */
    @RequestMapping("/simple.do")
    public String simple(Integer empno, String ename, String job, Double sal, Date hiredate){

        System.out.println("员工编号:" + empno);
        System.out.println("员工姓名:" + ename);
        System.out.println("员工岗位:" + job);
        System.out.println("员工薪资:" + sal);
        System.out.println("入职日期:" + hiredate);
        return "index";
    }
}

simple.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>简单参数类型</h1>
        <form action="simple.do" method="post">
            <p>员工编号:<input type="text" name="empno"></p>
            <p>员工姓名:<input type="text" name="ename"></p>
            <p>员工岗位:<input type="text" name="job"></p>
            <p>员工薪资:<input type="text" name="sal"></p>
            <p>入职日期:<input type="text" name="hiredate"></p>
            <p><button>提交</button></p>
        </form>
    </div>
</body>
</html>

Nota :

  • El nombre del parámetro de solicitud es coherente con el nombre del parámetro formal.

  • El formato predeterminado del tipo de fecha es aaaa/MM/dd.

  • Si hay un problema con la conversión de tipos, SpringMVC no generará una excepción, sino un registro de advertencia, y el cliente recibirá un código de estado de respuesta 400.

  • @RequestParam

Los parámetros de tipos simples también se pueden vincular a través de la anotación @RequestParam:

  • Con @RequestParam, no es necesario restringir el nombre del parámetro que se pasa a la solicitud para que sea el mismo que el nombre del parámetro formal del método del controlador.

  • Utilice el atributo requerido para especificar si se debe pasar el parámetro. Si se establece en verdadero, si no se pasa ningún parámetro, se informará un error 400.

  • Puede usar valor predeterminado para establecer el valor predeterminado, incluso si requerido = verdadero, no puede pasar el valor del parámetro.

@Controller
public class ParameterController {
    /**
     * @RequestParam
     * 位置:方法的形参
     * 作用:
     * 1.value/name: 请求参数与方法形参进行映射
     * 2.required: 默认值为true,表示当前请求中必须带有该参数
     * 3.defaultValue: 形参的默认值
     */
    @RequestMapping("/requestParam.do")
    public String requestParam(@RequestParam(value = "empno", required = false, defaultValue = "100") Integer id){
        System.out.println("请求参数:" + id);
        return "index";
    }
}
  • @DateTimeFormat

Formatee la fecha de acuerdo con el formato especificado:

@Controller
public class ParameterController {
    /**
     * @DateTimeFormat
     * 位置:方法的形参,成员变量
     * 作用:按照指定格式进行日期格式化
     */
    @RequestMapping("/dateTimeFormat.do")
    public String dateTimeFormat(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){
        System.out.println("日期为:" + date);
        return "index";
    }
}
  • @RequestHeader

Obtenga la información del encabezado de la solicitud especificada:

@Controller
public class ParameterController {
    /**
     * @RequestHeader
     * 位置:方法的形参
     * 作用:获取指定的请求头信息
     */
    @RequestMapping("/requestHeader.do")
    public String requestHeader(@RequestHeader("Accept-Encoding") String encoding){
        System.out.println("请求头信息:" + encoding);
        return "index";
    }
}
  • @ValorCookie

Obtener el valor de cookie especificado:

@Controller
public class ParameterController {
    /**
     * 设置Cookie
     * 会话:HttpSession,存储在服务器端,Cookie存储HttpSession对象的唯一标识JSESSIONID
     */
    @RequestMapping("/setCookie.do")
    public String setCookie(HttpServletResponse response){
        System.out.println("设置Cookie...");
        Cookie myCookie = new Cookie("username", "xiaoming");
        myCookie.setPath("/");
        // 设置myCookie的有效期为一天
        myCookie.setMaxAge(60 * 60 * 24);
        response.addCookie(myCookie);
        return "index";
    }

    /**
     * @CookieValue
     * 位置:方法的形参
     * 作用:获取指定的Cookie值
     */
    @RequestMapping("/getCookie.do")
    public String getCookie(@CookieValue("username") String username){
        System.out.println("Cookie:" + username);
        return "index";
    }
}

3.4.4 Tipos POJO

  • Obtenga los parámetros de solicitud y cree el objeto POJO especificado.

  • Si el nombre de la variable miembro del objeto es coherente con el nombre del parámetro de solicitud, el valor del parámetro de solicitud se puede establecer en el objeto POJO.

  • Cuando la variable miembro del objeto también es un objeto POJO, el nombre del parámetro de solicitud es: Nombre de variable miembro de tipo POJO. Nombre de variable miembro.

POJO:

public class Dept {
    
    private Integer deptno;
    private String dname;

    public Integer getDeptno() {
        return deptno;
    }

    public void setDeptno(Integer deptno) {
        this.deptno = deptno;
    }

    public String getDname() {
        return dname;
    }

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptno=" + deptno +
                ", dname='" + dname + '\'' +
                '}';
    }
}


public class Emp {
    
    private Integer empno;
    private String ename;
    private String job;
    private Double sal;
    /**
     * @DateTimeFormat可以用在形参,也可以用在字段、方法上,都是用来做日期格式化的
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date hiredate;

    private Dept dept;

    public Integer getEmpno() {
        return empno;
    }

    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Double getSal() {
        return sal;
    }

    public void setSal(Double sal) {
        this.sal = sal;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", sal=" + sal +
                ", hiredate=" + hiredate +
                ", dept=" + dept +
                '}';
    }
}

procesador:

@Controller
public class ParameterController {
    /**
     * POJO类型的形参
     * 要求:请求参数名称必须与POJO对象中成员名称保持一致
     *
     * springmvc获取请求参数,并且创建指定POJO对象,
     * 根据请求参数名与POJO对象成员变量的名称,通过setter方法进行赋值
     */
    @RequestMapping("/pojoParam.do")
    public String pojoParam(Emp emp){
        System.out.println(emp);
        return "redirect:/views/index.jsp";
    }
}

pojo.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>POJO参数类型</h1>
        <form action="pojoParam.do" method="post">
            <p>员工编号:<input type="text" name="empno"></p>
            <p>员工姓名:<input type="text" name="ename"></p>
            <p>员工岗位:<input type="text" name="job"></p>
            <p>员工薪资:<input type="text" name="sal"></p>
            <p>入职日期:<input type="text" name="hiredate"></p>
            <p>部门:<select name="dept.deptno">
                <option value="1">人力部</option>
                <option value="2">研发部</option>
                <option value="3">销售部</option>
            </select></p>
            <p><button>提交</button></p>
        </form>
    </div>
</body>
</html>

3.4.5 Convertidores de tipo personalizado

  • SpringMVC viene con muchos convertidores que pueden completar la mayoría de las conversiones de tipo Java.

  • ConversionService es la interfaz central del sistema de conversión de tipo Spring.

  • Puede usar org.springframework.format.support.FormattingConversionServiceFactoryBean para definir un ConversionService en el contenedor IOC. SpringMVC reconocerá automáticamente ConversionService y lo usará para convertir tipos de datos en ocasiones como el enlace de parámetros del método del procesador.

3.4.5.1 Interfaz del convertidor

    Interfaz org.springframework.core.convert.converter.Converter, características: cualquier tipo se puede convertir a otro tipo arbitrario.

Clase de implementación:

/**
 * 自定义的全局日期格式转换器
 * 实现Converter<S, T>接口
 * S : 原有类型,待转换类型
 * T : 转换之后的类型
 */
public class DateConverter implements Converter<String, Date> {
    private String partten = "yyyy-MM-dd";
    
    public void setPartten(String partten) {
        this.partten = partten;
    }
    /**
     * 日期格式转换
     * @param source 待转换类型的字符串数据
     * @return 转换之后的日期类型数据
     */
    @Override
    public Date convert(String source) {
        System.out.println("全局日期格式转换工具执行了....");
        SimpleDateFormat sdf = new SimpleDateFormat(partten);
        try {
            return sdf.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Configuración:

<mvc:annotation-driven conversion-service="formattingConversionService"/>
<!-- 配置格式化与转化服务 -->
<!--
    FormattingConversionService: 提供自定义的数据格式化与类型转换服务对象

	FormattingConversionService需要告知/配置给处理器适配器
-->
<bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <!-- 注册自定义的全局日期格式转换工具 -->
    <property name="converters">
        <set>
            <bean class="com.newcapec.util.DateConverter">
                <!--<property name="partten" value="yyyy-MM-dd HH:mm:ss"/>-->
            </bean>
        </set>
    </property>
</bean>

procesador:

@Controller
public class ParameterController {
    
    @RequestMapping("/getBirthday.do")
    public String getBirthday(Date birthday) {
        System.out.println("生日:" + birthday);
        return "index";
    }
}

3.4.5.2 Interfaz del formateador

    Interfaz org.springframework.format.Formatter, características: cualquier tipo especificado se puede convertir a tipo String, y el tipo String también se puede convertir a cualquier tipo especificado.

Tipo personalizado:

public class MyPoint {
    private int x;
    private int y;

    public MyPoint() {
    }

    public MyPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    @Override
    public String toString() {
        return "MyPoint{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}

Clase de implementación:

/**
 * 类型格式化器
 * 实现Formatter<T>接口
 * T : 转换之后的格式
 *
 * Converter与Formatter
 * Converter可以实现任意两种类型之间的转换,单向转换,只能将第一个泛型的类型转换为第二个泛型的类型
 * Formatter只能实现String与任意类型之间的格式化,双向转换
 */
public class MyPointFormatter implements Formatter<MyPoint> {
    @Override
    public MyPoint parse(String text, Locale locale) throws ParseException {
        //125,369
        String[] ss = text.split(",");
        return new MyPoint(Integer.parseInt(ss[0]),Integer.parseInt(ss[1]));
    }

    @Override
    public String print(MyPoint object, Locale locale) {
        return null;
    }
}

Configuración:

<bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="formatters">
        <set>
            <bean class="com.newcapec.util.MyPointFormatter"/>
        </set>
    </property>
</bean>

procesador:

@Controller
public class ParameterController {
    @RequestMapping("/getPoint.do")
    public String getPoint(MyPoint myPoint) {
        System.out.println("坐标:" + myPoint);
        return "index";
    }
}

3.4.6 Tipos de matrices

    Seleccione varias identificaciones en la página a través del cuadro de selección múltiple y páselas a los parámetros formales del método del controlador. Los parámetros formales del método usan una matriz para recibir varias identificaciones solicitadas por la página para lograr la eliminación por lotes.

@Controller
public class ParameterController {
    /**
     * 数组类型的参数
     * 客户端的提交规则: 一个请求参数名称对应多个请求参数值
     * 原生Servlet: String[] request.getParametervalues()
     * 
     * 特殊情况:
     * 当形参为数组类型,而请求参数值中的数据又是以逗号间隔,SpringMVC会按照逗号进行拆分,解析到数组中
     * 例如:请求参数为 ids=1,2,3,4,5  形参: 数组{1,2,3,4,5}
     */
    @RequestMapping("/removeBatch.do")
    public String removeBatch(Integer[] ids){
        System.out.println("批量删除的id为:" + Arrays.toString(ids));
        return "index";
    }
}

matriz.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>批量删除</h1>
        <form action="removeBatch.do">
            <table border="1" width="500" align="center">
                <tr>
                    <th><input type="checkbox"></th>
                    <th>部门编码</th>
                    <th>部门名称</th>
                </tr>
                <tr>
                    <td><input type="checkbox" name="ids" value="10"/></td>
                    <td>10</td>
                    <td>研发部</td>
                </tr>
                <tr>
                    <td><input type="checkbox" name="ids" value="20"/></td>
                    <td>20</td>
                    <td>人力部</td>
                </tr>
                <tr>
                    <td><input type="checkbox" name="ids" value="30"/></td>
                    <td>30</td>
                    <td>企划部</td>
                </tr>
            </table>
            <button>提交</button>
        </form>
    </div>
</body>
</html>

3.4.7 Tipos de colecciones

    SpringMVC no puede vincular directamente los parámetros formales del tipo de colección y necesita usar objetos POJO para realizarlo. El tipo de colección se puede definir como un atributo de una clase POJO, y el tipo POJO se usa como un parámetro formal del método Controller.

POJO:

public class CollectionBean {
    private List<Dept> deptList;

    public List<Dept> getDeptList() {
        return deptList;
    }

    public void setDeptList(List<Dept> deptList) {
        this.deptList = deptList;
    }
}

Controlador:

@Controller
public class ParameterController {
    /**
     * 集合类型的参数
     * 注意:springmvc中集合类型不能直接作为形参
     *      需要通过一个pojo对象包装,在一个pojo对象中含有一个集合类型的成员变量
     *
     * 批量新增或编辑数据
     */
    // public String insertBatch(List<String> list){ //错误的,不支持的
    //
    // }
    @RequestMapping("/insertBatch.do")
    public String insertBatch(CollectionBean bean){
        System.out.println("批量提交的部门:" + bean.getDeptList());
        return "index";
    }
}

lista.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>批量新增</h1>
        <form action="insertBatch.do" method="post">
            <table border="1" width="500" align="center">
                <tr>
                    <th>部门编码</th>
                    <th>部门名称</th>
                </tr>
                <tr>
                    <!-- 集合中的第一个元素:deptList.get(0) = deptList[0] -->
                    <td><input type="text" name="deptList[0].deptno"></td>
                    <td><input type="text" name="deptList[0].dname"></td>
                </tr>
                <tr>
                    <td><input type="text" name="deptList[1].deptno"></td>
                    <td><input type="text" name="deptList[1].dname"></td>
                </tr>
                <tr>
                    <td><input type="text" name="deptList[2].deptno"></td>
                    <td><input type="text" name="deptList[2].dname"></td>
                </tr>
            </table>
            <button>提交</button>
        </form>
    </div>
</body>
</html>

3.4.8 @Atributo de sesión

    Obtenga los datos del objeto especificado de HttpSession.

@Controller
public class ParameterController {
    /**
     * @SessionAttribute
     * 位置:方法的形参
     * 作用:从HttpSession中获取指定对象数据
     */
    @RequestMapping("/getUser.do")
    public String getUser(@SessionAttribute("loginUser") User user){
        System.out.println("登录用户:" + user);
        return "index";
    }
}

Clase de usuario:

public class User {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

Iniciar sesión en el controlador:

@Controller
public class LoginController {

    @RequestMapping("/login.do")
    public String login(User user, HttpSession session){
        System.out.println("登录操作...");
        session.setAttribute("loginUser", user);
        return "index";
    }
}

inicio de sesión.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <base href="${pageContext.request.contextPath}/">
    <title>Title</title>
</head>
<body>
    <div style="text-align: center">
        <h1>登录</h1>
        <form action="login.do" method="post">
            <p>用户名:<input type="text" name="username"></p>
            <p>密&emsp;码:<input type="text" name="password"></p>
            <p><button>提交</button></p>
        </form>
    </div>
</body>
</html>

Supongo que te gusta

Origin blog.csdn.net/ligonglanyuan/article/details/125167057
Recomendado
Clasificación