乐趣区

关于spring-mvc:SpringMVC基础之二SpringMVC的使用

(1)SpringMVC 的申请解决

1、SpringMVC 对申请参数的解决

​ 在之前的 servlet 中咱们能够通过 request.getParameter()来获取申请中的参数,然而在咱们编写的 SpringMVC 的应用程序中,在具体申请的办法中并不蕴含 request 参数,那么咱们应该如何获取申请中的参数呢?

​ 须要应用以下几个注解:

​ @RequestParam:获取申请的参数

​ @RequestHeader:获取申请头信息

​ @CookieValue:获取 cookie 中的值

@RequestParam 的根本应用

package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class RequestController {

    /**
     * 如何获取 SpringMVC 中申请中的信息
     *  默认状况下,能够间接在办法的参数中填写跟申请一样的名称,此时会默认承受参数
     *      如果有值,间接赋值,如果没有,那么间接给空值
     *
     * @RequestParam: 获取申请中的参数值, 应用此注解之后,参数的名称不须要跟申请的名称统一,然而必须要写
     *      public String request(@RequestParam("user") String username){
     *
     *      此注解还蕴含三个参数:*      value: 示意要获取的参数值
     *      required:示意此参数是否必须,默认是 true,如果不写参数那么会报错,如果值为 false,那么不写参数不会有任何谬误
     *      defaultValue: 如果在应用的时候没有传递参数,那么定义默认值即可
     *
     *
     * @param username
     * @return
     */
    @RequestMapping("/request")
    public String request(@RequestParam(value = "user",required = false,defaultValue = "hehe") String username){System.out.println(username);
        return "success";
    }
}

@RequestHeader 的根本应用:

package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import sun.management.resources.agent;

@Controller
public class RequestController {

    /**
     * 如果须要获取申请头信息该如何解决呢?*  能够应用 @RequestHeader 注解,*      public String header(@RequestHeader("User-Agent") String agent){*      相当于  request.getHeader("User-Agent")
     *
     *      如果要获取申请头中没有的信息,那么此时会报错,同样,此注解中也蕴含三个参数, 跟 @RequestParam 一样
     *          value
     *          required
     *          defalutValue
     * @param agent
     * @return
     */
    @RequestMapping("/header")
    public String header(@RequestHeader("User-Agent") String agent){System.out.println(agent);
        return "success";
    }
}

@CookieValue 的根本应用

package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import sun.management.resources.agent;

@Controller
public class RequestController {

    /**
     * 如果须要获取 cookie 信息该如何解决呢?*  能够应用 @CookieValue 注解,*      public String cookie(@CookieValue("JSESSIONID") String id){
     *      相当于
     *      Cookie[] cookies = request.getCookies();
     *      for(Cookie cookie : cookies){*          cookie.getValue();
     *      }
     *      如果要获取 cookie 中没有的信息,那么此时会报错,同样,此注解中也蕴含三个参数, 跟 @RequestParam 一样
     *          value
     *          required
     *          defalutValue
     * @param id
     * @return
     */
    @RequestMapping("/cookie")
    public String cookie(@CookieValue("JSESSIONID") String id){System.out.println(id);
        return "success";
    }
}

如果申请中传递的是某一个对象的各个属性值,此时如何在控制器的办法中获取对象的各个属性值呢?

​ 在 SpringMVC 的管制中,能间接实现对象的属性赋值操作,不须要人为干涉。

User.java

package com.mashibing.bean;

import java.util.Date;

public class User {
    private Integer id;
    private String name;
    private Integer age;
    private Date date;
    private Address address;

    public Integer getId() {return id;}

    public void setId(Integer id) {this.id = id;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public Integer getAge() {return age;}

    public void setAge(Integer age) {this.age = age;}

    public Date getDate() {return date;}

    public void setDate(Date date) {this.date = date;}

    public Address getAddress() {return address;}

    public void setAddress(Address address) {this.address = address;}

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", date=" + date +
                ", address=" + address +
                '}';
    }
}

Address.java

package com.mashibing.bean;

public class Address {
    private String province;
    private String city;
    private String town;

    public String getProvince() {return province;}

    public void setProvince(String province) {this.province = province;}

    public String getCity() {return city;}

    public void setCity(String city) {this.city = city;}

    public String getTown() {return town;}

    public void setTown(String town) {this.town = town;}

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                ", town='" + town + '\'' +
                '}';
    }
}

login.jsp

<%--
  Created by IntelliJ IDEA.
  User: root
  Date: 2020/3/7
  Time: 0:11
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="addUser" method="post">
    编号:<input type="text" name="id"/><br>
    姓名:<input type="text" name="name"/><br>
    年龄:<input type="text" name="age"/><br>
    日期:<input type="text" name="date"/><br>
    省份:<input type="text" name="address.province"/><br>
    城市:<input type="text" name="address.city"/><br>
    区域:<input type="text" name="address.town"/><br>
    <input type="submit" value="submit"/><br>
</form>
</body>
</html>

UserController.java

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {@RequestMapping("/addUser")
    public String addUser(User user){System.out.println(user);
        return "success";
    }
}
2、乱码问题的解决

​ 咱们在表单或者发送申请的时候,常常会遇到中文乱码的问题,那么如何解决乱码问题呢?

​ GET 申请:在 server.xml 文件中,增加 URIEncoding=“UTF-8”

​ POST 申请:编写过滤器进行实现

<?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 的配置文件:此配置文件的属性能够不增加,然而须要在 WEB-INF 的目录下创立 前端控制器名称 -servlet.xml 文件
        -->

        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
    </servlet>
    <!-- 匹配 servlet 的申请,/:标识匹配所有申请,然而不会 jsp 页面
    /*:拦挡所有申请,拦挡 jsp 页面

     然而须要留神的是,当配置成 index.html 的时候,会发现申请不到
     起因在于,tomcat 下也有一个 web.xml 文件,所有的我的项目下 web.xml 文件都须要继承此 web.xml
     在服务器的 web.xml 文件中有一个 DefaultServlet 用来解决动态资源,然而 url-pattern 是 /
     而咱们在本人的配置文件中如果增加了 url-pattern=/ 会笼罩父类中的 url-pattern,此时在申请的时候
     DispatcherServlet 会去 controller 中做匹配,找不到则间接报 404
     而在服务器的 web.xml 文件中蕴含了一个 JspServlet 的解决,所以不过拦挡 jsp 申请
    -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 解决 post 申请乱码 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!-- 解决响应乱码 -->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

留神:如果配置了多个过滤器,那么字符编码过滤器肯定要在最后面,否则生效。

3、SpringMVC 对原生 API 的反对
package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.PrintWriter;

@Controller
public class UserController {@RequestMapping("/addUser")
    public String addUser(User user){System.out.println(user);
        return "success";
    }

    /**
     * SpringMVC 也能够在参数上应用原生的 Servlet API
     *
     *  HttpSession
     *  HttpServletRequest
     *  HttpServletResponse
     *
     *  java.security.Principal 平安协定相干
     *  Locale:国际化相干的区域信息对象
     *  InputStream:
     *      ServletInputStream inputStream = request.getInputStream();
     *  OutputStream:
     *      ServletOutputStream outputStream = response.getOutputStream();
     *  Reader:
     *      BufferedReader reader = request.getReader();
     *  Writer:
     *      PrintWriter writer = response.getWriter();
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("api")
    public String api(HttpSession session, HttpServletRequest request, HttpServletResponse response){request.setAttribute("requestParam","request");
        session.setAttribute("sessionParam","session");
        return "success";
    }
}
4、应用 Model,Map,ModelMap 传输数据到页面

​ 在刚开始的 helloworld 我的项目中,咱们传递了参数回到咱们页面,然而后续的操作都只是承受用户的申请,那么在 SpringMVC 中除了能够应用原生 servlet 的对象传递数据之外,还有什么其余的形式呢?

​ 能够在办法的参数上传入 Model,ModelMap,Map 类型,此时都可能将数据传送回页面

OutputController.java

package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

@Controller
public class OutputController {@RequestMapping("output1")
    public String output1(Model model){model.addAttribute("msg","hello,Springmvc");
        return "output";
    }

    @RequestMapping("output2")
    public String output2(ModelMap model){model.addAttribute("msg","hello,Springmvc");
        return "output";
    }

    @RequestMapping("output3")
    public String output1(Map map){map.put("msg","hello,Springmvc");
        return "output";
    }
}

当应用此形式进行设置之后,会发现所有的参数值都设置到了 request 作用域中,那么这三个对象是什么关系呢?

5、应用 ModelAndView 对象传输数据到页面
package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class OutputController {@RequestMapping("mv")
    public ModelAndView mv(){ModelAndView mv = new ModelAndView();
        mv.setViewName("output");
        mv.addObject("msg","hello.modelAndView");
        return mv;
    }
}

​ 发现当应用 modelAndView 对象的时候,返回值的类型也是此对象,能够将要跳转的页面设置成 view 的名称,来实现跳转的性能,同时数据也是放到 request 作用中。

6、应用 session 传输数据到页面

@SessionAttribute:此注解能够示意,当向 request 作用域设置数据的时候同时也要向 session 中保留一份, 此注解有两个参数,一个 value(示意将哪些值设置到 session 中),另外一个 type(示意依照类型来设置数据,个别不必,因为有可能会将很多数据都设置到 session 中,导致 session 异样)。

@Controller
@SessionAttributes(value = "msg")
public class OutputController {@RequestMapping("output1")
    public String output1(Model model){model.addAttribute("msg","hello,Springmvc");
        System.out.println(model.getClass());
        return "output";
    }
}
7、应用 @ModelAttribute 来获取申请中的数据

​ @ModelAttribute 注解用于将办法的参数或者办法的返回值绑定到指定的模型属性上,并返回给 web 视图。首先来介绍一个业务场景,来帮忙大家做了解,在理论工作中,有些时候咱们在批改数据的时候可能只须要批改其中几个字段,而不是全副的属性字段都获取,那么当提交属性的时候,从 form 表单中获取的数据就有可能只蕴含了局部属性,此时再向数据库更新的时候,必定会失落属性,因为对象的封装是 springmvc 主动帮咱们 new 的,所以此时须要先将从数据库获取的对象保留下来,当提交的时候不是 new 新的对象,而是在原来的对象上进行属性笼罩,此时就须要应用 @ModelAttribute 注解。

User.java

package com.mashibing.bean;

public class User {
    private Integer id;
    private String name;
    private String password;
    private Integer age;

    public Integer getId() {return id;}

    public void setId(Integer id) {this.id = id;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public String getPassword() {return password;}

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

    public Integer getAge() {return age;}

    public void setAge(Integer age) {this.age = age;}

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

UserController.java

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

    Object o1 = null;
    Object o2 = null;
    Object o3 = null;

    @RequestMapping("update")
    public String update(@ModelAttribute("user") User user,Model model){System.out.println(user);
        o2 = model;
        // 能够看到所有的 model 都是同一个对象
        System.out.println(o1==o2);
        // 能够看到存储的 user 对象也是同一个
        System.out.println(user == o3);
        return "output";
    }

    @ModelAttribute
    public void MyModelAttribute(Model model){
        o1 = model;
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setAge(12);
        user.setPassword("123");
        model.addAttribute("user",user);
        System.out.println("modelAttribute:"+user);
        o3 = user;
    }
}

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: root
  Date: 2020/3/11
  Time: 13:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="update" method="post">
    <input type="hidden" value="1" name="id">
    姓名:张三 <br>
    明码:<input type="text" name="password"><br>
    年龄:<input type="text" name="age"><br>
    <input type="submit" value="提交">
  </form>
  </body>
</html>

其实在应用的时候能够简化写法,也就是说,在办法的参数上不加 @ModelAttribute 也不会有问题

    @RequestMapping("update")
    public String update(User user,Model model){System.out.println(user);
        o2 = model;
        // 能够看到所有的 model 都是同一个对象
        System.out.println(o1==o2);
        // 能够看到存储的 user 对象也是同一个
        System.out.println(user == o3);
        return "output";
    }

如果增加的 @ModelAttribute(“”)属性的值不对,那么也是获取不到值的。同时能够增加 @SessionAttributes 属性,然而留神,如果没有设置值的话,会报错

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;

@Controller
@SessionAttributes("u")
public class UserController {

    Object o1 = null;
    Object o2 = null;
    Object o3 = null;

    @RequestMapping("update")
    public String update(@ModelAttribute("u") User user,Model model){System.out.println(user);
        o2 = model;
        // 能够看到所有的 model 都是同一个对象
        System.out.println(o1==o2);
        // 能够看到存储的 user 对象也是同一个
        System.out.println(user == o3);
        return "output";
    }

    @ModelAttribute
    public void MyModelAttribute(Model model){
        o1 = model;
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setAge(12);
        user.setPassword("123");
        model.addAttribute("user",user);
        System.out.println("modelAttribute:"+user);
        o3 = user;
    }
}

留神:ModelAttribute 除了能够应用设置值到 model 中之外,还能够利用返回值。

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;

@Controller
public class UserController {

    Object o1 = null;
    Object o2 = null;
    Object o3 = null;

    @RequestMapping("update")
    public String update(@ModelAttribute("u") User user,Model model){System.out.println(user);
        o2 = model;
        // 能够看到所有的 model 都是同一个对象
        System.out.println(o1==o2);
        // 能够看到存储的 user 对象也是同一个
        System.out.println(user == o3);
        return "output";
    }

    @ModelAttribute("u")
    public User MyModelAttribute(Model model){
        o1 = model;
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setAge(12);
        user.setPassword("123");
//        model.addAttribute("user",user);
        System.out.println("modelAttribute:"+user);
        o3 = user;
        return user;
    }
}

总结:通过刚刚的给参数赋值,大家应该可能发现,当给办法中的参数设置值的时候,如果增加了 @ModelAttribute 注解,那么在查找值的时候,是遵循以下形式:

1、办法的参数应用参数的类型首字母小写,或者应用 @ModelAttribute(“”)的值

2、先看之前是否在 model 中设置过该属性值,如果设置过就间接获取

3、看 @SessionAttributes 注解标注类中的办法是否给 session 中赋值,如果有的话,也是间接获取,没有报异样

8、应用 forward 实现页面转发

​ 在发送申请的时候,能够通过 forward: 来实现转发的性能:

package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ForWardController {

    /**
     * 当应用转发的时候能够增加前缀 forward:index.jsp, 此时是不会通过视图解析器的,所以要增加残缺的名称
     *
     * forward: 也能够由一个申请跳转到另外一个申请
     *
     * @return
     */
    @RequestMapping("/forward01")
    public String forward(){System.out.println("1");
        return "forward:/index.jsp";
    }


    @RequestMapping("/forward02")
    public String forward2(){System.out.println("2");
        return "forward:/forward01";
    }
}
9、应用 redirect 来实现重定向
package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class RedirectController {


    /**
     * redirect : 重定向的门路
     *      相当于 response.sendRedirect("index.jsp")
     *      跟视图解析器无关
     * @return
     */
    @RequestMapping("redirect")
    public String redirect(){System.out.println("redirect");
        return "redirect:/index.jsp";
    }

    @RequestMapping("/redirect2")
    public String redirect2(){System.out.println("redirect2");
        return "redirect:/redirect";
    }
}

在 javaweb 的时候大家应该都接触过重定向和转发的区别,上面再具体说一下:

转发:

​ 由服务器的页面进行跳转,不须要客户端从新发送申请:

​ 特点如下:

​ 1、地址栏的申请不会发生变化,显示的还是第一次申请的地址

​ 2、申请的次数,有且仅有一次申请

​ 3、申请域中的数据不会失落

​ 4、根目录:localhost:8080/ 我的项目地址 /, 蕴含了我的项目的拜访地址

重定向:

​ 在浏览器端进行页面的跳转,须要发送两次申请(第一次是人为的,第二次是主动的)

​ 特点如下:

​ 1、地址栏的地址发生变化,显示最新发送申请的地址

​ 2、申请次数:2 次

​ 3、申请域中的数据会失落,因为是不同的申请

​ 4、根目录:localhost:8080/ 不蕴含我的项目的名称

比照:

区别 转发 forward() 重定向 sendRedirect()
根目录 蕴含我的项目拜访地址 没有我的项目拜访地址
地址栏 不会发生变化 会发生变化
哪里跳转 服务器端进行的跳转 浏览器端进行的跳转
申请域中数据 不会失落 会失落
10、动态资源的拜访

​ 当页面中蕴含动态资源的时候咱们可能正确的获取到吗?

hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    pageContext.setAttribute("ctx",request.getContextPath());
%>
<html>
<head>
    <title>Title</title>
</head>
<body>
hello springmvc
<img src="${ctx}/images/timg.jpg">
</body>
</html>

​ 此时大家发现咱们申请的图片基本拜访不到,依据查看发现门路是没有问题的,那么为什么会找不到动态资源呢?

大家发现此时是找不到对应的 mapping 映射的,此时是因为 DispatcherServlet 会拦挡所有的申请,而此时咱们没有对应图片的申请解决办法,所以此时报错了,想要解决的话非常简单,只须要增加一个配置即可

<!--
此配置示意  咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
动态资源能够拜访,然而动静申请无法访问
-->
<mvc:default-servlet-handler/>

​ 然而加上此配置之后,大家又发现此时除了动态资源无法访问之外,咱们失常的申请也无奈获取了,因而还须要再增加另外的配置:

<!-- 保障动态资源和动静申请都可能拜访 -->
<mvc:annotation-driven/>

(2)自定义视图解析器

​ 咱们在之前的操作中曾经用了 SpringMVC 中提供的视图解析器,那么如果咱们须要实现本人的视图解析器该如何操作呢?


MyViewController.java

package com.mashibing.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyViewController {@RequestMapping("/myview")
    public String myView(Model model){model.addAttribute("msb","马士兵");
        return "msb:/index";
    }
}

MyViewResolver.java

package com.mashibing.view;

import org.springframework.core.Ordered;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;

import java.util.Locale;

public class MyViewResolver implements ViewResolver, Ordered {
    private int order = 0;
    public View resolveViewName(String viewName, Locale locale) throws Exception {

        // 如果前缀是 msb: 结尾的就进行解析
        if (viewName.startsWith("msb:")){System.out.println("msb:");
            return new MyView();}else{
            // 如果不是,则间接返回 null
            return null;
        }
    }

    public int getOrder() {return this.order;}

    public void setOrder(Integer order) {this.order = order;}
}

MyView.java

package com.mashibing.view;

import org.springframework.core.Ordered;
import org.springframework.web.servlet.View;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class MyView implements View {public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {System.out.println("保留的对象是:"+model);
        response.setContentType("text/html");
        response.getWriter().write("欢送退出马士兵教育");
    }

    /**
     * 返回数据内容的类型
     * @return
     */
    public String getContentType() {return "text/html";}
}

springmvc.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 https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.mashibing"></context:component-scan>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <bean class="com.mashibing.view.MyViewResolver">
        <property name="order" value="1"></property>
    </bean>
</beans>

(3)自定义类型转换器

​ 在日常的企业开发需要中,咱们输出文本框的内容全部都是字符串类型,然而在后端解决的时候咱们能够用其余根本类型来承受数据,也能够应用实体类来承受参数,这个是怎么实现的呢?就是通过 SpringMVC 提供的类型转换器,SpringMVC 外部提供了十分丰盛的类型转换器的反对,然而有些状况下有可能难以满足咱们的需要,因而须要咱们本人实现,如下:

User.java

package com.mashibing.bean;

public class User {

    private Integer id;
    private String name;
    private Integer age;
    private String gender;

    public User() {}

    public Integer getId() {return id;}

    public void setId(Integer id) {this.id = id;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public Integer getAge() {return age;}

    public void setAge(Integer age) {this.age = age;}

    public String getGender() {return gender;}

    public void setGender(String gender) {this.gender = gender;}

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

MyConverter.java

package com.mashibing.converter;

import com.mashibing.bean.User;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class MyConverter implements Converter<String, User> {public User convert(String source) {
        User user = null;
        String[] split = source.split("-");
        if (source!=null && split.length==4){user = new User();
            user.setId(Integer.parseInt(split[0]));
            user.setName(split[1]);
            user.setAge(Integer.parseInt(split[2]));
            user.setGender(split[3]);
        }
        return user;
    }
}

UserController.java

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {@RequestMapping("/user")
    public String add(User user, Model model){System.out.println(user);
        model.addAttribute("user","user");
        return "success";
    }
}

success.jsp

<%--
  Created by IntelliJ IDEA.
  User: root
  Date: 2020/3/12
  Time: 21:36
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
${requestScope.user}
</body>
</html>

springmvc.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.mashibing"></context:component-scan>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <bean class="com.mashibing.view.MyViewResolver">
        <property name="order" value="1"></property>
    </bean>
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myConverter"></ref>
            </set>
        </property>
    </bean>
</beans>

(4)自定义日期格式化转换器

​ 有时候咱们常常须要在页面增加日期等相干信息,此时须要制订日期格式化转换器,此操作非常简单:只须要在独自的属性上增加 @DateTimeFormat 注解即可,制订对应的格局

User.java

package com.mashibing.bean;

import org.springframework.format.annotation.DateTimeFormat;

import java.util.Date;

public class User {

    private Integer id;
    private String name;
    private Integer age;
    private String gender;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birth;

    public User() {}

    public Integer getId() {return id;}

    public void setId(Integer id) {this.id = id;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public Integer getAge() {return age;}

    public void setAge(Integer age) {this.age = age;}

    public String getGender() {return gender;}

    public void setGender(String gender) {this.gender = gender;}

    public Date getBirth() {return birth;}

    public void setBirth(Date birth) {this.birth = birth;}

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", birth=" + birth +
                '}';
    }
}

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<form action="dateConvertion" method="post">
  编号:<input type="text" name="id"><br>
  姓名:<input type="text" name="name"><br>
  年龄:<input type="text" name="age"><br>
  性别:<input type="text" name="gender"><br>
  日期:<input type="text" name="birth"><br>
  <input type="submit" value="提交">
</form>
  </body>
</html>

DateConvertionController.java

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class DateConvertionController {@RequestMapping("dateConvertion")
    public String dateConvertion(User user){System.out.println(user);
        return "hello";
    }
}

springmvc.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.mashibing"></context:component-scan>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <bean class="com.mashibing.view.MyViewResolver">
        <property name="order" value="1"></property>
    </bean>
    <!-- 此配置示意  咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
    动态资源能够拜访,然而动静申请无法访问
    -->
    <mvc:default-servlet-handler/>
    <!-- 保障动态资源和动静申请都可能拜访 -->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

​ 此时运行发现是没有问题的,然而须要留神的是,如果同时配置了自定义类型转换器之后,那么日期格局转化是有问题的。

springmvc.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.mashibing"></context:component-scan>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <bean class="com.mashibing.view.MyViewResolver">
        <property name="order" value="1"></property>
    </bean>
    <!-- 此配置示意  咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
    动态资源能够拜访,然而动静申请无法访问
    -->
    <mvc:default-servlet-handler/>
    <!-- 保障动态资源和动静申请都可能拜访 -->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myConverter"></ref>
            </set>
        </property>
    </bean>
</beans>

​ 起因就在于 ConversionServiceFactoryBean 对象中有且仅有一个属性 converters,此时能够应用另外一个类来做替换 FormattingConversionServiceFactoryBean

springmvc.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.mashibing"></context:component-scan>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/page/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
    <bean class="com.mashibing.view.MyViewResolver">
        <property name="order" value="1"></property>
    </bean>
    <!-- 此配置示意  咱们本人配置的申请由 controller 来解决,然而不能申请的解决交由 tomcat 来解决
    动态资源能够拜访,然而动静申请无法访问
    -->
    <mvc:default-servlet-handler/>
    <!-- 保障动态资源和动静申请都可能拜访 -->
<!--    <mvc:annotation-driven></mvc:annotation-driven>-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="myConverter"></ref>
            </set>
        </property>
    </bean>
</beans>

(5)数据校验

​ 个别状况下咱们会在前端页面实现数据的校验,然而大家须要留神的是前端校验会存在数据的不平安问题,因而个别状况下咱们都会应用前端校验 + 后端校验的形式,这样的话既可能满足用户的体验度,同时也能保证数据的平安,上面来说一下在 springmvc 中如何进行后端数据校验。

​ JSR303 是 Java 为 Bean 数据合法性校验提供的规范框架,它曾经蕴含在 JavaEE 6.0 中。JSR 303 (Java Specification Requests 意思是 Java 标准提案)通过 Bean 属性上标注 相似于 @NotNull、@Max 等规范的注解指定校验规定,并通过规范的验证接口对 Bean 进行验证。

JSR303:

Hibernate Validator 扩大注解:

spring 中领有本人的数据校验框架,同时反对 JSR303 规范的校验框架,能够在通过增加注解的形式进行数据校验。在 spring 中自身没有提供 JSR303 的实现,须要导入依赖的包。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mashibing</groupId>
    <artifactId>springmvc_viewResolver</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.1.0.Final</version>
        </dependency>

    </dependencies>
</project>

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: root
  Date: 2020/3/12
  Time: 15:23
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<form action="dataValidate" method="post">
  编号:<input type="text" name="id"><br>
  姓名:<input type="text" name="name"><br>
  年龄:<input type="text" name="age"><br>
  性别:<input type="text" name="gender"><br>
  日期:<input type="text" name="birth"><br>
  邮箱:<input type="text" name="email"><br>
  <input type="submit" value="提交">
</form>
  </body>
</html>

DataValidateController.java

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;


@Controller
public class DataValidateController {@RequestMapping("/dataValidate")
    public String validate(@Valid User user, BindingResult bindingResult) {System.out.println(user);
        if (bindingResult.hasErrors()) {System.out.println("验证失败");
            return "redirect:/index.jsp";
        } else {System.out.println("验证胜利");
            return "hello";
        }
    }
}

User.java

package com.mashibing.bean;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;

public class User {

    private Integer id;
    @NotNull
    @Length(min = 5,max = 10)
    private String name;
    private Integer age;
    private String gender;
    @Past
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date birth;
    @Email
    private String email;

    public User() {}

    public Integer getId() {return id;}

    public void setId(Integer id) {this.id = id;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public Integer getAge() {return age;}

    public void setAge(Integer age) {this.age = age;}

    public String getGender() {return gender;}

    public void setGender(String gender) {this.gender = gender;}

    public Date getBirth() {return birth;}

    public void setBirth(Date birth) {this.birth = birth;}

    public String getEmail() {return email;}

    public void setEmail(String email) {this.email = email;}

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", birth=" + birth +
                ", email='" + email + '\'' +
                '}';
    }
}

此时大家发现在报错的中央无奈呈现谬误提醒,能够换另外一种形式:

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
<a href="add"> 增加用户 </a>

  </body>
</html>

add.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
<form:form action="dataValidate"  modelAttribute="user" method="post">
    id:<form:input path="id"></form:input><form:errors path="id"></form:errors> <br/>
    name:<form:input path="name"></form:input><form:errors path="name"></form:errors><br/>
    age:<form:input path="age"></form:input><form:errors path="age"></form:errors><br/>
    gender:<form:input path="gender"></form:input><form:errors path="gender"></form:errors><br/>
    birth:<form:input path="birth"></form:input><form:errors path="birth"></form:errors><br/>
    email:<form:input path="email"></form:input><form:errors path="email"></form:errors><br/>
    <input type="submit" value="submit">
</form:form>
</body>
</html>

DataValidateController.java

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;


@Controller
public class DataValidateController {@RequestMapping("/dataValidate")
    public String validate(@Valid User user, BindingResult bindingResult, Model model) {System.out.println(user);
        if (bindingResult.hasErrors()) {System.out.println("验证失败");
            return "add";
        } else {System.out.println("验证胜利");
            return "hello";
        }
    }

    @RequestMapping("add")
    public String add(Model model){model.addAttribute("user",new User(1,"zhangsan",12,"女",null,"1234@qq.com"));
        return "add";
    }
}

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">
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </context-param>
    <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>
        
    </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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

原生的表单如何获取错误信息:

DataValidateController.java

package com.mashibing.controller;

import com.mashibing.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Controller
public class DataValidateController {@RequestMapping("/dataValidate")
    public String validate(@Valid User user, BindingResult bindingResult, Model model) {System.out.println(user);
        Map<String,Object> errorsMap = new HashMap<String, Object>();
        if (bindingResult.hasErrors()) {System.out.println("验证失败");
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for (FieldError fieldError : fieldErrors) {System.out.println(fieldError.getDefaultMessage());
                System.out.println(fieldError.getField());
                errorsMap.put(fieldError.getField(),fieldError.getDefaultMessage());
            }
            model.addAttribute("errorInfo",errorsMap);
            return "add";
        } else {System.out.println("验证胜利");
            return "hello";
        }
    }

    @RequestMapping("add")
    public String add(Model model){model.addAttribute("user",new User(1,"zhangsan",12,"女",null,"1234@qq.com"));
        return "add";
    }
}

add.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
<form:form action="dataValidate"  modelAttribute="user" method="post">
    编号:<form:input path="id"></form:input><form:errors path="id"></form:errors>--->${errorInfo.id} <br/>
    姓名:<form:input path="name"></form:input><form:errors path="name"></form:errors>--->${errorInfo.name}<br/>
    年龄:<form:input path="age"></form:input><form:errors path="age"></form:errors>--->${errorInfo.age}<br/>
    性别:<form:input path="gender"></form:input><form:errors path="gender"></form:errors>--->${errorInfo.gender}<br/>
    生日:<form:input path="birth"></form:input><form:errors path="birth"></form:errors>--->${errorInfobirth}<br/>
    邮箱:<form:input path="email"></form:input><form:errors path="email"></form:errors>--->${errorInfo.email}<br/>
    <input type="submit" value="submit">
</form:form>
</body>
</html>
退出移动版