SpringMVC简介

Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据、业务与展现进行分离(解耦合)
从这样一个角度来说,Spring MVC和Struts、Struts2非常类似,都属于表现层的框架.
同时它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来

image.png

Web MVC设计模式

MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
MVC可对程序的后期维护和扩展提供了方便,并且使程序某些部分的重用提供了方便。而且MVC也使程序简化,更加直观。

  • 控制器Controller:对请求进行处理,负责请求转发;(Servlet)
  • 视图View:界面设计人员进行图形界面设计;(jsp)
  • 模型Model:程序编写程序应用的功能(实现算法等等)、数据库管理;(javabean,jdbc,javase)

注意,MVC不是Java的东西,几乎现在所有B/S结构的软件都采用了MVC设计模式。

Spring web mvc 架构

架构图

image.png

image.png

image.png

架构流程

1、 用户发送请求至前端控制器DispatcherServlet
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、 执行处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、 ViewReslover解析后返回具体View
10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户

组件说明

以下组件通常使用框架提供实现:

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

HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,注解方式等。

Handler:处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。

HandlAdapter:处理器适配器

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

View Resolver:视图解析器

View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。

一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。

SpringMVC入门程序

需求

`通过springmvc从控制层返回信息到view视图层

第一步:建立一个Web项目

第二步:导入spring4.3.3的jar包

通过maven依赖包:

  1. <!-- spring mvc -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-webmvc</artifactId>
  5. <version>4.3.3.RELEASE</version>
  6. </dependency>
  7. <!-- spring4 -->
  8. <dependency>
  9. <groupId>org.springframework</groupId>
  10. <artifactId>spring-core</artifactId>
  11. <version>4.3.3.RELEASE</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.springframework</groupId>
  15. <artifactId>spring-context</artifactId>
  16. <version>4.3.3.RELEASE</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.springframework</groupId>
  20. <artifactId>spring-jdbc</artifactId>
  21. <version>4.3.3.RELEASE</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.aspectj</groupId>
  25. <artifactId>aspectjweaver</artifactId>
  26. <version>1.7.3</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework</groupId>
  30. <artifactId>spring-beans</artifactId>
  31. <version>4.3.3.RELEASE</version>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.springframework</groupId>
  35. <artifactId>spring-web</artifactId>
  36. <version>4.3.3.RELEASE</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.springframework</groupId>
  40. <artifactId>spring-expression</artifactId>
  41. <version>4.3.3.RELEASE</version>
  42. </dependency>
  43. <dependency>
  44. <groupId>org.springframework</groupId>
  45. <artifactId>spring-orm</artifactId>
  46. <version>4.3.3.RELEASE</version>
  47. </dependency>
  48. <dependency>
  49. <groupId>org.springframework</groupId>
  50. <artifactId>spring-test</artifactId>
  51. <version>4.3.3.RELEASE</version>
  52. </dependency>
  53. <dependency>
  54. <groupId>javax.servlet</groupId>
  55. <artifactId>javax.servlet-api</artifactId>
  56. <version>3.1.0</version>
  57. </dependency>
  58. <dependency>
  59. <groupId>javax.servlet</groupId>
  60. <artifactId>jstl</artifactId>
  61. <version>1.2</version>
  62. </dependency>

第三步:前端控制器配置

在WEB-INF下web.xml中配置前端控制器

<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc.xml</param-value>
</init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
  • load-on-startup:表示servlet随服务启动;
  • url-pattern:/表示所有的请交给DispatcherServlet处理。
  • contextConfigLocation:指定springmvc配置的加载位置,如果不指定则默认加
  • 载WEB-INF/[DispatcherServlet 的Servlet 名字]-servlet.xml。

Servlet拦截方式

1、拦截固定后缀的url,比如设置为 .do、.action, 例如:/user/add.action
此方法最简单,不会导致静态资源(jpg,js,css)被拦截。

2、拦截所有,设置为/,例如:/user/add/zhangsan/23 /user/add.action
此方法可以实现REST风格的url,很多互联网类型的应用使用这种方式

但是此方法会导致静态文件(jpg,js,css)被拦截后不能正常显示。需要特殊处理。

3、拦截所有,设置为/*,此设置方法错误,因为请求到Action,当action转到jsp时再次被拦截,提示不能根据jsp路径mapping成功。

第四步:springmvc配置文件

Springmvc默认加载WEB-INF/[前端控制器的名字]-servlet.xml,也可以在前端控制器定义处指定加载的配置文件,
如下:

<init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
</init-param>

如上代码,通过contextConfigLocation加载classpath下的springmvc.xml配置文件。

创建springmvc.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/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 ">
    <!--扫描controller注解,多个包中间使用半角逗号分隔 -->
    <context:component-scan base-package="com.hzit.controller" />

    <!--替代注解处理器和适配器的配置 -->
    <mvc:annotation-driven />

    <!-- 配置视图解析器 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <!-- 设置前缀的位置 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 设置后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>
<!—过滤静态文件 -->
    <mvc:resources mapping="/resources/**" location="/resources/" />


</beans>

配置组件扫描器

使用组件扫描器省去在spring容器配置每个controller类的繁琐。使用<context:component-scan自动扫描标记@controller的控制器类,配置如下:

<!--扫描controller注解,多个包中间使用半角逗号分隔 -->
<context:component-scanbase-package="com.xxx.springmvc.controller"/>

配置处理器映射器和处理器适配器

springmvc使用自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter,可用在springmvc.xml配置文件中使用替代注解处理器和适配器的配置。

<!--替代注解处理器和适配器的配置-->
<mvc:annotation-driven></mvc:annotation-driven>

开启注解映射支持,它是为了简化配置的缩写形式,它相当于以下2个配置:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

配置视图解析器

在springmvc.xml文件配置如下:

<!-- ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
  • InternalResourceViewResolver:支持JSP视图解析
  • viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,所以classpath中必须包含jstl的相关jar 包;
  • prefix 和suffix:查找视图页面的前缀和后缀,最终视图的址为:

前缀+逻辑视图名+后缀,逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为hello,则最终返回的jsp视图地址 “WEB-INF/jsp/hello.jsp”

处理静态文件

如果只配置拦截类似于.do或者.action格式的url,则对静态资源的访问是没有问题的,但是如果配置拦截了所有的请求(如我们上面配置的“/”),就会造成js文件、css文件、图片文件等静态资源无法访问。
一般实现拦截器主要是为了权限管理,主要是拦截一些url请求,所以不对静态资源进行拦截

在springmvc.xml的配置文件中加入以下代码:

 <!-- 静态资源映射 -->
<mvc:resources mapping="/js/**" location="/WEB-INF/js/" />
<mvc:resources mapping="/css/**" location="/WEB-INF/css/" />
<mvc:resources mapping="/fonts/**" location="/WEB-INF/fonts/" />
<mvc:resources mapping="/plugins/**" location="/WEB-INF/plugins/" />
<mvc:resources mapping="images/**" location="/WEB-INF/images/" />

<!-- 当上面要访问的静态资源不包括在上面的配置中时,则根据此配置来访问 -->
<mvc:default-servlet-handler/>

第五步:处理器开发(通过注解)

在com.xxx.controller包下面创建HelloController.java文件

/**
 * Controller层 
 * @author Administrator
 *
 */
@Controller
public class HelloController {

    /**
     * 通過@RequestMapping注解定义访问路径
     * @return ModelAndView  或者String类型的数据
     */
    @RequestMapping("/hello")
    public ModelAndView hello() {

        ModelAndView mv = new ModelAndView();
        mv.addObject("helloMsg", "hello springmvc");

        //设置路径  配置视图解析器中的前缀+show+后缀/WEB-INF/jsp/show.jsp
        mv.setViewName("show");

        return mv;
    }

}

第六步:视图开发

创建/WEB-INF/jsp/show.jsp视图页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${helloMsg} 
</body>
</html>

第七步:部署在tomcat测试

通过请求:http://localhost:8080/Springmvc01/hello,如果页面输出信息就表明我们成功了!

image.png

注解开发

常用的注解

@RequestMapping

通过RequestMapping注解可以定义不同的处理器映射规则。

@RequestParam

定义如下:

public String editItem(@RequestParam(value="item_id",required=true) String id) {

}

形参名称为id,但是这里使用value=” item_id”限定请求的参数名为item_id,所以页面传递参数的名必须为item_id。

注意:如果请求参数中没有item_id将跑出异常:

HTTP Status 500 - Required Integer parameter ‘item_id’ is not present

这里通过required=true限定item_id参数为必需传递,如果不传递则报400错误

@PathVariable

@RequestMapping(value=”/ viewItems/{id}”):{×××}占位符,请求的URL可以是“/viewItems/1”或“/viewItems/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。

@RequestMapping("/viewItems/{id}") 
    public @ResponseBody viewItems(@PathVariable("id") String id,Model model) throws Exception{
        //方法中使用@PathVariable获取useried的值,使用model传回页面
        //调用 service查询商品信息
        ItemsCustom itemsCustom = itemsService.findItemsById(id);
        return itemsCustom;
}

如果RequestMapping中表示为”/viewItems/{id}”,id和形参名称一致,@PathVariable不用指定名称。

@RequestBody

作用:
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

@ResponseBody

作用:
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。

@RequestBody请求json @ResponseBody响应json实现

环境准备

Springmvc默认用MappingJacksonHttpMessageConverter对json数据进行转换,需要加入jackson的包,如下:

image.png

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.6.0</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.0</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.6.0</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.jr</groupId>
            <artifactId>jackson-jr-all</artifactId>
            <version>2.6.0</version>
        </dependency>

配置json转换器

在注解适配器中加入messageConverters

<!--转换json 注解适配器 -->
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean
                    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
            </list>
        </property>
    </bean>

注意:如果使用 则不用定义上边的内容。