SpringMVC注解开发

三、SpringMVC注解开发

1. 基本步骤

1.1 前端控制器

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

1.2 mvc命名空间与标签规范

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

1.3 组件扫描

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

1.4 MVC注解驱动

SpringMVC使用<mvc:annotation-driven>自动加载RequestMappingHandlerMapping(处理器映射器)和RequestMappingHandlerAdapter(处理器适配器),并且默认加载了很多参数绑定的方法,比如json转换解析器。可用在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解处理器和适配器的配置

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

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

1.5 视图解析器

配置视图解析器的前缀和后缀,可简化视图的访问地址。

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

配置视图解析器的前缀与后缀访问路径的变化:

  • 物理视图名称:配置之前,视图的真实访问路径为,/views/success.jsp
  • 逻辑视图名称:配置之后,视图的简化访问路径为,success
  • 物理视图名 = 前缀 + 逻辑视图名 + 后缀

1.6 处理器

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

1.7 视图

在webapp目录下建立“views”子目录,所有视图放置在“views”子目录中。

index.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=2019-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>

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

2. @ResquestMapping注解

通过@RequestMapping注解可以定义不同的处理器映射规则

2.1 url映射

对url(请求路径)和handler(处理器)的方法进行映射

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

注意

  • value的值可为字符串或字符串数组,可以将多个url映射到同一个方法
  • 请求路径的前斜杠,可加可不加,如果不加SpringMVC在查找映射时会自动加入,但是建议加上斜杠表示此字符串为路径

2.2 请求前缀

在控制器handler类上添加@RequestMapping(url)指定通用请求前缀,限制此类下的所有方法请求url必须以请求前缀开头,通过此方法对url进行分类管理

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

2.3 限制http请求方法

出于安全性考虑,对http的链接进行方法限制。如果限制请求为post方法,进行get请求,会出现报错

  • 限定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");
}

如果通过POST访问则报错:

在这里插入图片描述

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

如果通过GET访问则报错:
在这里插入图片描述

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

3. Controller方法返回值

3.1 ModelAndView类型

需要方法结束时,定义ModelAndView,将model和view分别进行设置

3.2 String类型

3.2.1 请求转发到视图

Controller方法返回字符串可以为逻辑视图名,通过视图解析器将其解析为物理视图地址

@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.2.2 重定向到视图

Controller方法返回字符串为:在跳转视图路径前,添加**redirect:**前缀

@Controller
public class MethodReturnController {
    /**
     * 2.重定向到视图
     * 在返回值字符串的前面添加redirect:的前缀
     *
     * 注意:在redirect:前缀之后不能使用逻辑视图名,必须使用物理视图名
     */
    @RequestMapping("/redirectPage.do")
    public String redirectPage(HttpServletRequest request){
        System.out.println("重定向到JSP...");
        request.setAttribute("message", "hello");
        return "redirect:/views/ok.jsp";
    }
}

注意:在**redirect:**前缀之后不能使用逻辑视图名,必须使用物理视图名

3.2.3 请求转发到处理器方法

请求转发到同一个或另一个处理器的方法中,Controller方法返回字符串为:在跳转视图路径前,添加**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";
    }
}

OtherController.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.2.4 重定向到处理器方法

重定向到同一个或另一个处理器的方法中,Controller方法返回字符串为:在跳转视图路径前,添加**redirect:**前缀

@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 void无返回值

在Controller方法形参上可以定义request对象和response对象,使用request或response指定响应结果

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

4. 参数绑定

4.1 SpringMVC参数绑定过程

客户端请求key/value数据,经过参数绑定,将key/value数据绑定到Controller方法的形参上

在这里插入图片描述

注意:在SpringMVC中,接收页面提交的数据是通过方法的参数(形参)来接收,而不是在Controller类定义成员变量(实参)接收!!!!

4.2 默认支持的类型

直接在controller方法形参上定义下边类型,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定

  • HttpServletRequest
    通过request对象获取请求信息
  • HttpServletResponse
    通过response处理响应信息
  • HttpSession
    通过session对象得到session中存放的对象
  • Model/ModelMap
    Model是一个接口,ModelMap是一个接口实现
    作用:将model数据填充到request域
@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";
    }
}

4.3 简单类型

通过处理器方法的形参接收请求参数,并且自动将其转换为指定的类型(基本数据,包装类,日期类型)

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

注意

  • 请求参数名称与形参名保持一致
  • 日期类型默认格式为yyyy/MM/dd
  • 如果类型转换出现问题,SpringMVC并不会抛出异常,而是一个警告日志,客户端会收到400的响应状态码

在这里插入图片描述

@RequestParam

通过@RequestParam注解也可对简单类型的参数进行绑定

  • 使用@RequestParam,不用限制request传入参数名称和Controller方法的形参名称一致
  • 通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,报400错误
  • 可以使用defaultvalue设置默认值,即使required=true也可以不传参数值
@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

按照指定格式进行日期格式化

@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

获取指定的请求头信息

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

获取指定的Cookie值

@Controller
public class ParameterController {
    /**
     * 设置Cookie
     */
    @RequestMapping("/setCookie.do")
    public String setCookie(HttpServletResponse response){
        System.out.println("设置Cookie...");
        Cookie myCookie = new Cookie("username", "xiaoming");
        myCookie.setPath("/");
        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";
    }
}

4.4 POJO类型

  • 获取请求参数,并且创建指定POJO对象
  • 对象的成员变量名称与请求参数名称一致,就可以将请求参数值设置在POJO对象中
  • 对象的成员变量也是一个POJO对象时,那么请求参数的名称为:POJO类型的成员变量名.成员变量名

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(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 +
                '}';
    }
}

处理器

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

4.5 自定义类型转换器

  • SpringMVC中自带了很多转换器,可完成大多数Java类型的转换工作
  • ConversionService是Spring类型转换体系的核心接口
  • 可以利用org.springframework.format.support.FormattingConversionServiceFactoryBean在IOC容器中定义一个ConversionService。SpringMVC将自动识别出ConversionService,并在处理器方法参数绑定等场合使用它进行数据类型的转换
4.5.1 Converter接口

org.springframework.core.convert.converter.Converter接口,特点:可将任意类型转换为另一个任意类型

实现类

/**
 * 自定义的全局日期格式转换器
 * 实现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;
    }
}

配置

<mvc:annotation-driven conversion-service="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>

处理器

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

org.springframework.format.Formatter接口,特点:可将任意指定类型转换为String类型,也可将String类型转换为任意指定类型

自定义类型

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

实现类

/**
 * 类型格式化器
 * 实现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;
    }
}

配置

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

处理器

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

4.6 数组类型

将页面上通过多选框选中多个的id,传到Controller方法的形参,方法形参使用数组接收页面请求的多个id,实现批量删除

@Controller
public class ParameterController {
    /**
     * 数组类型的参数
     * 客户端的提交规则: 一个请求参数名称对应多个请求参数值
     * 原生Servlet: String[] request.getParametervalues()
     */
    @RequestMapping("/removeBatch.do")
    public String removeBatch(Integer[] ids){
        System.out.println("批量删除的id为:" + Arrays.toString(ids));
        return "index";
    }
}

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

4.7 集合类型

SpringMVC无法直接绑定集合类型的形参,需要利用POJO对象才可实现。可将集合类型定义为一个POJO类的属性,该POJO类型作为Controller方法的形参

POJO类

public class CollectionBean {
    private List<Dept> deptList;

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

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

Controller

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

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

4.8 @SessionAttribute

从HttpSession中获取指定对象数据

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

用户

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 + '\'' +
                '}';
    }
}

登录Controller

@Controller
public class LoginController {

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

login.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>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JTZ001

你的鼓励是我创作的最大动力?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值