SpringMVC(一)

1. SpringMVC介绍

MVC模型

MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种用于设计创建 Web 应用程序的模式。主要目的就是为了分离Model模型和View视图,将数据的展示和数据的存储分离,核心是控制器,降低代码的耦合度,不同于三层架构。

序号MVC职责
1Model(模型)存储数据:JavaBean 与数据库进行交互
2View(视图)展示数据:JSP+JSTL+EL HTML
3Controller(控制器)控制器的三大作用: 1. 获取用户提交的数据 2. 调用业务层,获取Model中数据 3. 控制哪个页面或数据显示给用户

 

SpringMVC是什么

SpringMVC 是一种基于 MVC 设计模型的请求驱动类型的轻量级 Web 框架, 属于 Spring框架的后续产品。 Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。

SpringMVC 已经成为目前最主流的 MVC 框架之一, 从 Spring3.0 的发布, 就已全面超越 Struts2,成为最优秀的 MVC 框架。它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful 编程风格的请求。

2. SpringMVC的配置

步骤

1. 创建maven工程

2. 使用插件转换成web工程

3.添加pom.xml文件中依赖

<dependencies>
    <!-- 会间接依赖spring-context, spring-web等 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
</dependencies>

4.准备页面:在pages目录下创建/success.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>成功</title>
</head>
<body>
<h2>操作成功</h2>
</body>
</html>

5.创建控制器:com.it.controller.HelloController

  1. 在类上添加@Controller注解

  2. 创建方法public String hello()

  3. 在方法上添加@RequestMapping("hello.do")注解

  4. 方法中返回"success"字符串

添加配置

springMVC.xml

在resources目录下创建此XML文件

配置以下内容

  1. 开启注解扫描, 识别Controller控制器所在的包

  2. 配置视图解析器

    1. 控制器返回字符串的路径前缀

    2. 控制器返回字符串的路径后缀

  3. 开启SpringMVC注解驱动

    注:使用annotation-driven时,不要错选成cache命名空间,应该使用mvc的命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--1. 指定扫描基包:只扫描controller所在的包-->
    <context:component-scan base-package="com.it.controller"/>

    <!--2. 指定视图解析器,用来将逻辑地址转换成物理地址 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置拼接地址的前缀 -->
        <property name="prefix" value="/pages/"/>
        <!-- 配置拼接地址的后缀 -->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--3. 指定mvc注解的驱动,注:不要选错了-->
    <mvc:annotation-driven/>
</beans>

web.xml

  1. 配置DispatcherServlet(前端控制器)

    1. 创建Spring容器加载的配置名称contextConfigLocation

    2. 创建Spring容器加载的配置文件classpath:springMVC.xml 默认加载的是/WEB-INF/servlet名字-servlet.xml这个配置文件

    3. 配置servlet加载顺序load-on-startup为1

  2. 配置dispatcherServlet请求路径的拦截,拦截所有的*.do请求

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

    <!-- 前端控制器,配置Servlet -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 读取springMVC.xml配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>
        <!-- 在web容器启动的时候加载 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--所有*.do的访问地址都会由这个Servlet来处理-->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

在tomcat中部署运行

在浏览器中输入http://localhost:8080/hello.do

SpringMVC的执行流程分析

3.SpringMVC:三大组件

DispatcherServlet:前端控制器

用户请求到达前端控制器,它就相当于MVC模式中的C,dispatcherServlet是整个流程控制的中心(处理*.do的请求),由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。

org.springframework.web.servlet.DispatcherServlet

HandlerMapping:处理器映射器

HandlerMapping负责根据用户请求url找到处理器中的方法 (hello.do --> HelloController中hello())

SpringMVC提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

具体的实现类是:RequestMappingHandlerMapping

 

处理器

也叫后端控制器,就是我们写的Controller类

是DispatcherServlet前端控制器的实际处理器(HelloController),对具体的用户请求进行处理。

HandlerAdapter:处理器适配器

通过HandlerAdapter对处理器执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

因为不同的处理器有不同的实现方式,有注解的方式实现的,有配置文件的实现的。我们需要统一的适配器来处理它们。就好比生活中不同的设备有统一的USB接口一样。

ViewResolver:视图解析器

ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。(前缀+返回字符串+后缀)

具体实现类:InternalResourceViewResolver,根据处理器适配器执行的结果,由视图解析器渲染页面结果。

4. @RequestMapping注解使用

@RequestMapping的作用

作用

用来设置处理器中一个方法的访问地址

出现位置

用在方法和类上面

  • 类:相当于一个模块的访问地址 /order

  • 方法:指定这个方法的访问地址 /save

完整的访问地址: /模块地址/方法地址,如:/order/save

@Controller
@RequestMapping("/student")  //模块访问地址
public class Demo1StudentController {

    /**
     * 方法访问地址
     * @RequestMapping 属性:
     *  1. path指定访问地址,同义词是value
     *  2. method 限制请求的方法:GET或POST。如果被限制会出现405错误
     *  3. param 限制提交的参数:
     *      3.1) {"id","name"} 必须有这两个参数的名字,否则会出现400错误
     *      3.2) {"id=1","name=newboy"} 不但要有这些参数,而且值还有限制
     *      3.3) {"id!=1"} id不等于1的值都可以
     */
    @RequestMapping(path = "/save", method = RequestMethod.GET, params = {"id!=1"})
    public String save() {
        System.out.println("保存学生");
        return "success";
    }

}

5. 参数绑定:Servlet对象作为参数

步骤

  1. pom.xml中添加servlet的依赖

  2. 在控制器类中编写方法

  3. 使用Servlet对象做参数方法的参数

pom.xml

 

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

HttpServletRequest和HttpSession

需求

通过request,获取请求的参数数据

通过session,获取和保存会话域数据

步骤

  1. 创建String study()方法,访问地址设置为study

  2. 输出:调用学习方法

  3. 使用request对象获取浏览器提交的name参数值

  4. 将获取的值放在请求域中

  5. 在pages目录下创建student.jsp文件

  6. 跳转到student.jsp,使用EL在页面上显示

HttpServletResponse

需求

在方法中得到响应对象,并且使用

步骤

  1. 创建public void eat()方法,没有返回值,抛出IOException

  2. 设置访问地址为eat

  3. 方法使用HttpServletResponse对象做为参数

  4. 使用response设置响应类型,得到打印流

  5. 在浏览器上输出字符串

代码

/**
 * 请求对象,会话对象可以直接使用
 */
@RequestMapping("/study")
public String study(HttpServletRequest request, HttpSession session) {
    String id = request.getParameter("id");
    request.setAttribute("id",id);
    //直接使用会话域
    session.setAttribute("name", "张三");
    return "success";
}

/**
 * 响应对象
 */
@RequestMapping("/eat")
public void eat(HttpServletResponse response) throws IOException {
    System.out.println("调用了吃的方法");
    response.sendRedirect("/pages/success.jsp");
}

JSP

请求域中值:${requestScope.id} <hr/>
会话域中值:${sessionScope.name} <hr/>

 

6. 键值对类型的参数绑定

Map/Model/ModelMap

介绍

  • Model是一个接口,ModelMap是一个类,都用于封装响应的模型数据。

  • 使用Model和使用ModelMap,效果是一样的,它们使用的是相同的子类,两者没有继承关系。

  • 使用Model封装响应的模型数据,页面视图可以返回字符串类型。

步骤

使用Map

  1. 创建方法String sport(Map<String,Object> map)

  2. 调用map的put()方法向请求域中添加键和值

  3. 返回字符串

  4. 在student.jsp页面上显示出来

 

使用Model

  1. 创建方法String swim(Model model),方法参数是Model

  2. 调用model的addAttribute()方法向请求域中添加键和值

  3. 返回字符串

  4. 在student.jsp页面上显示出来

使用ModelMap

  1. 创建方法String draw(ModelMap map),方法参数是ModelMap

  2. 调用map的addAttribute()方法向请求域中添加键和值

  3. 返回字符串

  4. 在student.jsp页面上显示出来

/**
 * 绑定Map对象,如果向Map中添加键和值,就相当于向请求域中添加了键和值,降低了与Servlet对象的耦合度
 * 可以使用Map, Model, ModelMap
 */
@RequestMapping("/sport")
public String sport(Map<String,Object> map) {
    map.put("id", 100);
    map.put("name", "李四");
    System.out.println(map);
    return "success";
}

@RequestMapping("/swim")
public String swim(Model model) {
    //支持链式写法,可以添加多个键和值。也是添加到请求域中
    model.addAttribute("id", 200).addAttribute("name", "孙悟空");
    return "success";
}

@RequestMapping("/draw")
public String draw(ModelMap model) {
    //支持链式写法,可以添加多个键和值。也是添加到请求域中
    model.addAttribute("id", 300).addAttribute("name", "猪八戒");
    return "success";
}

7. 参数绑定:简单类型

/**
 * 参数的绑定
 */
@Controller
@RequestMapping("/user")
public class Demo2UserController {

    /**
     * 简单类型可以直接封装到方法中去
     * @param id 建议使用包装类型,如果没有值就为NULL,否则会出现500错误,会尝试将一个null转成int
     */
    @RequestMapping("/save")
    public String save(Integer id, String name) {
        System.out.println("保存用户id: " + id + ",name: " + name);
        return "success";
    }
}

访问地址

http://localhost:8080/user/save.do?id=1&name=xiaoming

结果

保存用户id: 1,name: xiaoming

8. 参数绑定:参数乱码问题

解决方案

Spring提供了统一的编码过滤器CharacterEncodingFilter,解决提交数据中文乱码问题。

  • 在web.xml中配置spring提供的CharacterEncodingFilter过滤器
  1. 指定初始参数名为:encoding,参数值为:utf-8

  2. 过滤地址为/*

CharacterEncodingFilter配置

<!-- 配置spring写的汉字乱码的过滤器 -->
<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>

9. 参数绑定:对象类型

POJO对象

要求

请求参数名称一定要和POJO对象的属性名一致

@RequestMapping("/update")
public String update(User user) {
    //会自动封装对象所有的属性值
    System.out.println(user);
    return "success";
}

10.参数绑定:简单类型的数组和集合

访问地址:

http://localhost:8080/user/delete.do?id=5&id=10&id=20

http://localhost:8080/user/list.do?id=5&id=10&id=20

处理器方法:

@RequestMapping("/delete")
public String delete(Integer[] id) {
    System.out.println(Arrays.toString(id));
    return "success";
}

/**
 * @RequestParam添加到方法的参数上
 */
@RequestMapping("/list")
public String list(@RequestParam ArrayList<Integer> id) {
    System.out.println(id);
    return "success";
}

1.给数组参数能否直接绑定值?

可以,只要参数名相同就可以了

2.给集合参数能否直接绑定值?

不可以,需要指定@RequestParam注解放在方法的形参前面

11. 参数绑定:POJO对象中的集合属性

代码

  • Address

@Data
public class Address {
    // 用户地址 - 省份
    private String province;
    // 用户地址 - 城市
    private String city;
}  
  • User
@Data
public class User {
    private Integer id;
    private String name;

    private Address address; //POJO类

    private List<String> hobby;  //字符串集合

    private List<Address> addressList;  //POJO类集合
  
  	private Map<String, Address> map;  //Map集合

}
  • 控制器方法
@RequestMapping("/update")
public String update(User user) {
    //会自动封装对象所有的属性值
    System.out.println(user);
    return "success";
}
  • 页面代码
<h2>包装类的封装</h2>
<form action="user/update.do" method="post">
    <input type="text" name="id" value="1"> <br/>
    <input type="text" name="name" value="白骨精"> <br/>
    省:
    <input type="text" name="address.province" value="广东"> <br/>
    市:
    <input type="text" name="address.city" value="广州"> <br/>
    爱好:
    <input type="checkbox" name="hobby" value="游泳">游泳
    <input type="checkbox" name="hobby" value="上网">上网
    <input type="checkbox" name="hobby" value="下棋">下棋 <hr/>
    其它地址:<br/>
    <input type="text" name="addressList[0].province" value="湖南省">
    <input type="text" name="addressList[0].city" value="长沙"> <br/>
    <input type="text" name="addressList[1].province" value="广西省">
    <input type="text" name="addressList[1].city" value="柳州"> <br/>
    Map集合:<br/>
    <input type="text" name="map['hn'].province" value="湖南省">
    <input type="text" name="map['hn'].city" value="长沙"> <br/>
    <input type="text" name="map['gx'].province" value="广西省">
    <input type="text" name="map['gx'].city" value="柳州"> <br/>
    <input type="submit" value="提交">
</form>

12. 参数相关的注解:@RequestParam

@RequestParam注解

  1. 作用:放在方法的参数前面,用于提交的参数名与方法的形参不同的情况

  2. 如果没有提供参数:

    1. int基本数据类型: 如果没有赋值会出现500

    2. Integer包装数据类型: 如果没有赋值会为NULL

/**
 * required 属性
 *  默认是true,表示这个参数必须要有,如果没有提供报400
 *  设置成false,没有就为null
 *  defaultValue 属性:
 *    如果没有指定值,默认是NULL,可以给它指定一个默认值
 */
@RequestMapping("/find")
public String find(@RequestParam(name = "name", required = false, defaultValue = "Boy") String username) {
    System.out.println("用户名:" + username);
    return "success";
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值