springMVC的使用

文章目录

一、SpringMVC的简单介绍

(1)定义:SpringMVC是目前主流的实现MVC设计模式的企业级开发框架,是Spring框架的一个子模块,无需整合,开发起来更加便捷。
(2)什么是MVC设计模式:将应用程序分为Controller、Model、View三层,controller接收客户端请求,调用Model生成业务数据,然后传递给View展示层。
(3)SpringMVC是对这套流程的封装,屏蔽了很多底层的代码,开放出接口,让开发者可以更加轻松地、便捷地完成基于MVC模式的web开发。

二、SpringMVC的核心组件

  • DispatcherServlet:前置控制器,是整个流程控制的核心,控制其他组件的执行,进行统一调度,降低组件之间的耦合性,相当于总指挥。
  • Handler:处理器,完成具体的业务逻辑,相当于Servlet或Action。
  • HandlerMapping:DispatcherServlet接收到请求之后,通过HandlerMapping将不同的请求映射到不同的Handler中。
  • HandlerInterceptor:处理器拦截器,是一个接口,如果需要完成一些拦截处理,可以实现该接口。
  • HandlerExecutionChain:处理器执行链,包括两部分内容Handler和HandlerInterceptor(系统会有一个默认的HandlerInterceptor,如果需要额外添加设置拦截的话,可以添加拦截器)。
  • HandlerAdpater:处理器适配器,Handler处理业务方法之前,需要进行一系列的操作,包括表单数据的校验、数据类型的转换、将把单数据封装到JavaBean等,这些操作都是由HandlerAdpater来完成的,因此开发者只需要将注意力集中在业务逻辑的处理上,DispatcherServlet通过HandlerAdapter执行不同的Handler.
  • ModelAndView:装载了模型数据和视图信息,作为Handler的处理结果,返回给DispatcherServlet.
  • ViewResolver:视图解析器,DispatcherServlet通过它将逻辑视图(不真实存在的,如ModelAndView)解析为物理视图(真实存在的,如jsp、HTML等),最终将渲染结果响应给客户端。

三、SpringMVC的工作流程

(1)总体流程图
在这里插入图片描述
(2)执行过程具体描述

  • 客户端请求被DispatcherServlet接受
  • 根据HandlerMapping映射到Handler
  • 生成Handler和HandlerInterceptor
  • Handler和HandlerInterceptor以HandlerExecutionChain形式一并返回给DispatcherServlet
  • DispatcherServlet通过HandlerAdapter调用Handler的方法完成业务逻辑的处理
  • Handler返回一个ModelAndView给DispatcherServlet
  • DispatcherServlet将获取得到的ModelAndView对象传给ViewResolver的视图解析器,讲逻辑视图解析为物理视图View
  • ViewResolver返回一个View给DispatcherServlet
  • DispatcherServlet根据View进行视图渲染(将模型数据Model填充到视图View中)
  • DispatcherServlet将渲染后的视图结果响应给客户端

四、SpringMVC的特点

  • 清晰的角色划分(每个组件的职责划分得很清晰,多个组件协同完成共同的任务)
  • 灵活的配置功能(是一个解耦合的过程,将各组件之间松散的结合在一起)
  • 提供了大量的控制器接口和实现类
  • 分离View层的实现(把Model和View进行分离,最终再将Model和View整合在一起)
  • 国际化支持(内容完全一样,这是不同国家的语言不同去显示而已)
  • 面向接口编程
小结

SpringMVC的执行流程非常复杂,实际开发中非常简单,因为大部分组件不需要开发者自己创建、管理,只需要配置文件的方式完成配置即可。真正需要开发者进行处理和书写的代码是Handler和View。

五、如何使用?

创建Maven工程,添加pom.xml依赖
<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.5</version>
    </dependency>
  </dependencies>
在web.xml文件中配置DispatcherServlet
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
    <servlet-name>dispatcherServlet</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>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>
配置springmvc.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       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">
    <!--自动扫描包,base-package="com.entor"表示改包下的所有类以及子包下的所有类扫描-->
    <context:component-scan base-package="com.wuzhou"/>
    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--整个相当于,比如是index.jsp文件,访问路径就是"/index.jsp"-->
        <!--视图解释器解释jsp文件的前缀,在webapp根目录下的文件-->
        <property name="prefix" value="/"/>
        <!--视图文件的后缀为jsp文件视图-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>
创建一个简单的Handler
package com.wuzhou.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Handler {
    @RequestMapping("/index")
    public String index(){
        System.out.println("执行了index方法");
        return "index";
    }
}

六、SpringMVC的注解解析

@RequestMapping

SpringMVC是通过@RequestMapping注解将URL请求与业务方法进行映射,在Handler类的定义处以及方法定义处都可以添加该注解@RequestMapping,在类定义处添加,相当于客户端多了一层访问路径

@Controller

@Controller注解是在类定义添加,将该类交给Ioc容器去管理(所谓的Ioc容器去管理,是因为在springmvc.xml文件中通过自动扫描包进行识别),同时使其成为一个控制器,可以接收客户端的请求

示例代码

package com.wuzhou.controller;

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

@Controller
@RequestMapping("/hello")
public class Handler {
    @RequestMapping("/index")
    public String index(){
        System.out.println("执行了index方法");
        return "index";
    }
}

@RequestMapping注解中的相关参数

(1)value属性:指的是URL的实际请求地址,默认的情况下是可以省略不写的,即是@RequestMapping的默认值是省略

 @RequestMapping("/index")
    public String index(){
        System.out.println("执行了index方法");
        return "index";
    }

等价于

 @RequestMapping(value = "/index")
    public String index(){
        System.out.println("执行了index方法");
        return "index";
    }

(2)method属性:指定请求method的类型,常见的几种类型有GET、POST、PUT、DELETE等

 @RequestMapping(value = "/index",method = RequestMethod.GET)
    public String index(){
        System.out.println("执行了index方法");
        return "index";
    }

上述代码index方法只能接收GET方式的请求

(3)params:指定请求中必须包含某些参数,否则无法调用该方法

@RequestMapping(value = "/index",method = RequestMethod.GET,params = {"name","id=10"})//其中id指定值为10,在url地址栏中id的属性值就应该是10,对于name的值可以是任意的
    public String index(){
        System.out.println("执行了index方法");
        return "index";
    }

上述代码请求中必须包含name和id的两个参数。与此同时,id的值必须是10,才能正确访问控制层的方法

关于参数的绑定,在形参列表中通过添加@RequestParam注解完成Http请求参数与业务方法中的参数进行映射
 @RequestMapping(value = "/index",method = RequestMethod.GET,params = {"name","id=10"})
 //其中params中的参数名称是要与url请求地址的参数名称对应相同
    public String index(@RequestParam("name") String nme,@RequestParam("id") Integer idNo){//@RequestParams()注解使用是在params注解属性中的参数名称不一样地时候需要添加进行赋给一个业务方法中的新参数名称,一般在业务逻辑方法中的参数名称是与params注解中的参数名称一样
        System.out.println("name = " + nme);
        System.out.println("id = " + idNo);
        System.out.println("执行了index方法");
        return "index";
    }

上述代码表示将请求的参数name和id分别赋给了形参nme和idNo,同时完成了自动类型转换,(注意的是从http地址栏中以get方式进行参数赋值都是String字符串类型的),所以在上述中的id值为10实际上是String类型的,实际上是把String类型的数值已经转换成Integer类型的数值了,在业务方法中的参数却是Integer类型的名称进行接收即可。因此这些工作都是由HandlerAdapter(处理器适配器)已经进行内部处理的结果。

SpringMVC也支持restful风格的URL

传统类型:http://localhost:8084/springmvc_0609/hello/index?name=1&id=10
REST形式(直接在url中写参数值,多个参数值之间用 / 隔开,并且要在注解@RequestMapping(value = “/rest/{name}/{id}”)中以添加参数名称,以{}中书写,多个参数名称用 / 隔开:http://localhost:8084/springmvc_0609/hello/rest/zhangsan/10

@RequestMapping(value = "/rest/{name}/{id}",method = RequestMethod.GET)
    public String rest(@PathVariable(value = "name") String name,@PathVariable(value = "id") int id){
        System.out.println("name1 = " + name);
        System.out.println("id1 = " + id);
        return "index";
    }

上述代码中,当业务方法中的形参名称进行对URL下的参数值接收,那么就必须添加@PathVariable注解来指定映射到业务方法中的参数名称(这个最主要的是这个注解的value属性值要与@RequestMapping注解中的value中的指定对应的参数名称对应,其实@PathVariable中的value属性值可不与业务方法中的参数名称相同),则是@PathVariable注解完成请求参数与业务方法中的形参进行映射。

映射Cookie

SpringMVC通过映射可以直接在业务方法中获取到Cookie的值。

  @RequestMapping(value = "/cookie")
    public String cookie(@CookieValue(value = "JSESSIONID") String jsession){
        System.out.println("jsession = " + jsession);
        return "index";
    }
使用javabean绑定参数

SpringMVC会根据请求参数名和JavaBean属性名进行自动匹配,自动为对象属性填充值,同时支持级联属性(也就是实体对象中包含另外一个实体对象)

实体类代码

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Address address;
}


package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
    private String addressName;
}

前端jsp注册表单页面

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/13
  Time: 22:58
  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="/hello/save" method="post">
    用户ID:<input type="text" name="id"><br>
    用户名:<input type="text" name="name"><br>
    地址名:<input type="text" name="address.addressName"><br>
    <input type="submit" value="注册">

</form>

</body>
</html>

控制器Handler代码

package com.wuzhou.controller;

import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@Controller
@RequestMapping(value = "/hello")
public class Handler {
    @RequestMapping(value = "/save",method = RequestMethod.POST)
    public String save(User user){
        System.out.println("user = " + user);
        return "index";
    }
}
如果出现中文乱码问题,只需要在web.xml文件中添加SpringMVC自带的过滤器即可
<!--添加一个处理乱码的过滤器,统一编码UTF-8,位置要放在第一位置,不然报错-->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

jsp的页面转发和重定向

SpringMVC是以默认是页面转发分形式响应jsp

(1)页面转发控制器

 @RequestMapping(value = "/forward")
    public String forward(){
        System.out.println("forward页面转发");
        return "forward:/index.jsp";
    }

(2)页面重定向控制器

 @RequestMapping(value = "/redirect")
    public String redirect(){
        System.out.println("redirect页面重定向");
        return "redirect:/index.jsp";
    }
SpringMVC 的数据绑定

数据绑定:在后端的业务方法中直接获取前端HTTP请求中的参数,将请求中的参数映射中业务方法中的形参中。
SpringMVC 中数据绑定的工作交给HandlerAdapter来完成的。

  • 基本数据类型的绑定
 @RequestMapping(value = "/basicType",produces = "application/json;charset=utf-8")//其中的produce属性值是返回含有中文的字符不会在浏览器上出现乱码或者解析不出来
    @ResponseBody
    public String basicType(int id){
        return "id的值为:"+id;
    }

上述代码中的@ResponseBody注解是表示SpringMVC会直接将业务方法中的返回值响应给客户端,如果不加这个@ResponseBody注解的话,SpringMVC会将业务方法的返回值传递给DispatcherServlet去处理,然后再由DispatcherServlet去调用ViewResolver对返回值进行解析,映射到一个jsp资源。

  • 包装类型的绑定
 @RequestMapping(value = "/packageType",produces = "application/json;charset=utf-8")
    @ResponseBody
    public String packageType(Integer id){
        return "id的值为:"+id;
    }

    @RequestMapping(value = "/packageType",produces = "application/json;charset=utf-8")
    @ResponseBody
    public String packageType(@RequestParam(value = "num",required = false,defaultValue = "0") Integer id){
        return "id的值为:"+id;
    }

包装类可以接收null值,当http请求参数中为null值时,使用包装类定义形参的数据类型,程序不会抛出异常;如果是基本数据类型的话,http请求参数中中的值为空的话,就会抛出空指针异常。

@RequestParam注解:

  • value=“num”:将http中的请求参数赋值给业务方法中的形参id
  • required:设置num是否为必填项,属性值true表示必填,false表示非必填,这个属性可以省略,默认是必填
  • defaultValue = “0”:如果http中的请求没有num参数,默认值是0

数组类型参数输入

@RestController
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
      @RequestMapping(value = "/array",produces = "application/json;charset=utf-8")
    //@ResponseBody
    public String array(String [] name){
        String s = Arrays.toString(name);
        System.out.println("s = " + s);
        return s;
    }
}

等同于

@Controller
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
    @RequestMapping(value = "/array",produces = "application/json;charset=utf-8")
    @ResponseBody
    public String array(String [] name){
        String s = Arrays.toString(name);
        System.out.println("s = " + s);
        return s;
    }
}

上述代码中的@RestController注解,表示直接将业务方法中的返回值响应给客户端,不进行视图解析;然而@Contoller表示该控制器的每一个业务方法的返回值都会交给视图解析器进行解析,如果只是想把业务方法中的返回值响应给客户端,则不需要进行视图解析,只需要在对应的方法上添加@ResponseBody即可。

  • User对象的封装类返回给浏览器客户端

业务类

@RestController
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
   @RequestMapping(value = "/save",produces ="application/json;charset=utf-8" )
    public String save(User user){
        //第一种方式
//        StringBuffer str=new StringBuffer();
//        StringBuffer append = str.append(user);
//        System.out.println(append);
//        return str.toString();
        //第二种方式
        String str="";
        str+=user;
        System.out.println("user = " + str);
        return str;
    }
}

实体封装类

package com.wuzhou.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private Address address;
}

package com.wuzhou.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
    private String addressName;
}

jsp前端

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/13
  Time: 22:58
  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="/hello/save" method="post">
    用户ID:<input type="text" name="id"><br>
    用户名:<input type="text" name="name"><br>
    地址名:<input type="text" name="address.addressName"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>
  • List集合对象实体类
    springMVC不支持List类型的直接转换,需要对List集合进行封装

业务类

@RestController
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
//    @RequestMapping(value = "/list",produces ="application/json;charset=utf-8")
    @RequestMapping(value = "/list")
    public String list(UserList users){
        StringBuffer s=new StringBuffer();
        for (User user:users.getUsers()) {
            s.append(user);
        }
        return s.toString();
    }
}

集合封装类

package com.wuzhou.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserList {
    private List<User> users;
}

jsp前端

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/13
  Time: 22:58
  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="/data/list" method="post">
    用户1ID:<input type="text" name="users[0].id"><br>
    用户1名:<input type="text" name="users[0].name"><br>
<%--    地址名:<input type="text" name="address.addressName"><br>--%>
    用户2ID:<input type="text" name="users[1].id"><br>
    用户2名:<input type="text" name="users[1].name"><br>
    用户3ID:<input type="text" name="users[2].id"><br>
    用户3名:<input type="text" name="users[2].name"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>

处理@ResponseBody注解的中文乱码问题
(1)在springmvc.xml文件中配置消息转换器进行处理

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:component-scan base-package="com.wuzhou"/>
    <!--消息转换器,就是返回带有中文字符给客户端浏览器的格式消息设置-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=utf-8"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
</beans>

(2)就是在@ResquestMapping注解中的produces注解属性中添加格式为produces ="application/json;charset=utf-8"就能处理返回给客户端含有中文字符的乱码问题

  • Map集合

自定义封装类

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserMap {
    private Map<String,User> userMaps;
}

业务方法

@RestController
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
     @RequestMapping(value = "/getMap",produces ="application/json;charset=utf-8")
    public String map(UserMap map) {
        StringBuffer s=new StringBuffer();
        for (String key:map.getUserMaps().keySet()) {
            User user = map.getUserMaps().get(key);
            s.append(user);
        }
        return s.toString();
    }
}

相当于

@RestController
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
    @RequestMapping(value = "/map",produces ="application/json;charset=utf-8")
    public Map<String,User> getMap(UserMap map) {
        Map<String,User> map1=new HashMap<>();
        Map<String, User> userMaps = map.getUserMaps();
        userMaps.entrySet().stream().forEach(stringUserEntry -> {
            System.out.println("stringUserEntry = " + stringUserEntry);
            map1.put(stringUserEntry.getKey(),stringUserEntry.getValue());
        });
        return map1;
    }
 }

相当于

@RestController
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
     @RequestMapping(value = "/map",produces ="application/json;charset=utf-8")
    public List<User> getMap(UserMap map) {
        List<User> userList=new ArrayList<>();
        Map<String, User> userMaps = map.getUserMaps();
            userMaps.entrySet().stream().forEach(stringUserEntry -> {
                System.out.println("stringUserEntry = " + stringUserEntry);
                userList.add(stringUserEntry.getValue());
        });
        return userList;
    }
}

jsp前端

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/13
  Time: 22:58
  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="/data/map" method="post">
    用户1ID:<input type="text" name="userMaps['a'].id"><br>
    用户1名:<input type="text" name="userMaps['a'].name"><br>
<%--    地址名:<input type="text" name="address.addressName"><br>--%>
    用户2ID:<input type="text" name="userMaps['b'].id"><br>
    用户2名:<input type="text" name="userMaps['b'].name"><br>
    用户3ID:<input type="text" name="userMaps['c'].id"><br>
    用户3名:<input type="text" name="userMaps['c'].name"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>
  • json
    客户端发生Json格式的数据时,直接绑定到springMVC中的业务方法的形参之中。

(一)处理SpringMVC中无法加载静态资源两种形式
在web.xml文件中添加配置即可
(1)

<!--配置默认的servlet请求处理策略,对静态资源不拦截,例如:html,css,js,image等-->
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
  </servlet-mapping>

在springmvc.xml文件中添加配置即可
(2)

<!--配置默认的servlet请求处理策略,对静态资源不拦截,例如:html,css,js,image等-->
    <mvc:default-servlet-handler/>

(二)jsp异步请求代码

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/17
  Time: 11:47
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.6.0.js"></script>
    <script type="text/javascript">
        $(function () {
            var user={
                "id":1,
                "name":"张三",
                "address":{
                    "addressName":"人民路"
                }
            };
            $.ajax({
                url:"/data/json",
                /*发送请求的地址*/
                data:JSON.stringify(user),
                /*要求为Object或String类型的参数,发送到服务器的数据。
                对象必须为key/value格式,例如{foo1:"bar1",foo2:"bar2"}
                转换为&foo1=bar1&foo2=bar2。*/
                type:"POST",
                /*要求为String类型的参数,请求方式(post或get)默认为get。*/
                contentType:"application/json;charset=utf-8",
                /*发送信息至服务器的内容格式编码,可能有中文参数*/
                dataType:"JSON",
                /*要求为String类型的参数,预期服务器返回的数据类型----返回json格式数据*/
                success:function (data) {
                    /*要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。*/
                    alert(data.id+"===="+data.name+"======"+data.address.addressName);
                }

            });
        });
    </script>
</head>
<body>

</body>
</html>

业务方法

@RestController
//相当于@Controller和@ResponseBody结合
@RequestMapping(value = "/data")
public class DataHandler {
     @RequestMapping(value = "/json",produces ="application/json;charset=utf-8")
    public User json(@RequestBody User user){
        System.out.println("user = " + user);
        user.setId(6);
        user.setName("王五");
        return user;
    }
}

springmvc中的JSON和javabean的转换需要借助于fastjson,pom.xml文件中需要添加相关依赖

<!--这个以来的作用是将前端传来的json字符串转成java对象-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.72</version>
    </dependency>

还需要在spring.xml文件中添加和配置fastjson的配置

 <!--消息转换器,就是返回带有中文字符给客户端浏览器的格式消息设置-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=utf-8"/>
            </bean>
            <!--配置fastjson-->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>

        </mvc:message-converters>
    </mvc:annotation-driven>
SpringMVC 模型数据的解析

(1)jsp四大作用域对应的内置对象:pageContext、request、session、application。
(2)模型数据的绑定是由ViewResolver来完成的,但在实际开发中,我们需要先添加模型数据,再交给ViewResolver来绑定。
(3)springMVC提供了以下几种方式添加模型数据
(Map、Model、ModeAndView属于request对象)、@SessionAttribute属于session对象、@ModelAttribute属于request对象

将模型数据绑定到request对象中
  • Map
    (1)Map的Handler
package com.wuzhou.controller;
import com.wuzhou.entity.Address;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Map;
@Controller
@RequestMapping(value = "/view")
public class DataViewController {
    @RequestMapping(value = "/map")
    public String map(Map<String,Object> map){
        User user=new User();
        user.setId(1);
        user.setName("张三");
        user.setAddress(new Address("人民路"));
        map.put("user",user);
        return "view";
    }
}

(2)jsp前端

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/19
  Time: 21:27
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%--用来解析el表达式从后端传来的数据--%>
<html>
<head>
    <title>Title</title>
<%--    <script type="text/javascript" src="js/jquery-3.6.0.js"></script>--%>
<%--    <script type="text/javascript"></script>--%>
</head>
<body>
        ${requestScope.user}
</body>
</html>

  • Model
    (1)Model的Handler
package com.wuzhou.controller;

import com.wuzhou.entity.Address;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

@Controller
@RequestMapping(value = "/view")
public class DataViewController {
    @RequestMapping(value = "/model")
    public String model(Model model){
        User user=new User();
        user.setId(2);
        user.setName("张三2");
        user.setAddress(new Address("人民路2"));
        model.addAttribute("user",user);
        return "view";
    }
}

(2)jsp前端

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/19
  Time: 21:27
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%--用来解析el表达式从后端传来的数据--%>
<html>
<head>
    <title>Title</title>
<%--    <script type="text/javascript" src="js/jquery-3.6.0.js"></script>--%>
<%--    <script type="text/javascript"></script>--%>
</head>
<body>
        ${requestScope.user}
</body>
</html>
  • ModelAndView
    (1)ModelAndView的handler
package com.wuzhou.controller;

import com.wuzhou.entity.Address;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.InternalResourceView;

import java.util.Map;

@Controller
@RequestMapping(value = "/view")
public class DataViewController {
    @RequestMapping(value = "/modelandView")
    public ModelAndView modelAndView(ModelAndView modelAndView){
        User user=new User();
        user.setId(3);
        user.setName("张三3");
        user.setAddress(new Address("人民路3"));
        modelAndView.addObject("user",user);
        modelAndView.setViewName("view");
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView1")
    public ModelAndView modelAndView1(){
        User user=new User();
        user.setId(3);
        user.setName("张三3");
        user.setAddress(new Address("人民路3"));
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("user",user);
        modelAndView.setViewName("view");
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView2")
    public ModelAndView modelAndView2(){
        User user=new User();
        user.setId(4);
        user.setName("张三4");
        user.setAddress(new Address("人民路4"));
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("user",user);
        View view=new InternalResourceView("/view.jsp");
        modelAndView.setView(view);
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView3")
    public ModelAndView modelAndView3(){
        User user=new User();
        user.setId(5);
        user.setName("张三5");
        user.setAddress(new Address("人民路5"));
        ModelAndView modelAndView=new ModelAndView("view");
        modelAndView.addObject("user",user);
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView4")
    public ModelAndView modelAndView4(){
        User user=new User();
        user.setId(6);
        user.setName("张三6");
        user.setAddress(new Address("人民路6"));
        View view=new InternalResourceView("/view.jsp");
        ModelAndView modelAndView=new ModelAndView(view);
        modelAndView.addObject("user",user);
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView5")
    public ModelAndView modelAndView5(Map<String,User> map){
        User user=new User();
        user.setId(7);
        user.setName("张三7");
        user.setAddress(new Address("人民路7"));
        map.put("user",user);
        ModelAndView modelAndView=new ModelAndView("view",map);
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView6")
    public ModelAndView modelAndView6(Map<String,User> map){
        User user=new User();
        user.setId(8);
        user.setName("张三8");
        user.setAddress(new Address("人民路8"));
        map.put("user",user);
        View view=new InternalResourceView("/view.jsp");
        ModelAndView modelAndView=new ModelAndView(view,map);
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView7")
    public ModelAndView modelAndView7(){
        User user=new User();
        user.setId(9);
        user.setName("张三9");
        user.setAddress(new Address("人民路9"));
        ModelAndView modelAndView=new ModelAndView("view","user",user);
        return modelAndView;
    }
    @RequestMapping(value = "/modelandView8")
    public ModelAndView modelAndView8(){
        User user=new User();
        user.setId(10);
        user.setName("张三10");
        user.setAddress(new Address("人民路10"));
        View view=new InternalResourceView("/view.jsp");
        ModelAndView modelAndView=new ModelAndView(view,"user",user);
        return modelAndView;
    }
}
  • HttpServletRequest
    (1)request的Handler
@Controller
@RequestMapping(value = "/view")
public class DataViewController {
     @RequestMapping(value = "request")
    public String request(HttpServletRequest request){
        User user=new User();
        user.setId(11);
        user.setName("张三11");
        user.setAddress(new Address("人民路11"));
        request.setAttribute("user",user);
        return "view";
    }
}

(2)jsp前端

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/19
  Time: 21:27
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%--用来解析el表达式从后端传来的数据--%>
<html>
<head>
    <title>Title</title>
<%--    <script type="text/javascript" src="js/jquery-3.6.0.js"></script>--%>
<%--    <script type="text/javascript"></script>--%>
</head>
<body>
        ${requestScope.user}

</body>
</html>
  • @ModelAttribute
    (1)ModelAttribute:先定义一个带该注解的方法,该方法用来返回要填充到模型数据中的对象(这个注解方法是到达该前置控制器时,先执行这个带该注解的方法,封装好了模型数据)
@ModelAttribute
    public User getUser(){
        User user=new User();
        user.setId(12);
        user.setName("张三12");
        user.setAddress(new Address("人民路12"));
        return user;
    }

等同于

 @ModelAttribute
    public void getUser(Map<String,User> map){
        User user=new User();
        user.setId(12);
        user.setName("张三12");
        user.setAddress(new Address("人民路12"));
        map.put("user",user);
    }

等同于

 @ModelAttribute
    public void getUser(Model model) {
        User user = new User();
        user.setId(13);
        user.setName("张三13");
        user.setAddress(new Address("人民路13"));
        model.addAttribute("user",user);
    }

(2)业务方法中无需再处理模型数据,只需要返回视图即可

@Controller
@RequestMapping(value = "/view")
public class DataViewController {
   @RequestMapping(value = "/modelAttribute")
    public String modelAttribute(){
        return "view";
    }
}
将模型数据绑定到session对象中
  • 使用原生的servlet API
@Controller
@RequestMapping(value = "/view")
public class DataViewController {
    @RequestMapping(value = "/session")
    public String session(HttpServletRequest request){
        HttpSession session = request.getSession();
        User user = new User();
        user.setId(14);
        user.setName("张三14");
        user.setAddress(new Address("人民路14"));
        session.setAttribute("user",user);
        return "view";
    }
}

等同于

@Controller
@RequestMapping(value = "/view")
public class DataViewController {
    @RequestMapping(value = "/session1")
    public String session1(HttpSession session){
        User user = new User();
        user.setId(15);
        user.setName("张三15");
        user.setAddress(new Address("人民路15"));
        session.setAttribute("user",user);
        return "view";
    }
}
  • 使用注解@SessionAttribute

(1)对于在DataViewController控制器中的所有业务方法,只要向request中添加key=“user”、key="address"的对象时,springMVC会自动将数据添加到session中,并保持key不变。

@Controller
@RequestMapping(value = "/view")
//@SessionAttributes("user")//该注解里面的value值是指对应相对应的键的值,同时也支持添加多个
@SessionAttributes(value = {"user","address"})
public class DataViewController {

}

(2)对于在DataViewController控制器中的所有业务方法,只要向request中添加type=User.class、type=Address.class的对象时,springMVC会自动将数据添加到session中,并保持key不变。

@Controller
@RequestMapping(value = "/view")
@SessionAttributes(types = {User.class,Address.class})
public class DataViewController {

}
将模型数据绑定到application对象中
@Controller
@RequestMapping(value = "/view")
//@SessionAttributes("user")//该注解里面的value值是指对应相对应的键的值,同时也支持添加多个
//@SessionAttributes(value = {"user","address"})
//@SessionAttributes(types = {User.class,Address.class})
//@SessionAttributes(types = User.class)//这个是通过数据类型去添加的,也支持多个数据类型对象
/**
 * 上面两个注解的SessionAttribute是全局的,
 * 绝大多数业务方法都不需要既是把模型数据放入session对象中,
 * 更多的是把它放在request对象中,更多的是不支持使用的
 */
public class DataViewController {
 @RequestMapping(value = "/application")
    public String application(HttpServletRequest request){
        User user = new User();
        user.setId(16);
        user.setName("张三16");
        user.setAddress(new Address("人民路16"));
        ServletContext context = request.getServletContext();
        context.setAttribute("user",user);
        return "view";
    }
}
springMVC自定义数据转换器

数据转换器是指将客户端http请求中的参数转换为业务方法中定义的形参,其自定义表示开发者可以自主设计转换器的方式,HandlerAdapter已经提供了通用的转换器,譬如String类型转int类型、String类型转double类型以及表单数据进行自动封装等。但是在特定的业务场景之下,HandlerAdapter无法进行数据转换,需要开发者自己定义转换器。
(1)客户端输入String类型的数据"2021-06-11",自定义转换器将该数据转换为Date类型的对象

  • 创建一个DateConverter转换器,实现Converter接口
package com.wuzhou.converter;


import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 自定义日期转换器
 */
//@Controller
public class DateConverter implements Converter<String, Date> {//Converter<String, Date>加泛型指定待传入转换的参数类型和转换之后返回的参数类型
    private String pattern;
    public DateConverter(String pattern){
        this.pattern=pattern;
    }
    @Override
    public Date convert(String s) {
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat(this.pattern);
        Date date=null;
        try {
            date = simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
  • springmvc.xml配置转换器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--自动扫描包,base-package="com.entor"表示改包下的所有类以及子包下的所有类扫描-->
    <context:component-scan base-package="com.wuzhou"/>
    <!--配置默认的servlet请求处理策略,对静态资源不拦截,例如:html,css,js,image等-->
<!--    <mvc:default-servlet-handler/>-->
    <!--配置自定义日期转换器,然后再把conversion-service="conversionService"配置到<mvc>标签中-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="com.wuzhou.converter.DateConverter">
                    <constructor-arg type="java.lang.String" value="yyyy-MM-dd"/>
                </bean>
            </list>
        </property>
    </bean>
    <!--消息转换器,就是返回带有中文字符给客户端浏览器的格式消息设置-->
    <mvc:annotation-driven conversion-service="conversionService">
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=utf-8"/>
            </bean>
            <!--配置fastjson-->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>
</beans>
  • jsp
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/21
  Time: 12:50
  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="/converter/date" method="post">
        请输入日期:<input type="text" name="date"/>(yyyy-MM-dd格式)<br/>
        <input type="submit" value="提交">
    </form>
</body>
</html>
  • 处理日期的Handler
package com.wuzhou.controller;

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

import java.util.Date;

@RestController
@RequestMapping(value = "/converter")
public class DateConverter {
    @RequestMapping(value = "/date")
    public String date(Date date){
        return date.toString();
    }
}

(2)客户端输入String类型的数据"1-张三-20",自定义转换器将该数据转换为Student类型的对象

  • 创建一个StudentConverter转换器,实现Converter接口
package com.wuzhou.converter;


import com.wuzhou.entity.Student;
import org.springframework.core.convert.converter.Converter;
public class StudentConverter implements Converter<String, Student> {
    @Override
    public Student convert(String s) {
        //1-张三-20转成{"1","张三","20"}
        String[] split = s.split("-");
        Student student=new Student();
        student.setId(Integer.parseInt(split[0]));
        student.setName(split[1]);
        student.setAge(Integer.parseInt(split[2]));
        return student;
    }
}
  • springmvc.xml配置转换器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--自动扫描包,base-package="com.entor"表示改包下的所有类以及子包下的所有类扫描-->
    <context:component-scan base-package="com.wuzhou"/>
    <!--配置默认的servlet请求处理策略,对静态资源不拦截,例如:html,css,js,image等-->
<!--    <mvc:default-servlet-handler/>-->
    <!--配置自定义日期转换器,然后再把conversion-service="conversionService"配置到<mvc>标签中-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <!--配置日期数据转换器bean对象-->
                <bean class="com.wuzhou.converter.DateConverter">
                    <constructor-arg type="java.lang.String" value="yyyy-MM-dd"/>
                </bean>
                <!--配置对象数据转换器bean对象-->
                <bean class="com.wuzhou.converter.StudentConverter"/>
            </list>
        </property>
    </bean>
    <!--消息转换器,就是返回带有中文字符给客户端浏览器的格式消息设置-->
    <mvc:annotation-driven conversion-service="conversionService">
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value="text/html;charset=utf-8"/>
            </bean>
            <!--配置fastjson-->
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>
</beans>
  • jsp
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/21
  Time: 16:13
  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="/converter/student" method="post">
        请输入学生信息:<input type="text" name="student"/>(id-name-age)<br/>
        <input type="submit" name="提交"/>
    </form>
</body>
</html>
  • 处理对象转换的Handler
package com.wuzhou.controller;

import com.wuzhou.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@RestController
@RequestMapping(value = "/converter")
public class DateConverter {
    @RequestMapping(value = "/student")
    public String student(Student student){
        return student.toString();
    }
}
springMVC的REST架构

REST:Representational State Tranfer,资源表现层状态转换,是目前比较主流的一种互联网软件架构,它结构清晰、标准规范、易于理解、便于扩展。

  • 资源(Resource)
    网络上的一个实体,或者说网络中存在的一个具体信息,一段文字、一张图片、一首歌曲、一段视频等等,总之就是一个具体的存在。可以用一个URL指向它,每个资源都有一个对应的特定的URL,要获取该资源时,只需要访问对应的URL即可。
  • 表现层(Representational)
    资源具体呈现出来的形式,比如可以用txt格式表示,也可以用HTML、xml、json等格式来表示。
  • 状态转换(State Tranfer)
    客户端如果需要操作服务器端中的某个资源,就是通过某种方式让服务器端发生状态转换,而这种转换是建立在表现层之上的,所以叫“表现层状态转换”。
  • 特点
    (1)url更加简洁
    (2)有利于不同系统之间的资源共享,只要遵守一定的规范,不需要其他的配置即可实现资源费共享
如何使用

(1)REST具体的操作就是http协议中的四个表示操作方式的动词分别对应CRUD的基本操作。

  • GET用来表示获取资源
  • POST用来表示新建资源
  • PUT用来表示修改资源
  • DELETE用来表示删除资源
    (2)使用如下
  • RestHandler代码
package com.wuzhou.controller;
import com.wuzhou.entity.Student;
import com.wuzhou.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
@RestController
@RequestMapping(value = "/rest")
public class RestHandler {
    @Autowired
    private StudentMapper studentMapper;
    //    @RequestMapping(value = "/findAll")
//    public Collection<Student> findAll(HttpServletResponse response){
//        response.setContentType("text/json;charset=utf-8");
//        //处理数据的中文乱码响应给前端中文数据出现的问题,这个相当于是同步的请求,需要进行响应编码处理
//        return studentMapper.findAll();
//    }
    @GetMapping(value = "/findAll", produces = "application/json;charset=utf-8")
    public Collection<Student> findAll(HttpServletResponse response) {
        //response.setContentType("text/json;charset=utf-8");
        //处理数据的中文乱码响应给前端中文数据出现的问题,这个相当于是同步的请求,需要进行响应编码处理
        return studentMapper.findAll();
    }
    @PostMapping(value = "/findById/{id1}")
    public Student findById(@PathVariable("id1") long id1) {
        return studentMapper.findById(id1);
    }
//    @GetMapping(value = "/findById")
//    public Student findById(long id1) {
//        return studentMapper.findById(id1);
//
//    }
    //    @PostMapping(value = "/save")
//    public void save(Student student){
//        studentMapper.saveOrUpdate(student);
//    }
//    @PostMapping(value = "/save", produces = "application/json;charset=utf-8")
//    public void save(@RequestBody Student student) {
//        studentMapper.saveOrUpdate(student);
//    }
    @PostMapping(value = "/save", produces = "application/json;charset=utf-8")
    public void save(@RequestBody Student student) {
        studentMapper.saveOrUpdate(student);
    }
    //    @PutMapping(value = "/update")
//    public void update(@RequestBody Student student) {
//        studentMapper.saveOrUpdate(student);
//    }
    @PutMapping(value = "/update",produces = "application/json;charset=utf-8")
    public void update(@RequestBody Student student) {
        studentMapper.saveOrUpdate(student);
    }
    @DeleteMapping(value = "/deleteById/{id2}")
    public void deleteById(@PathVariable("id2") long id2) {
        studentMapper.deleteById(id2);
    }
}
  • Sudent接口以及实现业务类
package com.wuzhou.mapper;

import com.wuzhou.entity.Student;

import java.util.Collection;

public interface StudentMapper {
    public Collection<Student> findAll();
    //查询所有数据
    public Student findById(long id);
    //根据id查询
    public void saveOrUpdate(Student student);
    //新增或者更新操作
    public void deleteById(long id);
    //根据ID删除操作
}


package com.wuzhou.mapper.Impl;

import com.wuzhou.entity.Student;
import com.wuzhou.mapper.StudentMapper;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class StudentMapperImpl implements StudentMapper {
    private static Map<Long,Student> studentMap;
    static {
        studentMap=new HashMap<>();
        studentMap.put(1L,new Student(1L,"李白",2));
        studentMap.put(2L,new Student(2L,"杜甫",21));
        studentMap.put(3L,new Student(3L,"王昌龄",22));
    }


    @Override
    public Collection<Student> findAll() {
        return studentMap.values();
    }

    @Override
    public Student findById(long id) {
        return studentMap.get(id);
    }

    @Override
    public void saveOrUpdate(Student student) {
        studentMap.put(student.getId(), student);
    }

    @Override
    public void deleteById(long id) {
        studentMap.remove(id);
    }
}

  • Student实体了
package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
}

SpringMVC文件的上传和下载
单文件上传

它的底层是使用的是Apache fileupload组件完成上传的,SpringMVC对这种方式已经进行了封装。

  • pom.xml引入依赖
<!--文件上传依赖-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  • jsp前端代码
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/1
  Time: 13:46
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="img"/>
        <%--这里的name属性值file是要与前端控制器的MultipartFile file中的对象file名称一样
        才能获取传过来的对象进行封装,并且获取对象file的参数:
        file =
        MultipartFile[field="file",
        filename=WPS图片-修改尺寸(1).jpg,
        contentType=image/jpeg,
        size=16561]
        --%>
        <input type="submit" value="上传"/>
        <br>
        <img src="${path}">
    </form>
</body>
</html>

以上前端代码需要注意几点:
(1)input中的type属性是要是file文件
(2)form的method设置为post(get请求只能将文件名上传给服务器)
(3)form中的enctype属性要设置为multipart/form-data(如果不设置只能将文件名上传给服务器)

  • FileUpload上传的Handler
package com.wuzhou.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping(value = "/file")
public class FileHandler {
    @RequestMapping(value = "/upload")
    public String upload(MultipartFile img, HttpServletRequest request) {
        // System.out.println("file = " + file);
        if (img.getSize() > 0) {
            //获取保存上传文件的file的路径
            String path = request.getServletContext().getRealPath("file");
            //获取上传文件名
            String filename = img.getOriginalFilename();
            File file = new File(path, filename);
            try {
                img.transferTo(file);
                //保存上传之后的文件路径
                request.setAttribute("path", "/file/" + filename);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "uploadFile";
    }
}
  • SpringMVC中的配置文件,需要添加一个bean标签需要一个上传文件的解析器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
 <!--配置上传组件-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</beans>
  • 在web.xml文件中需要添加servlet请求处理,对静态资源(后缀名为png等)不拦截,不加这个配置,否则客户端无法访问静态png等资源
 <<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--添加一个处理乱码的过滤器,统一编码UTF-8,位置要放在第一位置,不然报错-->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!--配置前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</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>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--配置默认的servlet请求处理策略,对静态资源不拦截,例如:html,css,js,image等-->
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>
  </servlet-mapping>
</web-app>
多文件上传
  • 添加pom.xml依赖
 <!--加入jstl标签库依赖-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--文件上传依赖-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  • jsp前端代码
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/1
  Time: 13:46
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/file/uploads" method="post" enctype="multipart/form-data">
        文件1:<input type="file" name="imgs"/><br>
        文件2:<input type="file" name="imgs"/><br>
        文件3:<input type="file" name="imgs"/><br>
        文件4:<input type="file" name="imgs"/><br>
        <%--这里的name属性值file是要与前端控制器的MultipartFile file中的对象file名称一样
        才能获取传过来的对象进行封装,并且获取对象file的参数:
        file =
        MultipartFile[field="file",
        filename=WPS图片-修改尺寸(1).jpg,
        contentType=image/jpeg,
        size=16561]
        --%>
        <input type="submit" value="上传"/>
        <br>
        <%--需要利用jsp标签库中的foreach循环标签--%>
        <c:forEach items="${files}" var="file">
            <img src="${file}" width="300px">
        </c:forEach>
    </form>
</body>
</html>
  • 多文件Handler处理代码
package com.wuzhou.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping(value = "/file")
public class FileHandler {
    //@RequestMapping(value = "/uploads")
    @PostMapping(value = "/uploads")
    public String uploads(MultipartFile[] imgs, HttpServletRequest request) {
        // System.out.println("file = " + file);
        List<String> files = new ArrayList<>();
        for (MultipartFile img : imgs) {
            if (img.getSize() > 0) {
                //获取保存上传文件的file的路径
                String path = request.getServletContext().getRealPath("file");
                //获取上传文件名
                String filename = img.getOriginalFilename();
                File file = new File(path, filename);
                try {
                    img.transferTo(file);
                    //保存上传之后的文件路径
                    //request.setAttribute("path", "/file/" + filename);
                    files.add("/file/" + filename);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        request.setAttribute("files", files);
        return "uploadFiles";
    }
}
多文件下载
  • 添加pom.xml依赖
 <!--加入jstl标签库依赖-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!--文件上传依赖-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
  • jsp前端代码
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/1
  Time: 23:12
  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>
    <a href="/file/download/1">1.jpg</a>
    <a href="/file/download/2">2.jpg</a>
</body>
</html>
  • Handler处理控制器
package com.wuzhou.controller;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping(value = "/file")
public class FileHandler {
    @GetMapping(value = "/download/{name}")
    public void download(@PathVariable("name") String name, HttpServletRequest request, HttpServletResponse response) {
        if (name != null) {
             name+=".jpg";
            String path = request.getServletContext().getRealPath("file");
            File file = new File(path, name);
            OutputStream ops = null;
            if (file.exists()) {
                response.setContentType("application/forc-download");
//                response.setHeader("Content-Disposition", "attachment;filename=" + name);
                try {
                    response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(),"utf-8"));
                    //这个是面对下载文件中含有中文名字的下载文件名出现乱码问题得到很好的解决
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                try {
                    ops = response.getOutputStream();
                    ops.write(FileUtils.readFileToByteArray(file));
                    ops.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (ops != null) {
                        try {
                            ops.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}
SpringMVC表单标签库
在不使用标签库
  • Handler控制器
package com.wuzhou.controller;
import com.wuzhou.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
       ModelAndView modelAndView=new ModelAndView("show");
        //ModelAndView modelAndView=new ModelAndView("tagShow");
        Student student=new Student(1L,"王五",28);
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}
  • jsp前端代码
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/3
  Time: 10:26
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head>
    <title>学生信息</title>
</head>
<body>
    <form>
        学生ID是:<input type="text" name="id" value="${student.id}"><br>
        学生姓名是:<input type="text" name="name" value="${student.name}"><br>
        学生年龄是:<input type="text" name="age" value="${student.age}"><br>
        <input type="submit" value="提交"/>
    </form>
</body>
</html>
在使用标签库
  • Handler控制器
package com.wuzhou.controller;
import com.wuzhou.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
       //ModelAndView modelAndView=new ModelAndView("show");
        ModelAndView modelAndView=new ModelAndView("tagShow");
        Student student=new Student(1L,"王五",28);
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}
  • jsp前端代码
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/3
  Time: 10:47
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>学生信息</title>
</head>
<body>
<form:form modelAttribute="student">
    <%--这里的modelAttribute中的属性是与后台的控制器的模型视图绑定的别名要一样--->modelAndView.addObject("student",student);--%>
    学生ID:<form:input path="id"/><br>
    学生姓名:<form:input path="name"/><br>
    学生年龄:<form:input path="age"/><br>
    <input type="submit" value="提交"/>
</form:form>
</body>
</html>

(1)jsp页面导入SpringMVC表单标签库,与导入JSTL(javaserver pages tag language)标签库的语法非常相似,前缀通常prefix是可以自定义的,通常定义为form。

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

(2)将form表单与模型数据进行绑定,通过modelAttribute属性完成绑定,将modelAttribute属性设置的值为模型数据对应的key值。

  后天Handler代码:modelAndView.addObject("student",student);
  jsp代码:<form:form modelAttribute="student">

(3)form表单完成绑定之后,将模型数据中的值取出绑定到不同的前台标签中,通过设置标签的path属性完成,将path属性设置为模型数据对应的属性名即可。

 学生ID<form:input path="id"/><br>
 学生姓名:<form:input path="name"/><br>
 学生年龄:<form:input path="age"/><br>
常用的表单标签库
  • form
<form:form modelAttribute="student">
</form:form>
  • input
 学生ID<form:input path="id"/><br>

这个标签渲染的是HTML中的input标签中的type="text"属性,form标签绑定的是模型数据,input标签中绑定的是模型数据中的属性值,通过path属性可以与模型数据中的属性名进行一一对应,并且支持级联操作(所谓的级联就是对象中含有对象作为属性)。

 学生地址:<form:input path="address.addressName"/><br>
  • password
 学生密码:<form:password path="password"/><br>

这个标签是HTML中的input标签中的type="password"属性,通过path属性与模型数据的属性进行绑定,password标签的值不会在页面中显示。

  • checkbox复选框
复选框:<form:checkbox path="flag"/>flag的值<br>

这个渲染的是HTML中的input标签的type="checkbox"属性,通过path属性与模型数据的属性值进行绑定,其值可以绑定boolean、数组以及集合数据类型的数据。
如果绑定的是Boolean类型的值,如果该变量的值为true,则表示选中该复选框中的值,否则表示不选中。
如果绑定数组或者集合,数组或者集合中的元素等于checkbox中的value值,表示选中,否则表示不选中。
(1)jsp代码

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/3
  Time: 10:47
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%--引入springmvc标签库--%>
<html>
<head>
    <title>学生信息</title>
</head>
<body>
<%--<form:form modelAttribute="user">--%>
<form:form modelAttribute="student">
    <%--这里的modelAttribute中的属性是与后台的控制器的模型视图绑定的别名要一样--->modelAndView.addObject("student",student);--%>
    爱好:<form:checkbox path="hobby" value="读书"/>读书<br>
    <form:checkbox path="hobby" value="看报"/>看报<br>
    <form:checkbox path="hobby" value="喝酒"/>喝酒<br>
    <form:checkbox path="hobby" value="旅游"/>旅游<br>
    <form:checkbox path="hobby" value="打羽毛球"/>打羽毛球<br>
    <form:checkbox path="hobby" value="打篮球"/>打篮球<br>
    <form:checkbox path="hobby" value="打乒乓球"/>打乒乓球<br>
    <form:checkbox path="hobby" value="打牌"/>打牌<br>
    <input type="submit" value="提交"/>
</form:form>
</body>
</html>

(2)Handler代码

package com.wuzhou.controller;

import com.wuzhou.entity.Address;
import com.wuzhou.entity.Student;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.Arrays;

@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
//        ModelAndView modelAndView=new ModelAndView("show");
        ModelAndView modelAndView=new ModelAndView("tagShow");
        //Student student=new Student(1L,"王五",28);
//        Address address=new Address("人民路");
//        User user=new User(1,"张三",address);
//        modelAndView.addObject("user",user);
        Student student=new Student();
        //student.setHobby(new String[]{"读书", "打篮球", "打乒乓球"});
        student.setHobby(Arrays.asList("打羽毛球","打牌","喝酒"));
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}

(3)Student实体类

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
   // private String[] hobby;
    private boolean flag;
    private List<String> hobby;

    public Student(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}
  • checkboxes复选框
  爱好:<form:checkboxes path="selectHobby" items="${student.hobby}"/><br>

这是一个渲染的是一组input标签中的type="checkbox"属性,是对form标签中的form:checkbox的一种简化,需要结合items和path属性来使用,item是表示绑定所有被遍历的集合或者数组,path是绑定被选中的集合或者数组,也可以这样理解的是,items是全部可选的集合或者数组,而path是为默认选中的集合或者数组。
(1)后端Handler处理器

package com.wuzhou.controller;
import com.wuzhou.entity.Address;
import com.wuzhou.entity.Student;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
//        ModelAndView modelAndView=new ModelAndView("show");
        ModelAndView modelAndView=new ModelAndView("tagShow");
        //Student student=new Student(1L,"王五",28);
//        Address address=new Address("人民路");
//        User user=new User(1,"张三",address);
//        modelAndView.addObject("user",user);
        Student student=new Student();
        //student.setHobby(new String[]{"读书", "打篮球", "打乒乓球"});
        student.setHobby(Arrays.asList("打羽毛球","打牌","喝酒","旅游"));
        student.setSelectHobby(Arrays.asList("打牌","打羽毛球","旅游"));
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}

(2)实体类

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
   // private String[] hobby;
    private boolean flag;
    private List<String> hobby;
    private List<String> selectHobby;
    public Student(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

(3)前端jsp代码

	<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/3
  Time: 10:47
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%--引入springmvc标签库--%>
<html>
<head>
    <title>学生信息</title>
</head>
<body>
<%--<form:form modelAttribute="user">--%>
<form:form modelAttribute="student">
    <%--这里的modelAttribute中的属性是与后台的控制器的模型视图绑定的别名要一样--->modelAndView.addObject("student",student);--%>
    爱好:<form:checkboxes path="selectHobby" items="${student.hobby}"/><br>
    <input type="submit" value="提交"/>
</form:form>
</body>
</html>

上述代码需要注意的是path可以直接绑定模型数据的属性值,items则需要通过EL表达式的形式从域中获取数据,不能直接写属性名。

  • radiobutton单选框
 单选框:<form:radiobutton path="radioId" value="1"/>单选框<br>

渲染的是HTML中的一个input的type属性type=“radio”,绑定的数据与标签的value值相等则为选中,否则不选中。
(1)前端jsp代码

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/3
  Time: 10:47
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%--引入springmvc标签库--%>
<html>
<head>
    <title>学生信息</title>
</head>
<body>
<%--<form:form modelAttribute="user">--%>
<form:form modelAttribute="student">
    <%--这里的modelAttribute中的属性是与后台的控制器的模型视图绑定的别名要一样--->modelAndView.addObject("student",student);--%>
    单选框:<form:radiobutton path="radioId" value="1"/>单选框<br>
    <input type="submit" value="提交"/>
</form:form>
</body>
</html>

(2)实体类代码

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
   // private String[] hobby;
    private boolean flag;
    private List<String> hobby;
    private List<String> selectHobby;
    private Integer radioId;
    public Student(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

(3)Handler代码

package com.wuzhou.controller;
import com.wuzhou.entity.Address;
import com.wuzhou.entity.Student;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
//        ModelAndView modelAndView=new ModelAndView("show");
        ModelAndView modelAndView=new ModelAndView("tagShow");
        //Student student=new Student(1L,"王五",28);
//        Address address=new Address("人民路");
//        User user=new User(1,"张三",address);
//        modelAndView.addObject("user",user);
        Student student=new Student();
        student.setRadioId(1);
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}
  • radiobuttons单选框
<form:radiobuttons path="selectGrape" items="${student.map}"/>

这个渲染的是HTML中的一组input标签属性中的type="radio"属性值,这里需要结合items和path两个属性来使用,items是用来绑定被遍历的数组或者集合,而path绑定的是被选中的值,items是为全部可选类型,path是默认选中的选项,其用法和form:checkboxes一致
(1)前端代码

<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/3
  Time: 10:47
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%--引入springmvc标签库--%>
<html>
<head>
    <title>学生信息</title>
</head>
<body>
<%--<form:form modelAttribute="user">--%>
<form:form modelAttribute="student">
    <%--这里的modelAttribute中的属性是与后台的控制器的模型视图绑定的别名要一样--->modelAndView.addObject("student",student);--%>
    单选框:<form:radiobutton path="radioId" value="1"/>单选框<br>
    学生年级:<form:radiobuttons path="selectGrape" items="${student.map}"/><br>
    <input type="submit" value="提交"/>
</form:form>
</body>
</html>

(2)实体类

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
   // private String[] hobby;
    private boolean flag;
    private List<String> hobby;
    private List<String> selectHobby;
    private Integer radioId;
    private Map<Integer,String> map;
    private Integer selectGrape;
    public Student(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

(3)Handler处理器

package com.wuzhou.controller;
import com.wuzhou.entity.Address;
import com.wuzhou.entity.Student;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
//        ModelAndView modelAndView=new ModelAndView("show");
        ModelAndView modelAndView=new ModelAndView("tagShow");
        //Student student=new Student(1L,"王五",28);
//        Address address=new Address("人民路");
//        User user=new User(1,"张三",address);
//        modelAndView.addObject("user",user);
        Student student=new Student();
        student.setRadioId(1);
        Map<Integer,String> map=new HashMap<>();
        map.put(1,"一年级");
        map.put(2,"二年级");
        map.put(3,"三年级");
        student.setMap(map);
        student.setSelectGrape(2);
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}
  • select下拉框
<form:select path="selectCity" items="${student.mapCity}"/>

这个标签渲染的是HTML中的一个select标签,需要结合items和path属性进行结合使用,其中items绑定的是被遍历的数组或者集合,path绑定的是被选中的集合或者数组中的值,其用法与form标签中的chechboxes和radiobuttons一样
(1)前端jsp

所在城市:<form:select path="selectCity" items="${student.mapCity}"/>

(2)后端Handler

package com.wuzhou.controller;
import com.wuzhou.entity.Address;
import com.wuzhou.entity.Student;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
//        ModelAndView modelAndView=new ModelAndView("show");
        ModelAndView modelAndView=new ModelAndView("tagShow");
        //Student student=new Student(1L,"王五",28);
//        Address address=new Address("人民路");
//        User user=new User(1,"张三",address);
//        modelAndView.addObject("user",user);
        Student student=new Student();
        Map<Integer,String> mapCity=new HashMap<>();
        mapCity.put(1,"桂林");
        mapCity.put(2,"梧州");
        mapCity.put(3,"河池");
        mapCity.put(4,"柳州");
        student.setMapCity(mapCity);
        student.setSelectCity(2);
        //student.setSelectCity(4);
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}

(3)实体类代码

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
   // private String[] hobby;
    private boolean flag;
    private List<String> hobby;
    private List<String> selectHobby;
    private Integer radioId;
    private Map<Integer,String> map;
    private Integer selectGrape;
    private Map<Integer,String> mapCity;
    private Integer selectCity;
    private String introduce;
    public Student(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}
  • options
    这个标签是要结合form标签中的select一起使用的,form标签中的select只定义path属性,而后在form:select标签的内部添加一个子标签form:options,设置items属性,获取被遍历的集合。

(1)前端jsp

所在城市1<form:select path="selectCity">
    <form:options items="${student.mapCity}"/>
</form:select><br>

(2)Handler后端代码

Map<Integer,String> mapCity=new HashMap<>();
        mapCity.put(1,"桂林");
        mapCity.put(2,"梧州");
        mapCity.put(3,"河池");
        mapCity.put(4,"柳州");
        student.setMapCity(mapCity);
        student.setSelectCity(2);
        //student.setSelectCity(4);
        modelAndView.addObject("student",student);

(3)实体类

package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private Long id;
    private String name;
    private Integer age;
   // private String[] hobby;
    private boolean flag;
    private List<String> hobby;
    private List<String> selectHobby;
    private Integer radioId;
    private Map<Integer,String> map;
    private Integer selectGrape;
    private Map<Integer,String> mapCity;
    private Integer selectCity;
    private String introduce;
    public Student(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}
  • option
    form:select标签要结合form:option来一起使用,其中form:select只需要定义path属性,然后给每一个form:option 设置一个value值,根据path属性中的值与其value属性中的值相匹配,相匹配之后就是默认选中。

(1)jsp代码

 所在城市2<form:select path="selectCity">
    <form:option value="1">柳州</form:option>
    <form:option value="2">梧州</form:option>
    <form:option value="3">贺州</form:option>
</form:select><br>

(2)后端Hander

package com.wuzhou.controller;
import com.wuzhou.entity.Address;
import com.wuzhou.entity.Student;
import com.wuzhou.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping(value = "/tag")
public class TagHandler {
    @RequestMapping(value = "/getTag")
    public ModelAndView getTag(){
//        ModelAndView modelAndView=new ModelAndView("show");
        ModelAndView modelAndView=new ModelAndView("tagShow");
        //Student student=new Student(1L,"王五",28);
//        Address address=new Address("人民路");
//        User user=new User(1,"张三",address);
//        modelAndView.addObject("user",user);
        Student student=new Student();
        student.setSelectCity(2);
        //student.setSelectCity(4);
        modelAndView.addObject("student",student);
        return modelAndView;
    }
}
  • textarea
    该渲染的是HTML中的一个textarea标签,其中path绑定的是模型数据的属性值,作为文本输入域的默认值。

(1)jsp代码

  文本信息:<form:textarea path="introduce"/><br>

(2)后端Handler

 student.setIntroduce("你好,我是老板");
 modelAndView.addObject("student",student);
  • errors
    处理错误信息,一般用于数据校验,然而该标签需要结合springMVC的验证器结合起来才能使用

七、SpringMVC的数据校验

定义

SpringMVC提供了两种数据校验的方式

  • 基于validator接口(基于validator接口实现,需要自定义validator验证器,每一条数据的验证规则都需要开发者手动完成)
  • 使用注解AnnotationJSR-303标准进行校验(使用注解AnnotationJSR-303标准则反之不需要添加自定义的验证器,可以通过注解的方式可以直接在实体类中添加每个属性的验证规则,这种方式更加简便,在实际开发中都是推荐使用的)

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

使用接口Validator自定义验证器
  • 自定义验证器
package com.wuzhou.validator;
import com.wuzhou.entity.Account;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
/**
 * 这个类是验证器类,实现了Validator接口
 */
public class AccountValidator implements Validator {
    /**
     * 先执行这个方法,若返回的结果是true,才往下进行,否则不往下执行
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return Account.class.equals(aClass);
    }
    /**
     * 这个才是真正验证器的实现的方法
     * @param o
     * @param errors
     */
    @Override
    public void validate(Object o, Errors errors) {
        ValidationUtils.rejectIfEmpty(errors,"name",null,"姓名不能为空");
        ValidationUtils.rejectIfEmpty(errors,"password",null,"密码不能为空");
    }
}
  • 实体类
package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
    private String name;
    private String password;
}
  • Handler控制器
package com.wuzhou.controller;
import com.wuzhou.entity.Account;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(value = "/validator")
public class ValidatorHandler {
    @GetMapping(value = "/login")
    public String login(Model model){
        model.addAttribute("account",new Account());
        return "login";
    }
    @PostMapping(value = "/login")//@Validated加这个注解会自动开启验证器功能
    public String login(@Validated Account account, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            return "login";
        }
        return "index";
    }
}
  • 需要配置springmvc.xml文件,把控制器与验证器进行联系
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--自动扫描包,base-package="com.entor"表示改包下的所有类以及子包下的所有类扫描-->
    <context:component-scan base-package="com.wuzhou"/>
 <!--配置自定义验证器-->
    <bean id="accountValidator" class="com.wuzhou.validator.AccountValidator"/>  <mvc:annotation-driven validator="accountValidator"/>
</beans>
  • jsp前端代码
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/7/7
  Time: 22:44
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="from" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form:form modelAttribute="account" action="/validator/login" method="post">
        姓名:<form:input path="name"/><from:errors path="name"/><br>
        密码:<form:input path="password"/><from:errors path="password"/><br>
        <input type="submit" value="提交">
    </form:form>
</body>
</html>
使用Annotation JSR - 303 标准
  • 需要在pom.xml中添加相关依赖
 <!--JSR-303验证器,利用的是Hibernate-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
            <version>3.4.1.Final</version>
        </dependency>
  • 通过注解的形式在实体类中添加验证规则
package com.wuzhou.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    @NotEmpty(message = "用户名不能为空")
    private String username;
    @Size(min = 6,max = 12,message = "密码6-12位")
    private String password;
    @Email(regexp = "^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\\\.[a-zA-Z0-9-]+)*\\\\.[a-zA-Z0-9]{2,6}$",message = "请输入正确的邮箱格式")
    private String email;
    @Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\\\\\d{8}$",message = "请输入正确的电话")
    private String phone;
}
  • 后台控制器
package com.wuzhou.controller;

import com.wuzhou.entity.Account;
import com.wuzhou.entity.Person;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;

@Controller
@RequestMapping(value = "/validator")
public class ValidatorHandler {
    @GetMapping(value = "/register")
    public String register(Model model){
        model.addAttribute("person",new Person());
        return "register2";
    }
    @PostMapping(value = "/register")//@Valid加这个注解会自动开启Annotation JSR-303验证器功能
    public String register(@Valid Person person, BindingResult bindingResult){
        if (bindingResult.hasErrors()){
            return "register2";
        }
        return "index";
    }
}
  • 配置springmvc.xml文件
     <mvc:annotation-driven/>
    <!--需要添加一个新的注解驱动才行-->
  • jsp
<%--
  Created by IntelliJ IDEA.
  User: laowangzhuamyong
  Date: 2021/6/13
  Time: 22:58
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form:form modelAttribute="person" method="post" action="/validator/register">
        用户名:<form:input path="username" autocomplete="false"/><form:errors path="username"/><br>
        密码:<form:password path="password" autocomplete="false"/><form:errors path="password"/><br>
        邮箱:<form:input path="email" autocomplete="false"/><form:errors path="email"/><br>
        电话:<form:input path="phone" autocomplete="false"/><form:errors path="phone"/><br>
        <input type="submit" value="提交"/>
    </form:form>
</body>
</html>
小结

校验规则详解:
@Null 被注解的元素必须为null

@NotNull 被注解的元素不能为null

@Min(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值

@Max(value) 被注解的元素必须是一个数字,其值必须小于于等于指定的最大值

@Email 被注解的元素必须是电子邮箱地址

@Pattern 被注解的元素必须符合对应的正则表达式

@Length 被注解的元素的大小必须在指定的范围内

@NotEmpty 被注解的字符串的值必须非空

Null 和 Empty 是不同的结果,String str = null,str 是 null,String str = “”,str 不是 null,其值为空。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值