Spring+SpringMVC+MyBatis-教程、笔记-4

base黑马,视频链接:https://www.bilibili.com/video/BV1WZ4y1P7Bp?t=94.4
此系列文章可以当做视频的配套笔记,也可以当做自学SSM框架的教程。

SpringMVC的请求-获得请求参数-请求参数类型

image.png

SpringMVC的请求-获得请求参数-获得基本类型参数

image.png
image.png

	@RequestMapping(value = "/quick11")
    @ResponseBody //代表不进行页面跳转,以直接响应数据的方式进行回写数据,但是现在的返回值类型又是void,表示不进行数据回写,表示响应体是空的
    public void save11(String username,int age){
        //int age 写成 String age 是没有问题的,客户端请求任何参数都是字符串的形式
        //int age也是可以的 SpringMVC的框架可以帮你进行数据类型的转换
        //String username写成 int username是不可以的,因为不能把一个字符串汉字或者ABC转换成一个数字
        System.out.println(username);
        System.out.println(age);
    }

启动项目进行测试:
image.png
image.png

SpringMVC的请求-获得请求参数-获得POJO类型参数

image.png
image.png
controller层:

	@RequestMapping(value = "/quick12")
    @ResponseBody
    public void save12(User user){
        System.out.println(user);
	}

效果:
image.png
image.png

SpringMVC的请求-获得请求参数-获得数组类型参数

image.png
controller层中的代码:

	@RequestMapping(value = "/quick13")
    @ResponseBody
    public void save13(String[] strs){
        //数组打印的都是地址 list打印的都是值
        System.out.println(Arrays.asList(strs));
    }

image.png
效果:
image.png

SpringMVC的请求-获得请求参数-获得集合类型参数1

image.png
比如,现在准备一个表单,这个表单提交的是某些人的信息。
某些人是多个人,多个人得封装到集合当中。有一个集合,这个集合对应的泛型是User

controller代码1

	@RequestMapping(value = "/quick14")
    @ResponseBody
    public void save14(List<User> userList){
        //但是这样封装是封装不进去的
        //得把List<User> userList 这个集合给包装到对象当中
        //包装到POJO对象当中,这个POJO对象 一般叫做VO对象

    }

创建VO类

package com.lyh.domain;

import java.util.List;

public class VO {
    private List<User> userList;

    public List<User> getUserList() {
        return userList;
    }

    public void setUserList(List<User> userList) {
        this.userList = userList;
    }

    @Override
    public String toString() {
        return "VO{" +
            "userList=" + userList +
            '}';
    }
}

创建form.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>Title</title>
    </head>
    <body>
      <form action="${pageContext.request.contextPath}/user/quick14" method="post">
        <%--        表明是第几个User对象的username、age--%>
          <input type="text" name="userList[0].username"><br>
          <input type="text" name="userList[0].age"><br>
          <input type="text" name="userList[1].username"><br>
          <input type="text" name="userList[1].age"><br>
          <input type="submit" value="提交">
      </form>
    </body>
  </html>

controller层代码:

	@RequestMapping(value = "/quick14")
    @ResponseBody
    public void save14(VO vo){
        System.out.println(vo);
	}

效果:
image.png
image.png

SpringMVC的请求-获得请求参数-获得集合类型参数2

image.png

在webapp目录下面,建立ajax.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--引入jQuery--%>
		<%--!!!!!!!!!!!!!注意引入JS文件不能使用单标签--%>
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>

    <%--当页面一加载的时候,就让它发请求,这个请求发送的数据是JSON格式的数据--%>
    <script>
        var userList = new Array();
        userList.push({username:"zhangsan",age:18});
        userList.push({username:"lisi",age:38});
        $.ajax({
            type:"POST",
            url:"${pageContext.request.contextPath}/user/quick15",
            data:JSON.stringify(userList),
            contentType:"application/json;charset=utf-8"
        });
    </script>
</head>
<body>

</body>
</html>

在webapp目录下建立js目录,把jquery-3.3.1.js文件复制到,建立的js目录下面。

controller层的代码

	@RequestMapping(value = "/quick15")
    @ResponseBody
    public void save15(@RequestBody List<User> userList){
        System.out.println(userList);
    }

测试:在控制台上会报404
image.png
有这个jquery文件夹,但是,是找不到的

在spring-mvc.xml中加入一句话:

<!-- 这行代码写上之后 jquery就可以获取到了-->
<mvc:resources mapping="/js/**" location="/js/"/>

再次访问:
image.png
image.png

SpringMVC的请求-获得请求参数-静态资源访问的开启

controller层中的代码:

	@RequestMapping(value = "/quick15")
    @ResponseBody
    //@RequestBody表示请求体,意味着要把请求体中的内容封装到List<User>这个集合中
    public void save15(@RequestBody List<User> userList){
        System.out.println(userList);
    }

为什么找不到JQuery对应的文件?
原因在前端控制器的配置上。
SpringMVC的整个架构,它的前端控制器是DispatcherServlet。
/,叫做缺省的servlet
意味着客户端发送请求,这个请求到服务端找对应的servlet
找不到,最终这个资源都归,缺省的servlet进行处理
而我在web.xml中所用的都是SpringMVC开发的
内部没有其他的servlet,意味着我都不匹配
最终会找DispatcherServlet
DispatcherServlet 内部要帮你进行一个虚拟路径的匹配
匹配controller层中的@RequestMapping
(会把,jquery-3.3.1.js,这个东西也当成一个@RequestMapping和你进行匹配)
但是没有任何一个资源叫做 jquery-3.3.1.js
所以匹配不上,匹配不上就什么都不会干了。
所以最终的JQuery文件是不能被访问到的。
但是写上**<mvc:resources mapping=“/js/** ** **” location=“/js/”/> **这句话就可以
image.png
spring-mvc.xml中的配置

<!--    在SpringMVC框架当中,要开放对那些资源的访问权限-->
<!--    一般就是一些静态资源-->
<!--    不需要去匹配对应的@RequestMapping了-->
<!--    直接找到对应的静态资源返回就行-->
<!--    mapping代表映射地址,找谁-->
<!--    location表示是哪个目录下面的资源是对外开放的-->
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/img/**" location="/img/"/>

spring-mvc.xml中的配置写上这段话也是可以的

<!--    代表在访问资源时,SpringMVC帮助找@RequestMapping对应的匹配地址-->
<!--    找不到就交给原始的容器,而这里的原始的容器是TomCat-->
<!--    就交给TomCat,让TomCat内部的机制去找静态资源-->
<!--    TomCat是有能力帮你找到静态资源的-->
    <mvc:default-servlet-handler/>
<!--    SpringMVC框架如果帮你找不到对应的资源,就交给原始的容器TomCat-->
<!--    TomCat去帮你找对应的静态资源,帮你返回-->

在上面的基础上再去测试一下:
image.png
也是可以的。

SpringMVC的请求-获得请求参数-配置全局乱码过滤器

服务器使用的是TomCat 8.5的版本
get请求中文本身是不乱码的
post会出现乱码的问题
对于他要进行相应的解决。

使用之前的form表单进行测试,表单的请求方式是post
image.png
现在去访问一下form表单
image.png
后台会出现乱码的情况
image.png
配置过滤器
image.png
把这个filter配置上之后,与此同时指定一个参数encoding
filter内部有一个初始化参数是encoding,这个encoding对应的值就设置编码UTF-8就行。
对所有的资源都要进行一个编码过滤。

在web.xml文件中配置全局过滤字符编码格式的filter

<!--配置全局过滤的filter-->
<filter>
  <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
  <!--    对所有的资源都进行过滤-->
  <url-pattern>/*</url-pattern>
</filter-mapping>

提交测试:
image.png
效果:
image.png

SpringMVC的请求-获得请求参数-参数绑定注解@RequestParam

image.png
controller层的代码:

	@RequestMapping(value = "/quick16")
    @ResponseBody
    public void save16(String username){
        System.out.println(username);
}

地址栏的输入:
image.png

效果:
image.png

但是现在有个问题:如果这里输入的是name
image.png
控制台会输出空
image.png
image.png
controller层的代码:

	@RequestMapping(value = "/quick16")
    @ResponseBody           //这里写客户端在请求时,请求的那个名称
    //将请求的 name参数 给映射到 username上
    //如果当前的参数只有1个,并且当前的参数是value的话,是可以省略掉的
    public void save16(@RequestParam(value = "name") String username){
        System.out.println(username);
    }

地址栏:
image.png
效果:
image.png
image.png

如果地址栏,这样写的话,会报错的。
image.png
会出错,因为在默认的情况下,必须得携带name参数

@RequestMapping(value = "/quick16")
    @ResponseBody           //这里写客户端在请求时,请求的那个名称
    //将请求的 name参数 给映射到 username上
    //如果当前的参数只有1个,并且当前的参数是value的话,是可以省略掉的
    //required = false 意味着在请求时,name属性,不是必须要携带的了
    public void save16(@RequestParam(value = "name",required = false) String username){
        System.out.println(username);
    }

效果:
image.png
此时,不会出错。控制台是 null
image.png

controller层代码:

	@RequestMapping(value = "/quick16")
    @ResponseBody           
    				//defaultValue 是默认值,当没有指定的请求参数时,则使用默认的值
    public void save16(@RequestParam(value = "name",required = false,defaultValue = "Hello,NiHao!!") String username){
        System.out.println(username);
    }

效果:
image.png
image.png

SpringMVC的请求-获得请求参数-Restful风格的参数的获取

并不是以**?**的方式携带数据的。而是把想请求的数据放到url地址内部的。
image.pngimage.png
controller层代码:

	//这里可以用method属性,来设置是用get请求还是用post等的请求方式
	@RequestMapping(value = "/quick17/{username}")
    @ResponseBody
    public void save17(@PathVariable(value ="username")String username){
        System.out.println(username);
    }

效果:
image.png
image.png

SpringMVC的请求-获得请求参数-自定义类型转换器

SpringMVC 本身框架内部具备一些已经定义好的类型转换器。
客户端请求的任何数据到达服务端之后,都是字符串。
但是在封装数据的时候,会发现,方法内部的形参如果是数字的话,也可以正常的封装。
说明SpringMVC这个框架,自动的已经把字符串给转换成了数字,封装到参数上了。
SpringMVC已经具备一些转换器了,但是这些转换器不能满足我们的需求。
image.png
image.png
1、Converter是SpringMVC提供的一个接口,复写它的方法
2、在spring-mvc.xml这个文件中声明转换器
把定义好的转换器配置到转换服务工厂内部就可以了
3、把这个转换服务工厂,交给在其内部引用转换服务工厂。

controller层:

	@RequestMapping(value = "/quick18")
    @ResponseBody
    public void save18(Date date){
        System.out.println(date);
    }

效果:
image.png
image.png
但是我们一般不用 2023/01/02 这种格式,可能用2023-01-02这种格式
image.png
上面的格式会出错。因为格式不匹配。

创建包:com.lyh.converter,在该包中创建 DateConverter类,实现SpringMVC转换器接口Converter<S,T>

package com.lyh.converter;

import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
									//转日期之前的字符串  后面是要转成的格式
public class DateConverter implements Converter<String, Date> {
    @Override     //这个String就是日期字符串
    public Date convert(String dataStr) {
        //将日期的字符串 转换成 正真的日期对象 返回即可
        //在内部可以指定格式,也可以把格式提成配置文件,可以自定义修改
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        //解析 dataStr
        Date date = null;
        try {
            date = format.parse(dataStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

转换完了之后,还是不可以用的,得告诉SpringMVC
在 spring-mvc.xml 中

<!--    声明转换器-->
<!--    其实在这个地方定义的是一个转换器服务的工厂对象-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
  <property name="converters">
    <list>
      <!--                 要自己自定义转换器的全限定名称-->
      <!--                让工厂去帮我们造这个日期转换器的bean-->
      <bean class="com.lyh.converter.DateConverter"></bean>
    </list>
  </property>
</bean>

<!--    mvc的注解驱动-->
<!--    conversion-service 就是 上面起的名字 id="conversionService"-->
<mvc:annotation-driven conversion-service="conversionService"/>
<!--    注册完之后,下次再进行相应的注解扫描的时候 就会使用 指定的转换器 去 完成对应的日期转换-->

测试:
image.png
image.png

SpringMVC的请求-获得请求参数-获得Servlet相关API

image.png
quickMethod16(),这个方法是框架帮忙调用的,方法内的参数都是形参,SpringMVC框架调用方法负责向里面传递实际参数。

controller层:

	@RequestMapping(value = "/quick19")
    @ResponseBody
    //想要一个User,让SpringMVC注入一个User,这样是不行的。SpringMVC注入一些公用的对象
    //这些是TomCat产生,交给SpringMVC的
    public void save19(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        System.out.println(request);
        System.out.println(response);
        System.out.println(session);

    }

效果:
image.png
image.png
看到了catalina,就等价与TomCat。
这三个对象都是TomCat帮你产生的。
只不过传给SpringMVC框架。SpringMVC框架在调用方法的时候,又传递到方法的形参中。

SpringMVC的请求-获得请求参数-获得请求头信息

HTTP请求刨除请求数据之外,还有请求头请求行。
顺序应该是请求行、请求头、请求数据。
请求头键值对的形式,是头的名称头的值
一般情况是根据头的名称去获取对应的值。image.png

controller层:

	@RequestMapping(value = "/quick20")
    @ResponseBody
    public void save20(){

    }

访问quick20,进行抓包
image.png
这里面有请求头响应头。
User-Agent代表当前浏览器的一些信息。

controller层:

	@RequestMapping(value = "/quick20")
    @ResponseBody  //这里的名字得和浏览器抓包请求的agent是一致的   不是必须的
    public void save20(@RequestHeader(value = "User-Agent",required = false) String user_agent){
        System.out.println(user_agent);
    }

效果:
image.pngimage.png
请求头中有一个比较特殊的就是Cookie
image.png
image.png
controller层

	@RequestMapping(value = "/quick21")
    @ResponseBody
    public void save21(@CookieValue(value = "JSESSIONID",required = false) String jsessionId){
        System.out.println(jsessionId);
    }

效果:
image.png
image.png

@RequestHeader 是根据前面的名字获得后面的值
image.png

@CookieValue,是根据JSESSIONID这个名字获得JSESSIONID的值,要更深入一层。
image.png

SpringMVC的请求-文件上传-客户端表单实现

文件上传也属于客户端把数据发送到服务器端,服务器端接收客户端请求的数据。
这个时候接收的数据就不是一个普通的数据了,就是一个文件。

文件上传客户端三要素

  1. 得有一个文件上传项,有一个按钮,一点击就去选择文件。
  2. 这个文件上传项所在的表单得是post的提交方式。
  3. 文件上传项,所在的表单enctype属性,必须是一个多部分表单,不能是原始默认的URL编码方式的。

image.png
webapp文件下创建upload.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>Title</title>
    </head>
    <body>                                                                    <%--文件上传 必须选择 多部分表单形式--%>
      <form action="${pageContext.request.contextPath}/user/quick22" method="post" enctype="multipart/form-data">
        名称<input type="text" name="username"><br>
        文件<input type="file" name="upload"><br>
        <input type="submit" value="提交"><br>
      </form>
    </body>
  </html>

image.png
如果是url编码方式,提交参数的格式都是键值对的形式
key=value & key=value

测试:
image.pngimage.png

SpringMVC的请求-文件上传-文件上传的原理

image.png
像**request.getParameterMap()**等方法都将会失效。
因为 request 在 get 某个方法时,获得的是URL编码方式的那个表单提交。
现在的表单是多部分表单形式,所以这些API都失效了。image.png
多部分表单,包括我整个表单的全部数据。
服务端可以获取这些数据, 因为这些数据都在HTTP请求体当中。
服务端可以获得当前表单的所有数据。
服务端怎么去获取对应的数据?

在web阶段时:
HTTP请求体都在这里,用最原始的java基础可以获取值,获取完之后通过字符串的切割等等相应的操作可以获取对应的数据。
但是太麻烦了
在web阶段学习文件上传时,借助的是Apache的 fileupload这个插件, 这个插件将文件上传对应的API封装的比较完全,操作比较简单。

SpringMVC框架阶段:
但是现在更简单,因为今天用的是SpringMVC框架
SpringMVC底层封装的也是fileupload这个插件。

文件上传的第一步是导入插件对应的坐标。

SpringMVC的请求-文件上传-单文件上传的代码实现1

image.png
web阶段也得导入fileupload 和 io 的坐标。
image.png
pom.xml文件中导入相关的坐标:

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.3</version>
</dependency>

image.png
这个文件上传解析器是Spring提供的一个叫做 CommonsMultipartResolver 这样的一个对象。

在 spring-mvc.xml 中进行相应的配置

<!--    配置文件上传的解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <property name="defaultEncoding" value="UTF-8"/>
  <property name="maxUploadSize" value="500000"/>
  <property name="maxUploadSizePerFile" value="500000"/>
</bean>

image.png

controller层相关代码:

	@RequestMapping(value = "/quick22")
    @ResponseBody
    public void save22(String username, MultipartFile uploadFile){
        System.out.println(username);

        //这里也是先打印一下 先看一下到底是不是空的 如果是空的就没有办法操作其他的了
        //如果不是空的 是对象 才可以对内部取相应的数据
        System.out.println(uploadFile);
    }

效果:
image.png
点击 **提交 **之后的效果:
image.png
说明文件已经上传成功了。

SpringMVC的请求-文件上传-单文件上传的代码实现2

将文件进行保存
就是以指定的名称将文件存到我的服务器的磁盘上

建立一个测试文件夹:D盘下面的MyTest文件夹。
image.png

controller层:

	@RequestMapping(value = "/quick22")
    @ResponseBody
    public void save22(String username, MultipartFile uploadFile) throws IOException {
        System.out.println(username);
        //获得上传文件的名称,肯定找对应的文件对象 uploadFile
        //uploadFile.getName();//这个代表上传文件表单项的名称,就是和uploadFile的对应值
        String originalFilename = uploadFile.getOriginalFilename(); //这个是文件的名称

        //获得完文件的名称了 得把这个文件存到某个位置
        //可以用原始的IO去存
        //但是 uploadFile 这个对象 本身就有相应的方法
        //就将这个文件  转移到哪儿 内部要一个file对象
        uploadFile.transferTo(new File("D:\\MyTest\\"+originalFilename));//加上文件名称
        //这就代表把文件,上传的文件,转移到服务器的某个磁盘上了
    }

效果:image.png
点击 **提交 **按钮

控制台上
image.png

D盘下面的MyTest文件夹
image.png

打开文件后的内容:
image.png

原始文件中的内容:
image.png

SpringMVC的请求-文件上传-多文件上传的代码实现

多文件上传和单文件上传的格式方法是一样的。

upload.jsp 代码:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>                                                                    <%--文件上传 必须选择 多部分表单形式--%>
        <form action="${pageContext.request.contextPath}/user/quick22" method="post" enctype="multipart/form-data">
            名称<input type="text" name="username"><br>
             <%--这里的名字得和conroller层 方法内部相应参数的名字一致--%>
            上传文件1:<input type="file" name="uploadFile"><br>
            上传文件2:<input type="file" name="uploadFile2"><br>
            <input type="submit" value="提交"><br>
        </form>
    </body>
    </html>

controller层代码:

@RequestMapping(value = "/quick22")
    @ResponseBody
    public void save22(String username, MultipartFile uploadFile,MultipartFile uploadFile2) throws IOException {
        System.out.println(username);
        String originalFilename = uploadFile.getOriginalFilename();
        uploadFile.transferTo(new File("D:\\MyTest\\"+originalFilename));

        String originalFilename2 = uploadFile2.getOriginalFilename();
        uploadFile2.transferTo(new File("D:\\MyTest\\"+originalFilename2));
    }

效果:
image.png
image.png

点击提交按钮:
image.png
image.png
image.png
image.png
服务端代码:
image.png
upload.jsp中建一个新的表单

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
  <html>
    <head>
      <title>Title</title>
    </head>
    <body>                                                                    
      <form action="${pageContext.request.contextPath}/user/quick22" method="post" enctype="multipart/form-data">
        名称<input type="text" name="username"><br>
        上传文件1:<input type="file" name="uploadFile"><br>
        上传文件2:<input type="file" name="uploadFile"><br>
        <input type="submit" value="提交"><br>
      </form>

      <form action="${pageContext.request.contextPath}/user/quick22" method="post" enctype="multipart/form-data">
        名称<input type="text" name="username"><br>
        <%--这里的名字得和conroller层 方法内部相应参数的名字一致--%>
          上传文件1:<input type="file" name="uploadFile"><br>
          上传文件2:<input type="file" name="uploadFile2"><br>
          <input type="submit" value="提交"><br>
      </form>

    </body>
  </html>

controller层:

    @RequestMapping(value = "/quick23")
    @ResponseBody                       //有多个就是数组
    public void save23(String username, MultipartFile[] uploadFile) throws IOException {
        System.out.println(username);
        for (MultipartFile multipartFile : uploadFile) {
            String originalFilename = multipartFile.getOriginalFilename();
            multipartFile.transferTo(new File("D:\\MyTest\\"+originalFilename));
        }
    }

效果:
image.png
点击 **提交 **按钮
image.png

SpringMVC的请求-知识要点

image.png
SpringMVC作为web层的框架,最主要的工作是获得客户端的请求,最终给客户端进行响应。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值