SpringMVC(一)基础入门看这篇

一、SpringMVC的基本概念

1.1 关于三层架构和MVC

  • 三层架构
      开发架构一般都是基于两种形式,一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就是浏览器服务器。在JavaEE开发中,几乎都是基于B/S架构的开发。那么在 B/S架构中,系统标准的三层架构 包括:表现层、业务层、持久层。
      表现层:也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果。表现层的设计一般都使用 MVC 模型。
      业务层:也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。
      持久层:也就是我们是常说的 dao 层。是数据库的主要操控系统,实现数据的增加、删除、修改、查询等操作,并将操作结果反馈到业务逻辑层
  • MVC模型
      MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写, 是一种用于设计创建Web 应用程序表现层的模式。
      Model(模型):通常指的就是我们的数据模型。作用一般情况下用于封装数据。
      View(视图):通常指的就是我们的 jsp 或者 html。作用一般就是展示数据的。通常视图是依据模型数据创建的。
      Controller(控制器):是应用程序中处理用户交互的部分。作用一般就是处理程序逻辑的。

1.2 SpringMVC概述

1.2.1 SpringMVC是什么

  1. 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架。
   2. Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供 了构建 Web 应用程序的全功能 MVC 模块。
  3. 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的 SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。

1.2.2 SpringMVC在三层架构的位置

在这里插入图片描述

1.2.3 SpringMVC的优势
  1. 清晰的角色划分: 控制器(controller)、验证器(validator)、命令对象(command obect)、表单对象(form object)、模型对象(model object)、Servlet分发器(DispatcherServlet)、处理器映射(handler mapping)、试图解析器(view resoler)等等。每一个角色都可以由一个专门的对象来实现。
  2. 分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。
  3. 由于命令对象就是一个 POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
  4. 和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。
  5. 可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。
  6. 可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。
  7. 功能强大的数据验证、格式化、绑定机制。
  8. 强大的 JSP 标签库,使 JSP 编写更容易。
  9. 本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
1.2.4 SpringMVC 和 Struts2 的优略分析

共同点:
    它们都是表现层框架,都是基于 MVC 模型编写的。
    它们的底层都离不开原始 ServletAPI。
    它们处理请求的机制都是一个核心控制器。
区别:
  Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter 。
  Spring MVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。
  Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便 。
  Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提 升,尤其是 struts2 的表单标签,远没有 html 执行效率高。

二、SpringMVC入门案例

2.1 入门案例

  1. 创建WEB工程,引入开发的jar包,下面是pom.xml文件
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!--解决创建maven项目默认jdk版本是1.5 的问题-->
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <!-- 版本锁定 -->
    <spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
</dependencies>
  1. 在web.xml中配置核心控制器DispatcherServlet
  <!--springmvc的核心控制器-->
<servlet>
	<servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>
    	org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
	<!-- 配置Servlet的初始化参数,读取springmvc的配置文件,创建spring容器-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--配置servlet启动时加载对象-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  1. 在resources目录下,编写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">

    <!--配置spring创建容器时要扫描的包-->
    <context:component-scan base-package="com.wink"/>
    <!--配置视图解析器-->
    <bean id="internalResourceViewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"></property><!--文件所在的目录-->
        <property name="suffix" value=".jsp"></property><!--文件的后缀名-->
    </bean>
    <!--配置spring开启注解mvc的支持-->
    <mvc:annotation-driven />
</beans>
  1. 编写index.jsp和HelloController控制器类,在WEB-INF目录下创建success.jsp

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
	<body>
	    <a href="hello">01—入门案例</a><br/>
	</body>
</html>

HelloController.java

@Controller
public class HelloController {
    @RequestMapping(path = "/hello")
    public String sayHello(){
        System.out.println("Hello SpringMVC");
        return "success";
    }

success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
	<body>
	    <h1>入门成功</h1>
	</body>
</html>

启动Tomcat服务器,运行
在这里插入图片描述

2.2 案例分析

在这里插入图片描述

  • 案例的执行流程
  1. 当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象, 就会加载springmvc.xml配置文件
  2. 开启了注解扫描,那么HelloController对象就会被创建
  3. 从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解 找到执行的具体方法
  4. 根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件 5. Tomcat服务器渲染页面,做出响应
  • SpringMVC执行原理图
    在这里插入图片描述

2.3 五大核心组件

DispatcherServlet:前端控制器
  用户请求到达前端控制器,它就相当于 mvc 模式中的 c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet 的存在降低了组件之间的耦合性。
Handler:处理器
  它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由 Handler 对具体的用户请求进行处理
HandlerMapping:处理器映射器
  HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的 映射方式,例如:配置文件方式,实现接口方式,注解方式等。
HandlerAdapter:处理器适配器
  通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理 器进行执行。

View Resolver:视图解析器
  View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名 即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
< mvc:annotation-driven>说明
  在 SpringMVC 的各个组件中,处理器映射器、处理器适配器、视图解析器称为 SpringMVC 的三大组件。
  使用< mvc:annotation-driven> 自动加载 处理映射器处理适配器,可用在SpringMVC.xml 配置文件中替代注解处理器和适配器的配置。

2.4 RequestMapping注解

  1. RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系
  2. RequestMapping注解可以作用在方法和类上
      作用在类上:第一级的访问目录 ,此处不写的话,就相当于应用的根目录。写的话需要以/开头
      作用在方法上:第二级的访问目录
      细节:${ pageContext.request.contextPath }也可以省略不写,但是路径上不能写 /
  3. 属性
      value:用于指定请求的 URL。它和 path 属性的作用是一样的。
       method:用于指定请求的方式。
       params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和 配置的一模一样。
       例如:
       params = {“accountName”},表示请求参数必须有 accountName
       params = {“moeny!100”},表示请求参数中 money 不能是 100。
       headers:用于指定限制请求消息头的条件。

2.5 Controller注解

   在 Spring MVC 中使用 Controller 注解类型声明某类的实例是一个控制器。例如:

@Controller
public class testController{
 // 处理请求的方法
}

@Controller表示 testController的实例是一个控制器
@Controller相当于@Controller(value="@Controller")
   在 Spring MVC 中使用扫描机制找到应用中所有基于注解的控制器类,所以,为了让控制器类被 Spring MVC 框架扫描到,需要在配置文件中声明 spring-context,并使用 <context:component-scan/> 元素指定控制器类的基本包

  <!-- 使用扫描机制扫描控制器类,控制器类都在controller包及其子包下 -->
    <context:component-scan base-package="controller" />
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

三、请求参数的绑定

3.1 绑定说明

   SpringMVC 绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。 要求:提交表单的name和参数的名称是相同的

//例如:<a href="account/findAccount?accountId=6">查询账户</a> 
//		参数为accountId=6
 @RequestMapping("/findAccount")  
 public String findAccount(Integer accountId) {
	System.out.println(accountId);   
 	return "success";  
} 

3.2 支持的数据类型

  • 基本类型参数:包括基本类型和String类型
  • POJO类型参数:包括实体类,以及关联的实体类
  • 数组和集合类型参数:包括list和map结构分集合(包括数组)

3.3 使用要求

  • 如果是基本类型或者 String类型:
    要求我们的参数名称必须和控制器中方法的形参名称保持一致。(严格区分大小写)

  • 如果是 POJO类型,或者它的关联对象:
    要求表单中参数名称和 POJO 类的属性名称保持一致。并且控制器方法的参数类型是 POJO 类型。比如: 对象.属性,user.name

  • 如果是集合类型,有两种方式:
    第一种: 要求集合类型的请求参数必须在 POJO 中。在表单中请求参数名称要和 POJO 中集合属性名称相同。
       给 List 集合中的元素赋值,使用下标。如:list[0].uname
       给 Map 集合中的元素赋值,使用键值对。 如:map[‘user’].uname
    第二种: 接收的请求参数是 json 格式数据。需要借助一个注解实现。

3.4 请求参数乱码问题

springmvc解决中文乱码

3.5 自定义类型转换器

有时候需要转换的类型不属于基本类型,比如:Date类型,需要定义自定义类型转换器实现转换

  • 首先,定义一个类,实现Converter接口,该接口有两个泛型
public interface Converter<S, T> {//S:表示接受的类型,T:表示目标类型  
	@Nullable  
  	T convert(S source);
}
/***************************************************************/
//自定义类型转换器
public class StringToDate implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
        if(source == null){
            throw new RuntimeException("请您传入数据");
        }
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return df.parse(source);
        } catch (ParseException e) {
            throw new RuntimeException("数据类型转换出现错误");
        }
    }
}
  • 接着,在spring配置文件(springmvc.xml)中配置类型转换器
    spring 配置类型转换器的机制是,将自定义的转换器注册到类型转换服务中去。
    <!--配置类型转换器工厂-->
    <bean id="conversionService"     
    	class="org.springframework.context.support.ConversionServiceFactoryBean">
    	<!-- 给工厂注入一个新的类型转换器 --> 
        <property name="converters">
            <array>
                <bean class="com.wink.utils.StringToDate"></bean>
            </array>
        </property>
    </bean>
  • 最后,在spring配置文件的annotation-driven标签中引用配置的类型转换服务
    <mvc:annotation-driven conversion-service="conversionService"/>

定义User类

public class User implements Serializable {
    private String uname;
    private Integer age;
    private Date birthday;
    }

ParamController.java

@Controller
public class ParamController {
    @RequestMapping("/saveuser")
    public String user(User user){
        System.out.println(user);
        return "success";
    }
}

param.jsp,添加一个表单,实现参数绑定

<form action="/saveuser" method="post">
    用户姓名:<input type="text" name="uname"/><br/>
    用户年龄:<input type="text" name="age"/><br/>
    用户生日:<input type="text" name="birthday"/><br/>
    <input type="submit" value="提交"/>
</form>

可以看到运行结果,Date类型传参也可以实现
在这里插入图片描述

四、常用注解

4.1 RequestParam

作用:
  把请求中指定名称的参数给控制器中的形参赋值。
属性:
   value:请求参数中的名称。
   required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错。
示例:

<!--jsp中的代码:-->
<a href="anno/testRequestParam?uname=haha">01_RequestParam注解</a>

控制器中的代码:

    @RequestMapping("/testRequestParam")
    //name的值为anno.jsp的参数名称uname
    public String testRequestParam(@RequestParam(name="uname") String username){
        System.out.println("RequestParam执行了");
        System.out.println(username);
        return "success";
    }

4.2 RequestBody

作用:
  用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。
  get 请求方式不适用。
属性:
  required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值 为 false,get 请求得到是 null。
示例:

<!--post请求jsp代码-->
<form action="/anno/testRequestBody" method="post">
	用户名称:<input type="text" name="username" ><br/>
	用户密码:<input type="text" name="password" ><br/>
	用户年龄:<input type="text" name="age" ><br/>
	<input type="submit" value="保存">
</form>

<!--get请求jsp代码-->
<a href="/anno/testRequestBody?body=test">02_RequestBody注解get请求</a>

控制器中的代码:

    @RequestMapping("/testRequestBody")
    public String testRequestBody(@RequestBody(required = false) String body){
        System.out.println("RequestBody执行了");
        System.out.println(body);
        return "success";
    }

4.3 PathVariable

作用:
  用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。
  url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。
属性:
  value:用于指定 url 中占位符名称。
  required:是否必须提供占位符。
示例:

<!--jsp中的代码-->
<a href="/anno/testPathVariable/100">03_PathVariable注解</a>

控制器中的代码:

    @RequestMapping("/testPathVariable/{uid}")
    public String testPathVariable(@PathVariable("uid") Integer id){
        System.out.println("PathVariable执行了");
        System.out.println(id);
        return "success";
    }

4.4 RequestHeader

作用:
  用于获取请求消息头。
属性:
  value:提供消息头名称
  required:是否必须有此消息头
  注: 在实际开发中一般不怎么用。
示例:

<!--jsp中的代码:-->
<a href="/anno/testRequestHeader">04_RequestHeader注解</a>

控制器中的代码:

    @RequestMapping("/testRequestHeader")
    public String testRequestHeader(@RequestHeader(value = "Accept")String requestHeader){
        System.out.println("RequestHeader执行了");
        System.out.println(requestHeader);
        return "success";
    }

4.5 CookieValue

作用:
  用于把指定 cookie 名称的值传入控制器方法参数。
属性:
  value:指定 cookie 的名称。
  required:是否必须有此 cookie。
示例:

<!--jsp中的代码-->
<a href="/anno/testCookieValue">05_CookieValue注解</a>

控制器中的代码:

    @RequestMapping("/testCookieValue")
    public String testCookieValue(@CookieValue(value = "JSESSIONID",required=false) String cookieValue){
        System.out.println("CookieValue执行了");
        System.out.println(cookieValue);
        return "success";
    }

4.6 ModelAttribute

作用:
  它可以用于修饰方法和参数。
  出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
  出现在参数上,获取指定的数据给参数赋值。
属性:
  value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。
应用场景:
  当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
示例:

<!--jsp中的代码-->
<form action="/anno/testModelAttribute" method="post">
	用户名称:<input type="text" name="uname" ><br/>
	<%--用户密码:<input type="text" name="password" ><br/>--%>
	用户年龄:<input type="text" name="age" ><br/>
	<input type="submit" value="保存">
</form>

控制器中的代码:

    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("abc") User user){
        System.out.println("执行了testModelAttribute");
        System.out.println(user);
        return "success";
    }
    //基于 Map 的应用场景示例 1:ModelAttribute 修饰方法不带返回值
    //该方法会先执行
    @ModelAttribute
    public void showModel(String uname, Map<String,User> map){
        System.out.println("执行了 showModel 方法");
        User user = new User();
        user.setUname(uname);
        user.setAge(22);
        user.setBirthday(new Date());
        map.put("abc",user);
    }

4.7 SeesionAttribute

作用:
  用于多次执行控制器方法间的参数共享。
属性:
  value:用于指定存入的属性名称
  type:用于指定存入的数据类型。
示例:

<!--jsp中的代码-->
<a href="anno/testPut">存入 SessionAttribute</a>
<a href="anno/testGet">取出 SessionAttribute</a>
<a href="anno/testClean">清除 SessionAttribute</a>

控制器中的代码:

    @RequestMapping("/testPut")
    public String testPut(Model model){
        //会存到request域对象中
        model.addAttribute("msg","啊啊啊");
        return "success";
    }
    @RequestMapping("/testGet")
    public String testGet(ModelMap modelMap){
        String msg = (String)modelMap.get("msg");
        System.out.println(msg);
        return "success";
    }
    @RequestMapping("/testClean")
    public String testClean(SessionStatus sessionStatus){
        sessionStatus.setComplete();
        return "success";
    }
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值