SpringMVC学习-1

学习地址

https://www.bilibili.com/video/BV1GE411d7KE
我的代码地址:https://gitee.com/Adger_world/spring

SpringMVC是什么

SpringMVC是目前主流的实现MVC设计模式的框架,是Spring框架的分支项目,以SpringIOC容器为基础,并利用容器的特性简化他的配置,SpringMVC相当于Spring的子模块,可以很好的与Spring结合起来进行开发,是JavaWeb必须要掌握的开发框架

什么是MVC设计模式

MVC设计模式不仅存在于Java应用程序当中,开始是起立于桌面应用程序的,一种软件设计典范

  • Model(模型)用来映射数据库字段。
  • View(视图)用来显示数据。
  • Controller(控制器)服务器端程序的入口

最典型的MVC就是JSP + servlet + javabean的模式,初学者很容易把JSP作为前端技术来讲,其实JSP的本质就是Servlet,是Java Server Page从JSP全名称就可以看出来,属于后端的技术
在这里插入图片描述

SprngMVC核心组件

  • DispatcherServlet
    前置控制器 是整个流程控制的核心,控制其他组件的执行,进行统一调度,降低组件之间的耦合性,核心组件

  • Handler
    处理器,完成具体的业务逻辑,相当于Servlet或者Action

  • HandlerMapping
    DispatcherServlet接受到用户发过来的请求之后,通过HandlerMapping将不同的请求映射到Handler

  • HandlerInterceptor
    处理器,拦截器,是一个接口,如果需要完成一些拦截处理,那么就可以实现这个接口

  • HandlerExcutionChain
    处理器执行链,包括两部分内容,Handler 和 HandlerInterceptor

  • HandlerAdapter 处理器适配器,Handler执行业务方法之前,需要进行一系列的操作,包括表单数据的验证、数据类型的转换、将表单数据封装到JavaBean当中等,这些操作都由HandlerAdapter完成,开发者只需要将注意力集中在业务逻辑的处理上。DispatcherServlet通过HandlerAdapter执行不同的Handler。

  • ModelAndView
    装载了模型数据,和视图信息,作为Handler的处理结果,返回给DispatcherServlet

  • ViewResolver
    试图解析器,DispatcherServlet通过它将逻辑视图解析为物理视图,什么是逻辑视图:ModelAndView的时候还是逻辑试图,最终要渲染能看到的界面,物理视图

SpirngMVC工作流程

在这里插入图片描述

  1. 客户端请求被DispatcherServlet接受
  2. 根据HandlerMapping映射到Handler
  3. 生成Handler和HandlerInteceptor
  4. Handler和HandlerInteceptor以HandlerExcutionChain的形式统一返回给DispatcherServlet
  5. DispatcherServlet通过HandlerAdapter调用Handler的方法完成业务逻辑的处理
  6. Handler返回一个ModelAndView对象给DispatcherServlet
  7. DispatcherServlet将获取的ModelAndView对象传给ViewResolver视图解析器,将逻辑视图解析为物理视图
  8. ViewResolver返回一个view给DispatcherServlet
  9. DispatcherServlet根据View进行视图渲染(将模型数据填充到视图中)
  10. DispatcherServlet将渲染后的结果响应给客户端

SpringMVC的特点

  • 国际化支持 什么是国际化 就是 在页面实现多国语言切换
  • 面向接口编程
  • 分离View层的实现
  • 提供大量的控制器接口和实现类
  • 灵活配置

快速入门

这里使用的是Maven项目构建工具,注意选中骨架就可以了
在这里插入图片描述
在这里插入图片描述
仓库配置,点击Finish就可以了
在这里插入图片描述
等待项目生成
在这里插入图片描述
可以打开工程目录,可以看出,不是满足maven的结构,自己需要手动创建Java文件夹跟resources文件夹,在2020版本的idea中已经优点小变化了,会跟你检测到
在这里插入图片描述
在这里插入图片描述

  • 导入依赖,相当于添加Jar包
<!-- Spring 最新稳定版本-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>
  • 在web.xml中配置DispatcherServlet,这是一个Servlet,所以需要配在web.xml中,在JavaWeb阶段,每写一个servlet,web.xml就有一个servlet的配置对吧
    这里的web.xml头版本是3.1还是几忘记了在这里插入图片描述
    还需要让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名字 -->
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 读取配置文件 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <!-- classpath指的是resources根目录 -->
      <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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 自动扫描 -->
    <context:component-scan base-package="club.adger">

    </context:component-scan>

  <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

建立相同结构的包名
在这里插入图片描述

package club.adger.controller;

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

import java.io.PrintStream;

/**
 * Created with IntelliJ IDEA.
 *  * @Auther: Adger
 * @Date: 2020/08/19/16:37
 * @Controller 交给IOC容器管理,同时具备了控制器的功能
 */
@Controller
public class HelloHandler {
    
    

    @RequestMapping("/index")
    public String index(){
    
    
        final PrintStream out = System.out;
        out.println("执行了index请求...");
        return "index";
    }
}

配置tomcat运行
在这里插入图片描述

SpringMVC注解描述

  • @RequestMapping
    SpringMVC通过@ResquestMapping 注解将URL请求与业务方法映射,在类上可以添加,在方法上也可以添加,在类的定义处添加的话,就相当于客户端(浏览器)多一层访问路径

  • @Controller
    @Controller在类的定义处添加,该类交给IOC容器管理(结合springmvc.xml中的配置自动扫描结合使用),使其成为一个控制器,就可以接受客户端请求了

最基础的配置

package club.adger.controller;

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

import java.io.PrintStream;

/**
 * Created with IntelliJ IDEA.
 *  * @Auther: Adger
 * @Date: 2020/08/19/16:37
 * @Controller 交给IOC容器管理,同时具备了控制器的功能
 */
@Controller
@RequestMapping("/hello")
public class HelloHandler {
    
    

    @RequestMapping("/index")
    public String index(){
    
    
        final PrintStream out = System.out;
        out.println("执行了index请求...");
        return "index";
    }
}
  • @RequestMapping 相关参数
    value指定URL实际请求的地址,是@RequestMapping的默认值
@RequestMapping("/index")
    public String index(){
    
    
        final PrintStream out = System.out;
        out.println("执行了index请求...");
        return "index";
    }

上述写法跟下面一样

@RequestMapping(value = "/index")
    public String index(){
    
    
        final PrintStream out = System.out;
        out.println("执行了index请求...");
        return "index";
    }
  • method:指定请求的method类型。Get、Post、Put、Delete
    只能被Get请求访问,如果去掉Get和post请求都可以接受
@RequestMapping(value = "/index",method = RequestMethod.GET)
   public String index(){
    
    
       final PrintStream out = System.out;
       out.println("执行了index请求...");
       return "index";
   }
  • params:指定请求中必须包含某些参数。否则无法访问
/**
    * params中是多个参数就用 {}
    *
    * @return
    */
   @RequestMapping(value = "/index",method = RequestMethod.GET,params = {
    
    "id","name"})
   public String index(){
    
    
       final PrintStream out = System.out;
       out.println("执行了index请求...");
       return "index";
   }

如果浏览器Get请求没有参数直接访问会出现http状态码400错误
在这里插入图片描述
现在随便给这两个参数值。发现成功
http://localhost:8080/hello/index?id=1&name=Adger
参数名字必须一样。值无所谓
在这里插入图片描述
如果固定死的情况下,值就不能随便填写,比如下面代码的情况。id必须为1

/**
     * params中是多个参数就用 {}
     *
     * @return
     */
    @RequestMapping(value = "/index",method = RequestMethod.GET,params = {
    
    "id=1","name"})
    public String index(){
    
    
        final PrintStream out = System.out;
        out.println("执行了index请求...");
        return "index";
    }

如果id不是1,就发生400错误
在这里插入图片描述
变成1就能访问成功
http://localhost:8080/hello/index?id=1&name=Adger
在这里插入图片描述

但是一般的话不会像上面这么写。而是获取这个从客户端传过来的值

 @RequestMapping(value = "/index",method = RequestMethod.GET,params = {
    
    "id","name"})
    public String index(int id){
    
    
        final PrintStream out = System.out;
        //打印输出id值
        out.println(id);
        out.println("执行了index请求...");
        return "index";
    }

http://localhost:8080/hello/index?id=1&name=Adger
浏览器发送请求,可以看到已经收到并打印出来
在这里插入图片描述
注意浏览器的参数名必须跟java代码中的参数必须一样,不然报错,名字一样的话,SpringMVC会帮你自动装填

如果想要不一样的话,可以加上@RequestParam注解

 @RequestMapping(value = "/index",method = RequestMethod.GET,params = {
    
    "id","name"})
    public String index(@RequestParam("id") int i,@RequestParam("name") String n){
    
    
        final PrintStream out = System.out;
        //打印输出id值和name
        out.println(i);
        out.println(n);
        out.println("执行了index请求...");
        return "index";
    }

客户端发送请求,http://localhost:8080/hello/index?id=1&name=Adger
发现成功
在这里插入图片描述

在这里插入图片描述

SpringMVC支持RESTful风格的URL

什么是RESTful风格的URL

是互联网一种架构的形式,直观的能看出接口请求
传统 HTTP 类型:http://localhost:8080/hello/index?id=1&name=Adger
REST风格类型:http://localhost:8080/hello/index/1/Adger

如下面代码RESTful风格的URL

/**
     * @PathVariable 代表浏览器地址输入 与下面参数 绑定
     * @param id
     * @param name
     * @return
     */
    @RequestMapping("/rest/{id}/{name}")
    public String rest(@PathVariable("id") int id,@PathVariable("name") String name){
    
    
        System.out.println("id"+id+"\t"+name);
        return "index";
    }

测试访问:http://localhost:8080/hello/rest/1/Adger
发现成功
在这里插入图片描述
在这里插入图片描述

SpringMVC映射Cookie

什么是Cookie

就是客户端的一个文本文件,保存了用户的一些私人记录
SpringMVC可以直接取出Cookie,实际开发中用的不多

@RequestMapping("/cookie")
 public String cookie(@CookieValue(value = "JSESSIONID") String sessionId){
    
    
     System.out.println(sessionId);
     return "index";
 }

浏览器访问:http://localhost:8080/hello/cookie
在这里插入图片描述
在这里插入图片描述

SpringMVC绑定JavaBean

SpringMVC会根据请求参数名和JavaBean的属性名进行关联,自动为对象填充属性值,同时支持级联属性,级联属性也就是,对象中的对象比如,Address address

这里新建的一个包,entity,放实体类的,加入lombok简化实体类,当加入字段的时候就不需要重新生成get和set方法和toString了

package club.adger.entity;

import lombok.Data;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/21/20:53
 */
@Data
public class User {
    
    
    private long id;
    private String name;
}

从这里可以看出他的set和get方法等
在这里插入图片描述
编写一个页面

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/21
  Time: 20:59
  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">
    <%-- 注意这里的 name 属性值 不能随便填 必须是 你的实体类的属性名 才能封装到 JavaBean中去 --%>
    用户名id: <input type="text" name="id"><br>
    用户名: <input type="text" name="name"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>

后端入口编写
这里直接写实体类对象

@RequestMapping(value = "/save",method = RequestMethod.POST)
public String save(User user){
    
    
     System.out.println(user);
     return "index";
 }

在这里插入图片描述
发现跳转
在这里插入图片描述
浏览器直接访问页面测试:http://localhost:8080/register.jsp
在这里插入图片描述
这里是没有输入中文的,如果输入中文就会乱码,只需要加一个过滤器就可以了,没有加的情况下测试
在这里插入图片描述
发现乱码
在这里插入图片描述
解决:在web.xml中加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>

重启测试
在这里插入图片描述
发现成功
在这里插入图片描述

级联绑定

新建一个实体类

package club.adger.entity;

import lombok.Data;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/21/21:15
 */
@Data
public class Address {
    
    
    private String address;
}

在这里插入图片描述
在原来的register.jsp中多添加个输入框

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/21
  Time: 20:59
  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">
    <%-- 注意这里的 name 属性值 不能随便填 必须是 你的实体类的属性名 才能封装到 JavaBean中去 --%>
    用户名id: <input type="text" name="id"><br>
    用户名: <input type="text" name="name"><br>
        <%-- 第一个address是 user实体类中的,第二个是 Address对象的 属性值 --%>
    用户地址: <input type="text" name="address.address"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>

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

JSP页面的转发和重定向

转发和重定向是什么:就是页面之间的跳转的两种的不同方式,转发是服务器端跳转,重定向是客户端的跳转,区别:转发地址栏不会改变,重定向地址栏改变,转发是一次请求,重定向是两次请求,转发不会丢失数据,而重定向会

SpringMVC默认是以转发的形式响应jsp的

  • 转发
    新写一个入口
@RequestMapping("/forward")
public String forward(){
    
    
     // 相当于 return "index";
     return "forward:/index.jsp";
 }

浏览器测试访问:http://localhost:8080/hello/forward
在这里插入图片描述
发现地址栏是没有变化的

  • 重定向
    新写一个入口
@RequestMapping("/redirect")
 public String redirect(){
    
    
     //转发跟重定向像 这么 写的话 必须加后最 不然找不到的
     return "redirect:/index.jsp";
 }

浏览器测试访问:http://localhost:8080/hello/redirect
测试发现浏览器地址栏变化
在这里插入图片描述

SpringMVC 数据绑定

数据绑定:在后端的业务方法中直接获取客户端的HTTP请求中的参数,将请求参数映射到业务方法中的形参中
SpringMVC中的数据绑定的工作是由HandlerAdapter来完成的

  • 基本数据类型的绑定
    这段代码
package club.adger.controller;

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

/**
* Created with IntelliJ IDEA.
*
* @Auther: Adger
* @Date: 2020/08/21/21:44
*/
@Controller
@RequestMapping("/data")
public class DataBindHandler {
    
    
   @RequestMapping("/baseType")
   public String baseType(int id){
    
    
       return id+"";
   }
}

这里不希望直接返回jsp页面,而是客户端发过来的请求直接返回id值,这样写的话,直接当成逻辑视图来解析

浏览器测试访问:http://localhost:8080/data/baseType?id=1

发现SpringMVC直接当成逻辑视图解析了
在这里插入图片描述
怎么解决呢,写上@ResponseBody注解

package club.adger.controller;

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

/**
 * Created with IntelliJ IDEA.
 *  * @Auther: Adger
 * @Date: 2020/08/21/21:44
 */
@Controller
@RequestMapping("/data")
public class DataBindHandler {
    
    
    @RequestMapping("/baseType")
    @ResponseBody
    public String baseType(int id){
    
    
        return id+"";
    }
}

浏览器测试访问:http://localhost:8080/data/baseType?id=1
在这里插入图片描述
@RequestBody 表示SpringMVC会直接将业务方法的返回值响应给客户端,如果不加@RequestBody注解,SpringMVC会将业务方法的返回值传递给DispatcherServlet再由DispatcherServlet调用ViewResolver对返回值进行解析,映射到一个jsp资源

  • 包装类
    为什么使用包装类:包装类自带了默认值,就比如下面这种情况,如果什么都不传的话:http://localhost:8080/data/baseType,就会发生500错误

在这里插入图片描述

@RequestMapping("/packageType")
@ResponseBody
 public String packageType(Integer id){
    
    
     return id+"";
 }

浏览器访问测试:http://localhost:8080/data/packageType
在这里插入图片描述
包装类可以接收null,当HTTP请求没有参数时,使用包装类定义形参的数据类型,程序不会抛出异常

下图代码

@RequestMapping("/packageType")
@ResponseBody
 public String packageType(@RequestParam(value = "num",required = false,defaultValue = "0") Integer id){
    
    
     return id+"";
 }

@RequestParam注解里面的属性值解释

  • value
    value="num"代表将HTTP请求中名为num的参数赋给形参id
  • required
    required=true代表必填,false代表不必,
  • defaultValue
    defaultValue = "0"如果HTTP请求中没有参数则默认值为0
数组
@RequestMapping("/array")
@ResponseBody
 public String array(String[] name){
    
    
     String s = Arrays.toString(name);
     return s;
 }

在浏览器输入测试地址:http://localhost:8080/data/array?name=adger&name=wangwu

发现成功
在这里插入图片描述

简化@ResponseBody

从这张图能看出来,如果写一个就需要@ResponseBody,简化如下代码

package club.adger.controller;

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

import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/21/21:44
 */
@RestController
@RequestMapping("/data")
public class DataBindHandler {
    
    
    @RequestMapping("/baseType")
    public String baseType(int id){
    
    
        return id+"";
    }

    @RequestMapping("/packageType")
    public String packageType(@RequestParam(value = "num",required = false,defaultValue = "0") Integer id){
    
    
        return id+"";
    }

    @RequestMapping("/array")
    public String array(String[] name){
    
    
        String s = Arrays.toString(name);
        return s;
    }
}

@RestController:Controller里面的方法都是以Rest形式返回,如果是提供数据的就可以用@RestController,如果需要视图,就不需要用@RestController,简单来说就是@RestController返回了Model,而@Controller返回了ModelAndView

@RestController
@RequestMapping("/data")
public class DataBindHandler {
    
    
    @RequestMapping("/baseType")
    public String baseType(int id){
    
    
        return id+"";
    }
}    

等于

@Controller
@RequestMapping("/data")
public class DataBindHandler {
    
    
    @RequestMapping("/baseType")
    @ResponseBody
    public String baseType(int id){
    
    
        return id+"";
    }
}    
集合

SpirngMVC不支持List类型的直接转换,需要对List类型集合进行包装。

新建一个实体类

package club.adger.entity;

import lombok.Data;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/23/15:12
 */
@Data
public class UserList {
    
    
    private List<User> users;
}

新写一个控制方法

@RequestMapping("/list")
 public String list(UserList userList){
    
    
     StringBuffer stringBuffer = new StringBuffer();
     for (User user:userList.getUsers()) {
    
    
         stringBuffer.append(user);
     }d
     return stringBuffer.toString();
 }

新建一个jsp页面

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/23
  Time: 15:19
  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>
<%-- 这些封装到User对象中去,后台用的UserList参数接受,实体类是List<User> 所以可以这样封装 --%>
    <form action="/data/list" method="post">
        用户1编号: <input type="text" name="users[0].id"><br>
        用户1名称:<input type="text" name="users[0].name"><br>

        用户2编号: <input type="text" name="users[1].id"><br>
        用户2名称:<input type="text" name="users[1].name"><br>

        用户3编号: <input type="text" name="users[2].id"><br>
        用户3名称:<input type="text" name="users[2].name"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

浏览器访问:http://localhost:8080/addList.jsp
输入测试数据提交,有中文发现乱码
在这里插入图片描述

在这里插入图片描述
打个断点调试,发现return 那里还是中文的,那就是服务器端返回前端的时候乱码
在这里插入图片描述
在以前的Web工程能直接使用servlet因为tomcat有,而maven工程是不会依赖
这里用servlet编码响应格式没有效,直接通过配置文件的方式去配
SpringMVC.xmll配置文件改写

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <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"></property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!-- 自动扫描 -->
    <context:component-scan base-package="club.adger">

    </context:component-scan>

    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/"></property>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

重新测试:http://localhost:8080/addList.jsp
发现成功
在这里插入图片描述
处理@ResponseBody中文乱码,可以直接在SpirngMVC配置消息转换器

<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"></property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
map

自定义封装类

package club.adger.entity;

import lombok.Data;

import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: Adger
 * @Date: 2020/08/24/16:37
 */
@Data
public class UserMap {
    
    
    private Map<String,User> users;
}

业务方法

@RequestMapping("/map")
public String map(UserMap userMap){
    
    
    StringBuffer stringBuffer = new StringBuffer();
    // map集合遍历跟List集合不一样 遍历key值
    for (String key : userMap.getUsers().keySet()){
    
    
        User user = userMap.getUsers().get(key);
        stringBuffer.append(user);
    }
    return stringBuffer.toString();
}

Jsp

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/24
  Time: 16:43
  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">
    <%-- 这里[] 中的名字 随便定义 但是 服务器端就必须 按照这种名字来取 --%>
    用户1编号: <input type="text" name="users['a'].id"><br>
    用户1名称:<input type="text" name="users['a'].name"><br>

    用户2编号: <input type="text" name="users['b'].id"><br>
    用户2名称:<input type="text" name="users['b'].name"><br>

    用户3编号: <input type="text" name="users['c'].id"><br>
    用户3名称:<input type="text" name="users['c'].name"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

浏览器测试访问http://localhost:8080/addMap.jsp
注意点:前端的数据类型要和后端的数据类型一致
发现成功
在这里插入图片描述

JSON

客户端发生JSON格式的数据,直接通过SpringMVC绑定到业务方法的形参中
用Ajax发送请求,加上Jquery,我在web-app目录下新建了一个文件夹叫,js,把jquery引入进来
新建一个json.jsp文件

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/24
  Time: 16:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%-- 引入jquery --%>
    <script src="js/jquery.min-3.5.js"></script>
</head>
<body>
    <script>
        $(function () {
    
    
            alert(123)
        })
    </script>
</body>
</html>

启动tomcat测试访问这个页面看jquery环境有没有成功,如果alert就成功,浏览器输入:http://localhost:8080/json.jsp
发现 $ 找不到问题,其实这是SpringMVC拦截了
在这里插入图片描述
前置控制器拦截了所有请求,包括静态资源
在这里插入图片描述
可以在SpringMVC配置文件配置,也可以在web.xml中配置,不由DispatcherServlet控制,交给默认的servlet

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

浏览器再测试访问:http://localhost:8080/json.jsp
发现成功
在这里插入图片描述
发送ajax请求,表单是发送不了的

<%--
  Created by IntelliJ IDEA.
  User: Adger
  Date: 2020/8/24
  Time: 16:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%-- 引入jquery --%>
    <script src="js/jquery.min-3.5.js"></script>
</head>
<body>
    <script>
        /**
         * json数据格式
         */
        $(function () {
    
    
            var user = {
    
    
                "id":1,
                "name":"张三"
            };

            $.ajax({
    
    
                url:"data/json",//地址
                data:JSON.stringify(user),//把user对象转换为json数据格式
                type:"POST",//请求方式
                contentType:"application/json;charset=UTF-8",//因为有 中文设置编码
                dataType:"JSON",//返回的数据格式
                success:function (data) {
    
    
                    alert(data.id + "--" + data.name)
                }
            })
        })
    </script>
</body>
</html>

后台的业务方法

/**
  * 如果你是json数据对象 需要加@RequestBody 一个 是@ResponseBody响应 一个是接受
  * @param user
  * @return
  */
 @RequestMapping("/json")
 public User json(@RequestBody User user){
    
    
     System.out.println(user);
     return user;
 }

浏览器访问测试:http://localhost:8080/json.jsp
发现出错
在这里插入图片描述
后台也没有进入
在这里插入图片描述
借助阿里巴巴的fastJson解析json数据,还需再SpringMVC.xml中配置解析

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.72</version>
 </dependency>

SpringMVC.xml配置,我发现我这个版本的FastJsonHttpMessageConverter已经去掉了![
在这里插入图片描述

 <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"></property>
            </bean>
            <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"></bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

发现数据弹出
在这里插入图片描述
在这里插入图片描述
SpringMVC的json和javaBean的转换需要借助于fastjson

SpringMVC的模型数据解析

SpringMVC很重要的一项工作就是再控制器获取模型数据,并且返回给客户端,也就是在jsp页面展示模型数据,jsp也就是使用el表达式从域对象中获取出来
Jsp的四大作用域内置对象也就是可以直接使用的回顾

  1. pageContext

  2. request

  3. session

  4. application
    上面从小到大,模型数据的绑定是由ViewReslover来玩成的,在实际开发中,我们需要先添加模型数据,在交给ViewResolver来绑定
    SpringMVC提供一下几种方式来添加模型数据

  5. Map

  6. Model

  7. ModelAndView

  8. @SessionAttribute

  9. @ModelAttribute

map

新建一个ViewHandler,业务方法如下

package club.adger.controller;

import club.adger.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

/**
 1. Created with IntelliJ IDEA.
 2.  3. @Auther: Adger
 4. @Date: 2020/08/24/19:47
 5. 因为是视图 所以 用的是Controller 不需要 json数据现在
 */
@Controller
@RequestMapping("/view")
public class ViewHandler {
    
    

    /**
     * 因为 直接 返回 一个视图没什么作用的 需要 放入 map 中 从view 页面 中获取 模型数据
     * @param map
     * @return
     */
    @RequestMapping("/map")
    public String map(Map<String,User> map){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        map.put("user",user);
        return "view";
    }
}

新建一个View.jsp的页面,作为视图

<%--
 Created by IntelliJ IDEA.
 User: Adger
 Date: 2020/8/24
 Time: 19:54
 To change this template use File | Settings | File Templates.
--%>
<%--
   isELIgnored 是否 忽略 el表达式 改为 False
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
   <title>Title</title>
</head>
<body>
${
    
    requestScope.user}
</body>
</html>

浏览器启动测试:http://localhost:8080/view/map
发现成功

在这里插入图片描述

Model

业务方法如下

 @RequestMapping("/model")
    public String model(Model model){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        model.addAttribute("user",user);
        return "view";
    }

视图页面不动,浏览器访问:http://localhost:8080/view/model
在这里插入图片描述

ModelAdnView

业务方法如下

@RequestMapping("/modelAndView")
 public ModelAndView modelAndView(){
    
    
     User user = new User();
     user.setId(1);
     user.setName("Adger");
     ModelAndView modelAndView = new ModelAndView();
     modelAndView.addObject("user",user);
     modelAndView.setViewName("view");
     return modelAndView;
 }

视图还是不变
浏览器访问测试:http://localhost:8080/view/modelAndView
发现成功
在这里插入图片描述
另外一种方式

  @RequestMapping("/modelAndView2")
    public ModelAndView modelAndView2(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("user",user);
        View view = new InternalResourceView("/view.jsp");
        modelAndView.setView(view);
        return modelAndView;
    }

等于上第一个的
浏览器访问测试:http://localhost:8080/view/modelAndView2
在这里插入图片描述
第三种形式,这三种其实都是一样的

  @RequestMapping("/modelAndView3")
    public ModelAndView modelAndView3(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        ModelAndView modelAndView = new ModelAndView("view");
        modelAndView.addObject("user",user);
        return modelAndView;
    }

浏览器访问测试:http://localhost:8080/view/modelAndView3
发现成功
在这里插入图片描述
第四种方式

    @RequestMapping("/modelAndView4")
    public ModelAndView modelAndView4(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        ModelAndView modelAndView = new ModelAndView("view");
        modelAndView.addObject("user",user);
        return modelAndView;
    }

浏览器访问测试:http://localhost:8080/view/modelAndView4
在这里插入图片描述
第五种方式

 @RequestMapping("/modelAndView5")
    public ModelAndView modelAndView5(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        Map<String, User> map = new HashMap<>();
        map.put("user",user);
        ModelAndView modelAndView = new ModelAndView("view",map);
        return modelAndView;
    }

浏览器访问测试:http://localhost:8080/view/modelAndView5
发现成功
在这里插入图片描述
第6种方式

 @RequestMapping("/modelAndView6")
    public ModelAndView modelAndView6(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        Map<String, User> map = new HashMap<>();
        map.put("user",user);
        View view = new InternalResourceView("/view.jsp");
        ModelAndView modelAndView = new ModelAndView(view,map);
        return modelAndView;
    }

浏览器访问测试:http://localhost:8080/view/modelAndView6
发现成功
在这里插入图片描述
第七种方式

 @RequestMapping("/modelAndView7")
    public ModelAndView modelAndView7(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        //后面两个参数是 你到 key value
        ModelAndView modelAndView = new ModelAndView("view","user",user);
        return modelAndView;
    }

浏览器访问测试:http://localhost:8080/view/modelAndView7
在这里插入图片描述
第八种

 @RequestMapping("/modelAndView8")
    public ModelAndView modelAndView8(){
    
    
        User user = new User();
        user.setId(1);
        user.setName("Adger");
        View view = new InternalResourceView("/view.jsp");
        //后面两个参数是 你到 key value
        ModelAndView modelAndView = new ModelAndView(view,"user",user);
        return modelAndView;
    }

浏览器访问测试:http://localhost:8080/view/modelAndView8
在这里插入图片描述

使用原生的方式

先导入servlet-api的依赖

<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
 </dependency>

写后台业务方法

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

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

@ModelAttribute

这个注解的使用方法

  1. 定义一个方法,改方法专门用来返回要填充到模型数据中的对象
  2. 业务方法无需处理数据模型,只需要返回视图
@ModelAttribute
 public User getUser(){
    
    
     User user = new User();
     user.setId(1);
     user.setName("Adger");
     return user;
 }
 
@RequestMapping("/ModelAttribute")
  public String modelAttribute(){
    
    
      return "view";
  }

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

猜你喜欢

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