SpringMVC学习-2(完结)

上篇文章已经看到第六集了,第七集开始

SpringMVC模型数据解析

  1. session
@RequestMapping("/session")
public String session(HttpServletRequest request){
    
    
    HttpSession session = request.getSession();
    User user = new User();
    user.setId(1);
    user.setName("Adger");
    session.setAttribute("user",user);
    return "view";
}

jsp视图更改

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
 request:${
    
    requestScope.user}

session:${
    
    sessionScope.user}
</body>
</html>

浏览器访问测试:http://localhost:8080/view/session
只存进session里面,但是request为什么也有值,是因为一个注解@ModelAttribute注释掉,就可以了
在这里插入图片描述

直接创建好的session

@RequestMapping("/session2")
public String session2(HttpSession httpSession){
    
    
    User user = new User();
    user.setId(1);
    user.setName("Adger");
    httpSession.setAttribute("user",user);
    return "view";
}

直接访问测试:http://localhost:8080/view/session2
在这里插入图片描述

@SessionAttributes

这个注解不是给方法添加而是给类添加的,这个注解添加之后每个注解都生效,在类定义上只要加上@SessionAttributes(value = “user”)就都会有
在这里插入图片描述
测试map方法:http://localhost:8080/view/map
发现成功
在这里插入图片描述
上面是根据名字来添加的,下面是根据类型来添加的
@SessionAttributes(types = User.class)
在这里插入图片描述
上述两种方式是针对全局的,访问测试发现有数据:http://localhost:8080/view/map

在这里插入图片描述
添加多个的形式@SessionAttributes(value = {“user”,“address”})或者@SessionAttributes(types = {User.class, Address.class})

application

将模型数据绑定到application对象中,这个范围大小,使用起来没什么意义

SpringMVC自定义数据转换器

数据转换器是指:将客户端的HTTP请求中的参数直接转换为业务方法中定义的形参,自定义表示开发者可以自主设计转换的方式,HandlerAdapter已经提供了通用的转换,String转int,String转double,表单数据的封装,在特殊的业务场景下HandlerAdapter无法进行转换,就需要开发者自定义转换器

客户端输入String类型的数据"2020-03-03,自定义数据转换器,该数据转为Date类型的对象"

  • 创建DataConverter接口,名字可以自定义,实现Convertr接口
package club.adger.converter;

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

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

/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/27/10:58
* 注意 不要 倒错包
* 实现这个接口的方法
* 这个接口 是有一个泛型的 只需要定义需要转的类型 就比如 String 转 Data类型 只需要 按下面 定义非常方便 扩展性很好
*/
public class DateConverter implements 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配置转换器

<!-- 配置自定义转换器 id自定义 但是下面使用的id必须一样-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
   <property name="converters">
       <list>
           <!-- 自己的转换器传进来 -->
           <bean class="club.adger.converter.DateConverter">
               <constructor-arg type="java.lang.String" value="yyyy-MM-dd"></constructor-arg>
           </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"></property>
       </bean>
       <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"></bean>
   </mvc:message-converters>
</mvc:annotation-driven>

新建一个jsp页面。方便测试

扫描二维码关注公众号,回复: 13125301 查看本文章
<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/27
  Time: 11:40
  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">
        <%-- name属性跟 方法中的参数对应 服务器端的控制器 --%>
        请输入日期: <input type="text" name="date">(--)<br>
            <input type="submit" value="提交">
    </form>
</body>
</html>

新建一个Handler或者controller

package club.adger.controller;

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

import java.util.Date;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/27/11:40
 */
@RestController
@RequestMapping("/converter")
public class ConverterHandler {
    
    

    @RequestMapping("/date")
    public String date(Date date){
    
    
        //返回到客户端
        return date.toString();
    }
}

运行测试访问浏览器:http://localhost:8080/addDate.jsp
在这里插入图片描述
发现成功
在这里插入图片描述

Spring MVC RESTful架构

RESTful风格开发的项目结构清晰,RESTful风格在前后端分离的项目我觉得还是蛮多的,是目前比较主流的互联网软件架构,REST是资源表现层状态转换

REST简写解释

  • R Resources(资源)
    存在的一个具体信息,列如,一段文本,一张图片

  • E Representation(表现层)
    资源具体呈现出来的形式,比如文本可以用txt文本表示,也可以用HTML,JSON或者XML形式表示

  • ST State Transfer (状态转换)
    客户端如果希望操作服务器的某个资源,就会让服务端发生状态转换,而这种转换是建立在表现层之上的

如何使用

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

  • GET 用来表示获取资源
  • POST 用来表示新建资源
  • PUT 用来表示修改资源
  • DELETE 用来表示删除资源
    值得注意的是,get请求自己浏览器能测一测,其他的请求方式得借助于第三方工具了,如PostMan
    新建一个RESTHandler,作增删改查操作,额视频上面叫的respository,也有人叫dao或者mapper的,我这里就叫mapper吧
    新建一个Student实体类
package club.adger.entity;

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

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/27/15:49
 * @AllArgsConstructor 这个表示添加 有参构造函数
 * @NoArgsConstructor 这个表示添加的 无参构造函数
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    
    
    private long id;
    private String name;
    private int age;
}

新建一个StudentMapper,由于视频没有用到持久层的框架,也没有真正用到数据库,所以用了map集合模拟下,怎么看lombok呢,直接点击idea的Structure,就可以看到你的实体类有哪些东西了
在这里插入图片描述
StudentMapper持久层Java文件,这是一个接口

package club.adger.mapper;

import club.adger.entity.Student;

import java.util.Collection;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/27/15:46
 * 请注意这是一个接口
 */
public interface StudentMapper  {
    
    
    /**
     * 这是查找所有学生的方法
     * @return
     */
    public Collection<Student> findAll();

    /**
     * 这是查找 单个学生的方法
     * @param id
     * @return
     */
    public Student findById(long id);

    /**
     * 这是保存或者修改单个学生的方法
     * @param student
     */
    public void saveOrUpdate(Student student);

    /**
     * 这是删除某个学生的方法
     * @param id
     */
    public void deleteById(long id);
}

新建一个impl的包,建在mapper下面,里面的类全是实现mapper接口的

package club.adger.mapper.impl;

import club.adger.entity.Student;
import club.adger.mapper.StudentMapper;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/27/15:55
 * @controller 控制器(注入服务)
 *
 * @service 服务(注入dao)
 * 主要用来进行业务的逻辑处理
 *
 * @repository(实现dao访问)
 * 即DAO组件
 */
@Repository
public class StudentMapperImpl implements StudentMapper {
    
    

    private static Map<Long,Student> studentMap;

    static {
    
    
        studentMap = new HashMap<>();
        studentMap.put(1L,new Student(1L,"Adger",20));
        studentMap.put(2L,new Student(2L,"刘杰",21));
        studentMap.put(3L,new Student(3L,"Adger",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);
    }
}

控制器方法

package club.adger.controller;

import club.adger.entity.Student;
import club.adger.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.Collection;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/27/15:42
 */
@RestController
@RequestMapping("/rest")
public class RESTHandler {
    
    

    @Autowired
    private StudentMapper studentMapper;

    /**
     * 查找是发送get请求
     * @RequestMapping(value = "/findAll",method = RequestMethod.GET) 是等于 @GEtMapping的,就相当于简写形式吧
     * 由于中文放在了对象里面,会出现中文乱码
     * @return
     */
    @GetMapping("/findAll")
    public Collection<Student> findAll(HttpServletResponse response){
    
    
        response.setContentType("text/json;charset=UTF-8");
        return studentMapper.findAll();
    }

    @GetMapping("/findById/{id}")
    public Student findById(@PathVariable("id") long id){
    
    
        return studentMapper.findById(id);
    }

    @PostMapping("/save")
    public void save(@RequestBody Student student) {
    
    
        studentMapper.saveOrUpdate(student);
    }

    @PutMapping("/update")
    public void update(@RequestBody Student student){
    
    
        studentMapper.saveOrUpdate(student);
    }

    @DeleteMapping("/deleteById/{id}")
    public void deleteById(@PathVariable("id") long id){
    
    
        studentMapper.deleteById(id);
    }
}

访问测试:http://localhost:8080/rest/findAll
由于是@RestController所以是json格式形式返回,你们可能不一样,我这里用了json-view插件
在这里插入图片描述
http://localhost:8080/rest/findById/1
在这里插入图片描述
get的请求还好测试,但是删除跟跟修改呢对吧还有post用一下postman
在postMan测试保存:http://localhost:8080/rest/save
在这里插入图片描述

浏览器测试访问:http://localhost:8080/rest/findAll
在这里插入图片描述
测试put请求:http://localhost:8080/rest/update
在这里插入图片描述
发现成功
在这里插入图片描述
测试Delete请求:http://localhost:8080/rest/deleteById/1
在这里插入图片描述
发现成功
在这里插入图片描述

Spring MVC 文件上传 下载

上传跟下载这个功能用的还是比较多的,底层是通过IO流上传下载的

单文件上传

底层使用Apache fileupload组件完成上传,SpringMVC对这种方式进行了封装,只需要在pom.xml加入依赖,就相当于先引入文件上传的jar包

<!-- 这里更改下servlet-api 版本不一样有些方法没有-->
 <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>4.0.1</version>
  <scope>provided</scope>
</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.2.2</version>
 </dependency>

SpringMVC.xml配置,里面还可以配置文件上传的大小等

<!-- 配置文件上传下载的组件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>

JSP页面

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/28
  Time: 10:41
  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>
    <%--
    这个method一定是post而不是文件本身 get有大小限制
    一定需要这个不然只能上传文件名字
    enctype="multipart/form-data
    --%>
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="img">
        <input type="submit" value="上传">
    </form>
</body>
</html>

后台方法

package club.adger.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;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/10:44
 */
@Controller
@RequestMapping("/file")
public class FileHandler {
    
    

    /**
     * MultipartFile img 接受 客户端 传进来的参数 就是文件
     * @param img
     * @return
     */
    @PostMapping("/upload")
    public String upload(MultipartFile img, HttpServletRequest request){
    
    
        if(img.getSize() > 0){
    
    
            //获取保存文件的路径
            String path = request.getServletContext().getRealPath("file");
            //获取上传的文件名
            String name = img.getOriginalFilename();
            File file = new File(path, name);
            if (!file.getParentFile().exists()) {
    
    
                file.getParentFile().mkdirs();
                System.out.println("创建目录" + file);
            }
            try {
    
    
                img.transferTo(file);
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        System.out.println(img);
        return "upload";
    }
}

浏览器访问测试:http://localhost:8080/upload.jsp
发现成功
在这里插入图片描述

上传后的文件显示

服务器端方法更改

package club.adger.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;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/10:44
 */
@Controller
@RequestMapping("/file")
public class FileHandler {
    
    

    /**
     * MultipartFile img 接受 客户端 传进来的参数 就是文件
     * @param img
     * @return
     */
    @PostMapping("/upload")
    public String upload(MultipartFile img, HttpServletRequest request){
    
    
        if(img.getSize() > 0){
    
    
            //获取保存文件的路径
            String path = request.getServletContext().getRealPath("file");
            //获取上传的文件名
            String name = img.getOriginalFilename();
            File file = new File(path, name);
            if (!file.getParentFile().exists()) {
    
    
                file.getParentFile().mkdirs();
                System.out.println("创建目录" + file);
            }
            try {
    
    
                img.transferTo(file);
                //保存上传之后的文件路径
                request.setAttribute("path",name);
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        System.out.println(img);
        return "upload";
    }
}

jsp页面更改

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/28
  Time: 10:41
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--
    这个method一定是post而不是文件本身 get有大小限制
    一定需要这个不然只能上传文件名字
    enctype="multipart/form-data
    --%>
    <form action="/file/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="img">
        <input type="submit" value="上传">
    </form>
    <img src="${path}">
</body>
</html>

由于文件也是资源,所以会被SpringMVC拦截,所以web.xml中也要放行

<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>*.png</url-pattern>
</servlet-mapping>

<servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>*.gif</url-pattern>
</servlet-mapping>

浏览器测试访问:http://localhost:8080/upload.jsp
在这里插入图片描述
发现成功
在这里插入图片描述

多文件上传

服务器端增加方法

@PostMapping("/uploads")
 public String uploads(MultipartFile[] imgs,HttpServletRequest request){
    
    
     List<String> files = new ArrayList<>();
      for (MultipartFile img : imgs){
    
    
         if(img.getSize() > 0){
    
    
             //获取保存文件的路径
             String path = request.getServletContext().getRealPath("file");
             //获取上传的文件名
             String name = img.getOriginalFilename();
             File file = new File(path, name);
             if (!file.getParentFile().exists()) {
    
    
                 file.getParentFile().mkdirs();
                 System.out.println("创建目录" + file);
             }
             try {
    
    
                 img.transferTo(file);
                 files.add(name);
             } catch (IOException e) {
    
    
                 e.printStackTrace();
             }
         }
     }
     request.setAttribute("files",files);
    return "uploads";
 }

pom.xml引入el表达式,因为是多文件,用遍历的形式,到时候回显上去

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

新建uploads.jsp页面

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/28
  Time: 11:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <%-- 控制图片的大小 --%>
    <style>
        img{
    
    
            width: 300px;
            height: 300px;
        }
    </style>
</head>
<body>
<form action="/file/uploads" method="post" enctype="multipart/form-data">
    file1:<input type="file" name="imgs"><br>
    file2:<input type="file" name="imgs"><br>
    file3:<input type="file" name="imgs"><br>
    <input type="submit" value="上传">
</form>
<c:forEach items="${files}" var="file">
    <img src="${file}">
</c:forEach>
</body>
</html>

浏览器访问测试:http://localhost:8080/uploads.jsp
在这里插入图片描述
发现成功
在这里插入图片描述
注意的是你服务器关闭文件就没了,多文件上传就是传了一个数组的形式过去

文件的下载

上传的话就是把客户端的资源上传到服务器端,下载的话就是一个反向过程,但是你的服务器端必须有这个资源才能下载
新建一个download.jsp页面,这里是Get请求,因为是超链接

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/28
  Time: 11:52
  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/14">14.gif</a>
<a href="/file/download/15">15.gif</a>
<a href="/file/download/16">16.gif</a>
</body>
</html>

新建后端方法

 /**
     * rest风格 加映射 @PathVariable
     * @param name
     * @param request
     * @param response
     */
    @GetMapping("/download/{name}")
    public void download(@PathVariable("name") String name, HttpServletRequest request, HttpServletResponse response){
    
    
        if(name != null){
    
    
            name += ".gif";
            String path = request.getServletContext().getRealPath("file");
            File file = new File(path, name);
            OutputStream outputStream = null;
            if(file.exists()){
    
    
                // 响应的设置
                response.setContentType("application/forc-download");
                response.setHeader("Content-Disposition","attachment;filename="+name);
                try {
    
    
                    outputStream = response.getOutputStream();
                    outputStream.write(FileUtils.readFileToByteArray(file));
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }finally {
    
    
                    if(outputStream != null){
    
    
                        try {
    
    
                            outputStream.close();
                        } catch (IOException e) {
    
    
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

我先把文件传上去,去download页面测试:http://localhost:8080/download.jsp
在这里插入图片描述
在这里插入图片描述
就下载成功了
在这里插入图片描述

SpringMVC表单 标签库

新建后端方法跟文件

package club.adger.controller;

import club.adger.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/12:19
 */
@Controller
@RequestMapping("/tag")
public class TagController {
    
    

    @GetMapping("/get")
    public ModelAndView get(){
    
    
        ModelAndView modelAndView = new ModelAndView("show");
        Student student = new Student(1L, "Adger", 22);
        modelAndView.addObject("student", student);
        return modelAndView;
    }
}

新建show.jsp页面

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/28
  Time: 12:25
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>学生信息</h1>
    学生ID: <input type="text" name="id" value="${student.id}">
    学生姓名:<input type="text" name="name" value="${student.name}">
    学生年龄:<input type="text" name="age" value="${student.age}">
</body>
</html>

浏览器测试访问:http://localhost:8080/tag/get
在这里插入图片描述
上面不是用了表单标签库,下面的代码是用了表单标签库,后端方法改下视图就可以了

package club.adger.controller;

import club.adger.entity.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/12:19
 */
@Controller
@RequestMapping("/tag")
public class TagController {
    
    

    @GetMapping("/get")
    public ModelAndView get(){
    
    
        ModelAndView modelAndView = new ModelAndView("tag");
        Student student = new Student(1L, "Adger", 22);
        modelAndView.addObject("student", student);
        return modelAndView;
    }
}

新建tag.jsp页面

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/28
  Time: 12:30
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>学生信息表单标签库</h1>
<%-- modelAttribute是后端的key值   注意闭合标签--%>
<form:form modelAttribute="student">
    学生ID: <form:input path="id"/>
    学生姓名:<form:input path="name"/>
    学生年龄:<form:input path="age"/>
</form:form>
</body>
</html>


浏览器测试访问:http://localhost:8080/tag/get
发现成功,发现变的只是视图界面的代码
在这里插入图片描述
jsp页面需要导入表单标签库,前缀名字按照自己喜好

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

后端方法中与模型数据绑定

 modelAndView.addObject("student", student);

最后通过path属性绑定,对应实体类的属性

path="id"

常用的表单标签

  • modelAttribute
    modelAttribute属性绑定模型数据
<form:form modelAttribute="student"></form:form>
  • input
    渲染的是input标签,这两个是结合起来使用的,支持级联操作
<form:input path="id"/>
  • password
    与上面用法一样,值不会再页面显示,有值不显示
    还有很多就没写了。感觉不怎么常使用

SpringMVC数据校验

SpringMVC提供了两种数据校验的方式:1.基于Validator接口、2.使用Annotation-JSR-303标准进行校验
基于Validator接口的方式需要自定义Validator验证器,每一条的数据验证需要开发者手动完成,使用JSR-303则不需要,通过注解的方式可以在实体类中添加每个属性的验证规则

基于Validator 接口

实体类Account

package club.adger.entity;

import lombok.Data;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/13:27
 */
@Data
public class Account {
    
    
    private String name;
    private String password;
}

  • 自定义验证器AccountValidator接口,实现Validator接口
    新建一个validator包
package club.adger.validator;

import club.adger.entity.Account;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/13:30
 * 如果 supports 是 true validate 方法是执行的,如果不是就不执行
 */
public class AccountValidator implements Validator {
    
    
    @Override
    public boolean supports(Class<?> clazz) {
    
    
        return Account.class.equals(clazz);
    }

    /**
     * 第一个参数为实体类的属性哪个属性需要验证
     * 第二个参数为 验证状态
     * 第三个参数为 错误信息
     * @param target
     * @param errors
     */
    @Override
    public void validate(Object target, Errors errors) {
    
    
        ValidationUtils.rejectIfEmpty(errors,"name",null,"姓名不能为空");
        ValidationUtils.rejectIfEmpty(errors,"password",null,"密码不能为空");
    }
}

新建ValidatorHandler

package club.adger.controller;

import club.adger.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;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/13:34
 */
@Controller
@RequestMapping("/validator")
public class ValidatorHandler {
    
    

    /**
     * 这个方法只是为了绑定模型
     * @param model
     * @return
     */
    @GetMapping("/login")
    public String login(Model model){
    
    
        model.addAttribute("account",new Account());
        return "login";
    }

    /**
     * @Validated 注解 代表验证器 验证
     * @param account
     * @param result
     * @return
     */
    @PostMapping("/login")
    public String login(@Validated Account account, BindingResult result){
    
    
        //是否有错
        if (result.hasErrors()){
    
    
            return "login";
        }
        return "index";
    }
}

新建login.jsp页面

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/28
  Time: 13:36
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@taglib prefix="form" 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"></form:input><br><form:errors path="name"></form:errors>
        密码:<form:input path="password"></form:input><form:errors path="password"></form:errors>
        <input type="submit" value="登录">
    </form:form>
</body>
</html>


最重要的一步:springmvc.xml还需要配置

<!-- 基于Validtor验证器 配置 -->
 <bean id="accountValidator" class="club.adger.validator.AccountValidator"></bean>
 <mvc:annotation-driven validator="accountValidator"></mvc:annotation-driven>

浏览器访问测试:http://localhost:8080/validator/login
首先get请求,访问页面,也携带模型数据为空
在这里插入图片描述
发送post请求,校验成功
在这里插入图片描述

JSR-303

使用JSR-303标准进行验证,需要导入依赖的jar文件,这里使用的是Hibernate的Validator
pom.xml

<!-- JSR-303 -->
<dependency>
   <groupId>org.hibernate.validator</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>6.1.5.Final</version>
 </dependency>

 <dependency>
   <groupId>javax.validation</groupId>
   <artifactId>validation-api</artifactId>
   <version>1.1.0.Final</version>
 </dependency>

 <dependency>
   <groupId>org.jboss.logging</groupId>
   <artifactId>jboss-logging</artifactId>
   <version>3.4.1.Final</version>
 </dependency>

通过注解的方式直接在实体类中添加相关的验证规则,person实体类

package club.adger.entity;

import lombok.Data;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/28/14:12
 */
@Data
public class Person {
    
    

    /**
     * 不为空判断
     */
    @NotEmpty(message = "用户名不能为空")
    private String name;

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

ValidatorHandler方法\

 /**
     * 就是模仿数据库
     * @param model
     * @return
     */
    @GetMapping("/register2")
    public String register(Model model){
    
    
        model.addAttribute("person",new Person());
        return "register2";
    }

    @PostMapping("/register2")
    public String register(@Valid Person account, BindingResult result){
    
    
        //是否有错
        if (result.hasErrors()){
    
    
            return "register2";
        }
        return "index";
    }

springmvc.xml配置。因为是基于注解的所有要让注解生效,这个必须单独配置一个,不管上面有没有

<mvc:annotation-driven></mvc:annotation-driven>

浏览器测试访问:http://localhost:8080/validator/register2
在这里插入图片描述
提交之后呢,发现成功

校验规则详解:
@Null 被注解的元素必须为null
@Min(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值
@Email 被注解的元素必须是电子邮箱地址
@Pattern 被注解的元素必须符合对应的正则表达式
@Length 被注解的元素的大小必须在指定的范围内
@NotEmpty 被注解的字符串的值必须非空

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

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

猜你喜欢

转载自blog.csdn.net/qq_45004361/article/details/108246451