2.SpringMVC介绍 2.1.SpringMVC是什么 SpringMVC是Spring组织下的一个表现层框架。和Struts2一样。它是Spring框架组织下的一部分。我们可以从Spring的整体结构中看得出来: 2.2.SpringMVC的作用 1.接收Web请求中的参数 2.把处理好的数据返回给页面 2.3.为什么要学习SpringMVC 技术是要更新换代的,可以说Springmvc是对Struts2的技术更新,Struts2太老了,许多设计已经过时,效率不符合现在业务(互联网)的需要,而且SpringMVC与Spring是一家的它们之间的衔接是无缝的,所以使用SpringMVC更方便和Spring进行整合。 更重要的一点是Struts2存在安全漏洞,之前的某些版本曾经造成过一些企业的损失,这也加速了Struts2的迅速老去。 那为什么之前还要学习Struts2呢?是因为今后工作中不一定都是从事新的系统开发,你有可能去维护一个已经上线的老系统,比如许多传统行业里面应用的系统Struts2的使用率仍然不小,因此从学习的角度Struts2也要学习掌握。 2.4.了解SpringMVC的处理流程 要想引入SpringMVC做表现层开发,最基本的需要完成两件事: 1. 配置好前端控制器DispatcherServlet。 2. 开发后端控制器并在SpringMVC的配置文件中加入企业级的配置。 3.SpringMVC环境搭建及入门程序 3.1.软件环境 Jdk:jdk1.7.0_72 Eclipse:mars Tomcat:apache-tomcat-7.0.53 Springmvc:4.1.3 说明: 作为本课练习对jdk,eclipse版本的要求不严格。 但在实际项目中团队的开发版本是有严格要求的,最新版本不代表是最好的,实际项目都选用最稳定的版本。 3.2.环境搭建 3.2.1.第一步:创建一个java web工程(UTF-8)并导入jar包 1.创建一个java web工程 2.导入jar包 在web工程中拷贝到lib文件夹下的jar包可以自动被导入工程 spring原生jar包: Spring常用依赖jar包: 3.2.2.第二步:配置前端控制器 【web.xml】是整个web请求的入口配置文件 <说明> ·前端控制器: org.springframework.web.servlet.DispatcherServlet,它是SpringMVC接收web请求的第一入口,也是唯一入口。这是一个servlet对象,因此需要在web.xml中进行配置。 ·<load-on-startup>:此项配置是控制当前servlet是否随tomcat启动而被加载 配置的值必须是整数 值 >= 0:表示当前servlet随着tomcat启动而被加载,值的大小表示加载的顺序,越小越优先 值 < 0:表示当前servlet不会随着tomcat启动而被加载,只有当它被使用的时候才加载。 DispatcherServlet启动后会立刻去找SpringMVC的配置文件,然后根据配置文件中的内容进行加载和扫描 ·<init-param>: 用这个标签加载SpringMVC配置文件,意义就是在DispatcherServlet的初始化过程中加载配置文件, <param-name>为【contextConfigLocation】 <param-value>为【classpath:SpringMVC配置文件的类目录下的相对路径】 ·SpringMVC默认配置文件: 如果没有显示的配置SpringMVC的核心配置文件,SpringMVC会去[/WEB-INF/]下找默认的核心配置文件。默认核心配置文件的命名:servlet-name的值 + -servlet.xml。在实际工作中要知道:当发现web.xml没有配置核心配置文件时要知道去[/WEB-INF/]下找它的默认配置文件。 因为各种框架的默认配置文件的位置可能不同,所以企业很少采用默认的配置文件路径,因此我们需要统一规划配置文件的存放位置,通过手动配置完成配置文件的加载。 ·常用URL样式: [/*]: SpringMvc禁止使用,不支持。 [*.action]: 以.action为结尾的url地址请求可以进入DispatcherServlet, 放行所有资源文件后缀的url。 [/]: 所有url地址请求均可进入DispatcherServlet, 但只放行以.jsp为结尾的url,其他资源文件后缀的url都不放行(这个明天的RESTful的时候会具体用到, 今天先不讲) 资源文件请求url: <link href="<%=basePath%>css/bootstrap.min.css" rel="stylesheet"> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <?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" id="WebApp_ID" version="2.5"> <display-name>springmvc</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 配置springmvc前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置SpringMVC的配置文件 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:SpringMvc.xml</param-value> </init-param> <!-- 配置DispacherServlet随tomcat启动而被加载 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 配置什么样的url路径可以进入DispatcherServlet --> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app> 3.2.3.第三步:创建springmvc核心配置文件 新建一个source folder: config 在config下创建一个xml文件: SpringMvc.xml,文件头可以从其他地方直接拷贝过来。 <?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:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> </beans> 3.2.4.第四步:启动tomcat测试环境 到此为止SpringMvc基本框架搭建完成,启动tomcat,日志中不报错,就说明环境搭建成功。 下面就是入门程序的开发。 3.3.案例需求 3.3.1.需求 使用SpringMVC实现商品列表的展示。 3.3.2.需求分析 1.要展示全部商品列表,所以不需要参数,请求url: http://localhost:8080/<具体web应用的名字>/list.action 2.主要关注SpringMvc的入门程序,所以暂不考虑连接数据库等多余功能,在业务处理中只做假的模拟数据返回给页面。 3.4.入门程序 3.4.1.第一步:创建jsp页面 创建jsp页面的目录: 前端页面不是本课内容,参考: 参考资料\参考案例\jsp\itemList.jsp直接拷贝到工程jsp目录中。 问题:放在WebContent目录下和放到WEB-INFO目录下的区别? WEB-INFO是受tomcat保护目录,它里面的文件只能由servlet去访问,不能通过url地址栏去请求访问。 WebContent下的文件可以直接通过url地址栏去访问,一般的欢迎页和静态资源文件都放在这里。 3.4.2.第二步:创建和配置后端控制器 创建包: cn.baidu.controller用于存放后端控制器,cn.baidu.pojo用于存放保存返回数据的bean 创建后端控制器类: <说明> ·@Controller:表明用这个注解修饰的类需要SpringMVC扫描成SpringMVC的组件。 package cn.baidu.controller; import org.springframework.stereotype.Controller; // 定义一个java类,@Controller注解标注在类定义的上方表明这个类需要SpringMVC扫描。 @Controller public class ItemsController { } 在SpringMvc.xml中配置后端控制器类的扫描 <说明> <context:component-scan base-package="要扫描的包路径" /> 扫描指定包及子包下的@Controller、@Service、@Repository等注解修饰的java类。 其中在SpringMVC配置文件中只扫描@Controller修饰的类所在的包,并注册为SpringMVC的组件。 其它注解修饰的类在Spring配置文件中扫描,并注册为Spring的组件。 <?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:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置SpringMVC下Controller类的扫描 --> <context:component-scan base-package="cn.baidu.controller" /> </beans> 注意: 如果想扫描多个包,可以配置多个<context:component-scan base-package="指定的包名" /> 3.4.3.第三步:编写方法响应url请求 注解类型的Controller类中使用@RequestMapping注解修饰的方法响应url请求。一个url对应一个方法。不可能多个url同时对应一个方法,也不可能多个方法同时响应一个url请求。 <说明> ·@RequestMapping(“具体URL”): 指明这个方法响应的具体url是什么。这里面配置的url是工程名后的具体url,以【/】开头,如果不写【/】也可以,推荐写。 @RequestMapping(“具体URL”)和它修饰的方法就形成一对key/value,key就是URL,value就是由注解修饰的方法包装在handler对象中(handler是SpringMVC内置的专门用来封装url请求响应方法的对象),最终再把这些key/value放到一个map对象中保存。 ·Model: 模型对象,是SpringMVC默认支持的一种形参类型, 作用:负责将返回给页面的数据赋值给request对象(这个赋值的过程是SpringMVC底层做的,将你赋给Model对象的属性名和值赋给request对象,这个详细过程不需要我们掌握它的详细逻辑,理解一下即可。) 这样JSP就可以用EL表达式从request对象中取得这个属性名的数据了。 ·记住:对于jsp永远都是从request对象中通过属性名取值。 package cn.baidu.controller; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import cn.baidu.pojo.Items; // 定义一个java类,@Controller注解标注在类定义的上方表明这个类需要SpringMVC扫描。 @Controller public class ItemsController { // 标注url到请求方法的key/value对应关系 @RequestMapping("/list") public String list(Model model) throws Exception { //商品列表(临时数据) List<Items> itemsList = new ArrayList<Items>(); Items items1 = new Items(); items1.setName("联想笔记本"); items1.setPrice(6000f); items1.setDetail("ThinkPad T430 联想笔记本电脑!"); Items items2 = new Items(); items2.setName("苹果手机"); items2.setPrice(5000f); items2.setDetail("iphone6苹果手机!"); itemsList.add(items1); itemsList.add(items2); // 1. 设置返回给页面的数据 // 第一个参数是属性名称, 第二个参数是属性值 //model在SpringMVC底层是将它里面的属性名和属性值赋值给了request对象,而jsp页面通过request域进行取值 model.addAttribute("itemList", itemsList); //简化完的剩余的字符串叫做视图的逻辑视图名 //视图的物理路径 = 前缀 + 逻辑视图名 + 后缀. return "itemList"; model.addAttribute("itemsList", itemsList); // 2. 指定返回页面的地址 return "/WEB-INF/jsp/itemList.jsp"; } } 返回的页面是否存在、是否正确都需要先判断一下,在SpringMVC中使用一个视图解析器的组件来做这些处理。 配置视图解析器:在SpringMVC.xml中配置 <?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:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置指定包下的组件扫描 --> <context:component-scan base-package="cn.baidu.controller" /> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> </bean> </beans> 3.4.4.第四步:启动tomcat测试 访问地址: http://localhost:8080/springmvc/list.action 3.4.5.第五步:优化方法的返回路径 上面直接返回jsp的路径倒是很直接,但是每个方法都返回一长串路径看着有点乱,而且每个方法返回的路径中【/WEB-INF/jsp/】和【.jsp】都是重复的,未免显得有些冗余。 能否将这些重复的部分提取出来放到SpringMVC的配置文件中呢?答案是肯定的——修改视图解析器的配置: 【SpringMVC.xml】中配置视图解析器的前缀和后缀专门用来拼接视图文件的路径: <?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:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置指定包下的组件扫描 --> <context:component-scan base-package="cn.baidu.controller" /> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 后缀 --> <property name="suffix" value=".jsp" /> </bean> </beans> 说明: 1.作用: 用视图解析器中配置的前缀和后缀简化Controller类中的编码 2.代码的简化: ······ // 2. 指定返回页面的地址 return "itemList"; ······ 3.逻辑视图名与视图文件物理路径 简化后Controller方法中返回的字符串叫做逻辑视图名。 视图文件物理路径=前缀 + 逻辑视图名 + 后缀。 SpringMVC能保证每次返回的字符串都会自动走视图解析器,然后按照上面的方式拼接,再进行后续处理。 3.5.本节总结 本单元内容主要是搭建了一个SpringMVC开发环境并学习了它的入门程序。 这个开发环境只有SpringMVC,所以不是我们正式的环境,了解即可,不重要。 入门程序中学习到的两个注解@Controller和@RequestMapping用法以及返回数据和返回页面的处理方式要掌握。 <!-- 配置后端控制器的扫描 --> <!-- 这个标签可以扫描的注解 : @Controller , @Service, @Repository,这是前三个的父注解@Compontent --> <context:component-scan base-package="cn.baidu.controller"></context:component-scan> <!-- 显示配置处理器映射器和处理器适配器 --> <!-- 默认形式的处理器映射器和处理器适配器 : 默认的组件是不推荐使用的,因为它们是旧版 DefaultAnnctationHandlerMapping和AnnotationMethodHandlerAdapter --> <!-- 配置当前版本下最新的注解形式的处理器映射器和处理器适配器 : 虽然是最新的,但是一旦版本变更可能会引起新的修改--> <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> --> <!-- 企业中系统一劳永逸的方式 : 注解驱动方式 --> <!-- 作用 : 会加载当前版本下最新的注解形式的处理器映射器和处理器适配器,能提高执行效率 --> <mvc:annotation-driven/> <!-- 配置视图解析器 --> <!-- 这个视图解析器就是用来解析jsp页面的,也是springmvc默认的视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置前缀和后缀为了简化开发 --> <property name="prefix" value="/WEB-INF/jsp/"></property> <!-- 配置后缀 --> <property name="suffix" value=".jsp"></property> </bean> 4.SpringMVC框架 4.1.框架结构(重点) 1.学习框架结构的目的: 开发不用, 但面试时会问到 2.框架结构详细内容:(面试题) 说明:前端控制器是接收web请求的入口,地位最重要。如果还要做其他具体的工作会使它的负担过于繁重,因此SpringMVC找来了四个帮手,叫做四个组件,来帮助前端控制器承担一些具体的工作,这样前端控制器就只发号司令做为集中控制调度中心,具体的工作交给四个组件来完成。 具体工作分为两部分: 1.处理请求:两个组件,一个来找Handler,一个来执行Handler 1)处理器映射器负责找到URL对应的Handler对象 2)处理器适配器负责执行找到的Handler对象。 2.返回结果:两个组件,一个来找页面,一个来执行页面渲染 1)视图解析器负责找到要返回的页面 2)视图对象负责渲染页面,渲染页面需要的数据由前端控制器传给它。 ●啥是freemaker? 就是模版, 通过模版和数据生成输出的文本(HTML网页, 电子邮件等). 比如网易首页点击进入的一个html页面, 这些静态的html都是由freemarker生成的, 而struts2只支持jsp. 4.2.框架流程 1.用户发送请求至前端控制器DispatcherServlet 2.DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3.处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet 4.DispatcherServlet通过HandlerAdapter处理器适配器调用处理器 5.执行处理器(handler也叫后端控制器-->Service-->DAO) 6.Handler执行完成返回ModelAndView 7.HandlerAdapter将handler执行结果ModelAndView返回给DispatcherServlet 8.DispatcherServlet将ModelAndView传给ViewReslover视图解析器 9.ViewReslover根据handler中设置的页面信息解析成一个View视图对象并返回它. 10.DispatcherServlet调用View对象的接口方法对实际的视图文件(如: jsp文件)进行渲染(即将模型数据填充至视图文件中) 11.DispatcherServlet响应用户 口述 : 先扫描@Controller修饰的类 打开这个类找出里面所有由@Requestmapping修饰的方法 通过反射得到这个方法的method对象 把method对象封装到一个handler对象中(handlder是SpringMVC内置的对象用来统一调用方法的) 最终把RequestMapping中配置的url作为key,把handler对象作为value放到一个map对象中 这个map对象由处理器映射器来维护 4.3.需要认识的SpringMVC组件 SpringMVC的整个控制层采用组件式的结构。 SpringMVC的组件有: 前端控制器DispatcherServlet、 处理器Handler(相对于前端控制器的后端控制器)、 处理器映射器HandlerMapping、 处理器适配器HandlerAdapter、 视图对象View、 视图解析器ViewResolver。 其中HandlerMapping、HandlerAdapter、ViewResolver是springmvc的三大核心组件,Handler涉及具体业务需要程序员实现,View由ViewResolver生成,负责渲染页面。 三大组件干的事情其实都可以集中交给DispatcherServlet来干,但都交给它会使它过于臃肿,处理效率会大大降低,因此分而治之才是上策。 4.3.1.DispatcherServlet:前端控制器 DispatcherServlet负责接收用户请求,是整个流程的控制中心,但它几乎不做任何具体的工作,只进行任务调度。具体的工作由具体的组件来完成。这就是组件式结构的优势,专项事情又专门的组件来做,这样能提高专项的处理能力同时集中调度的存在降低了组件之间的耦合性。 4.3.2.Handler:处理器 在DispatcherServlet的控制下Handler对具体的用户请求进行处理。 由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。 4.3.3.HandlerMapping: 处理器映射器 HandlerMapping负责为每个请求找到一个合适的处理器handler,其实简单来说就是维持了一个url到handler的映射Map。springmvc提供了不同的映射器,实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 比如注解方式的映射器会根据核心配置文件中配置的<context:component-scan base-package="包路径" />指定的包路径(包括子目录)进行扫描,找@Controller标注的Java类,该类中所有使用@RequestMapping修饰的方法都是一个handler对象,并根据@RequestMapping的值作为key,对应的方法的handler对象作为value,形成一个url到方法的k/v键值对映射。而且这种扫描只要在tomcat启动时做一次,不会影响系统的性能。 4.3.4.HandlerAdapter: 处理器适配器 1.什么是适配器: 2.适配器的作用:统一调用接口,好扩展。 3.Springmvc中的处理器适配器: 处理器适配器HandlerAdapter负责执行具体的处理器。 SpringMVC有多个适配器,当HandlerMapping找到了url对应的handler对象后,前端控制器会挑选一个能够执行这个handler的处理器适配器,然后给这个适配器发送指令,同时把这个handler对象传给这个适配器,让它执行handler,最终将handler的返回值和逻辑视图名字符串返回给前端控制器。 4.3.5.ViewResolver: 视图解析器 视图解析器(ViewResolver)负责解析出视图文件的物理路径,并根据这个路径生成视图View对象。 ViewResolver首先把逻辑视图名解析成实际的页面位置,再生成视图View对象并返回给前端控制器。 4.3.6.View:视图对象类型 1.View视图对象 View对象负责渲染视图文件,将数据结果通过视图文件展示给用户。前端控制器调用View对象的接口方法render(),参数就是后台返回的数据,在render方法拿数据渲染视图文件生成返回给客户端的结果。 springmvc框架提供了很多的View类型,包括:jstlView、freemarkerView、pdfView等。 2.视图文件 视图文件可以是jsp、pdf、freemaker等,最常用的就是jsp。一般情况下需要通过页面jsp标签或页面模版将处理器返回的model数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。 4.3.7.组件总结 SpringMVC的三大组件(理解记忆):处理器映射器、处理器适配器、视图解析器 需要程序员编写代码的有:处理器(包括处理器、具体业务的service和dao)、视图文件(jsp) 4.4.SpringMvc三大组件的配置 Springmvc三大组件配置在核心配置文件中,springmvc支持组件免配置、显示配置和企业的配置方法 4.4.1.组件的免配置 1.何为免配置: 即什么都不配。此时SpringMVC仍然可以正常运行,全凭它自己的DispatcherServlet.properties,会从中找到合适的组件去执行。这个属性文件的位置: 2.DispatcherServlet.properties的作用: 如果没有显示配置三大组件(其中一个或者全部),依靠这个属性文件中的默认配置组件,springmvc也能正确的执行。 3.上面的入门程序中自动选择的三大组件分别是: a)处理器映射器 b)处理器适配器 c)视图解析器 默认的视图解析器只有一个。 4.坏处: 每次请求都要去这里去找合适的组件,所以执行效率很低,因此什么都不配置是不可取的。需要我们显示配置来提高执行效率。 4.4.2.SpringMvc显式配置处理器映射器和处理器适配器 1.显式配置默认选择的处理器映射器和处理器适配器(旧版) 2.显式配置官方推荐的处理器映射器和处理器适配器(新版) 3.企业中的配置方法:注解驱动 作用:帮助我们显式配置当前Spring版本的最新的注解形式的处理器映射器和处理器适配器 好处:简化配置,一劳永逸 4.面试题: springmvc是否要配置注解驱动和注解扫描? 有什么区别? 答: 都需要配置,两个东西的作用完全不一样,不要混淆视听。 注解驱动:作用就是替我们显式的配置当前spring版本下最新版本的注解形式的处理器映射器和处理器 适配器 注解扫描:扫描指定包及子包下的@Controller、@Service、@Repository等注解修饰的java类,其 中@Controller修饰的类注册为SpringMVC的组件,其它注解修饰的类注册为Spring的 组件。 4.4.3.SpringMvc显式配置视图解析器 前面已经学过,此处只给出配置的例子。 4.4.4.显示配置的意义 处理器映射器、适配器:提高执行效率 视图解析器(有前缀和后缀):简化编码 4.5.本节重点 掌握: SpringMVC的框架流程,能说出来从请求到返回页面的处理流程; SpringMVC三大组件的最终形态的显示配置方法。 理解: 三大核心组件的功能。 了解: Springmvc默认组件配置; 单独配置新版的处理器映射器和处理器适配器。 下面是完整的springmvc核心配置文件的配置:SpringMVC.xml <?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:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置指定包下的组件扫描 --> <!-- 作用:SpringMVC可以自动去扫描指定包以及子包下的java文件,如果扫描到有@Controller(控制层的类) @Service(业务层的类) @Repository(数据库访问层的类)这些注解修饰的类,则把这些类注册为 SpringMVC的组件 --> <context:component-scan base-package="cn.baidu.controller" /> <!-- 1. SpringMVC默认的三大组件选择(处理器映射器、处理器适配器、视图解析器) 如果没有显示的配置三大组件,SpringMVC也能正常执行,是因为会默认去找SpringMVC的默认 属性文件DispatcherServlet.properties,从中找到合适的三大组件去执行。但这种方式在么次 请求的时候都会去找一遍,所以效率很低,因此采用默认的三大组件选择是不可取的。 我们应该显示的配置它们,这样可以提高系统的访问效率。 --> <!-- 2. 显示的配置处理器映射器和处理器适配器 --> <!-- 默认的注解形式的处理器映射器:老版本,不推荐使用 --> <!-- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> --> <!-- 默认的注解形式的处理器适配器:老版本,不推荐使用 --> <!-- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> --> <!-- 当前最新版本的注解形式的处理器映射器 --> <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> --> <!-- 当前最新版本的注解形式的处理器适配器 --> <!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" /> --> <!-- 3. 企业中配置注解形式的处理器映射器和处理器适配器的方法:注解驱动 --> <!-- 作用:显示的配置了当前Spring版本下最新的注解形式的处理器映射器和处理器适配器。由于它 没有和任何class关联,所以即使Spring版本升级,该项配置也不会发生任何改动,企业中 喜欢采用这种一劳永逸的方法。 --> <mvc:annotation-driven /> <!-- 配置视图解析器 --> <!-- 作用:利用显示配置视图解析器中的前缀和后缀可以简化Controller方法中的视图信息的设置,只需 在setViewName方法中设置逻辑视图名称(视图文件的名称,比如jsp文件)即可。每次视图解 析器都会自动的进行视图文件物理路径的拼接:前缀 + 逻辑视图名称 + 后缀。从而方便了我们的 编码工作。 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 后缀 --> <property name="suffix" value=".jsp" /> </bean> </beans> 5.SSM整合 5.1.SSM整合包含的框架 5.2.SSM整合思路 5.2.1.整合思路的重要性 整合的步骤是固定的, 过程是可以复制的, 人家告诉我们怎么整合就怎么来做就可以了. 具体来说, 第一是你手头有现成的资料照着做即可; 第二如果你没有资料, 怎么办? 这时候如果能记住思路, 我们就可以上网去找资料. 但如果思路记不住就连资料怎么找都不知道了, 所以说思路是很重要的, 要记住. 5.2.2.具体的整合思路(重点) 首先,先划分大层次,整合后分为三层:表现层 业务层 数据访问层,再加上web.xml这是整体的骨架; 其次,再逐层规划每一层具体要干什么。 ssm整合的思路如下: Spring与MyBatis的整合在MyBatis第二天的时候已经学习过了,这里仍然沿用。SpringMVC与Spring又是一家的,所以它们之间是不需要整合配置的,即所谓的无缝整合,直接就可以用,只不过需要在web.xml中配置它们两个。具体规划如下: SSM整合分三层:DAO层、Service层、Controller层 代码目录: ·DAO层: pojo:pojo类 dao:映射文件、接口文件——Mybatis逆向工程自动生成,DAO通过SM整合jar包来扫描 ·Service层: service:service接口和实现类——利用@Service注解修饰,让spring来扫描 ·Controller层: controller:Controller类及方法——利用@Controller注解修饰,让SpringMVC来扫描 配置目录: ·config: MyBatisConfig.xml——MyBatis配置 ApplicationContext-dao.xml——数据源、连接池、会话工厂、mapper包扫描 ApplicationContext-service.xml——注解扫描(service层的组件扫描)、事务管理 (以上两个配置文件可以配置在一个文件中,这里为了体现分层的思路所以分开配置。) SpringMVC.xml——注解扫描(Controller层的组件扫描)、注解驱动、视图解析器 web.xml Spring监听(管理service层和dao层)、SpringMVC前端控制器(管理Controller层) JSP:在【/WEB-INF/】创建jsp目录,存放jsp页面。 面试题:事务配置在哪一层?为什么? 事务配置在service层,因为service层控制的是业务,在一个service中有可能调用多个DAO中的方法进行一系列的操作,这些操作要么都成功,要么都失败。比如汇款,汇出操作成功了,但是存入给另一个人时发现卡被注销了,这个时候要整个业务回滚,否则钱就会丢失,所以必须在service层做事务控制。 注意: 不要纠结Controller层的类域Service层的类能否放到一个目录下。这个问题没有意义,因为分层的意思就是强制将它们分开,Controller层的目录就放Controller的类,Service层的目录就放Service的类,DAO层的目录就放Dao的类。 配置文件是否合并的问题,这个问题也不要纠结,看个人喜好,如果想让配置文件单一化,就可以把两个ApplicationContext文件合并,但SpringMVC.xml与ApplicationContext不要合并,因为前者是表现层由Spring的子集框架SpringMVC专门负责,后者是业务层以及DAO层由Spring本身自己负责。 5.3.软件环境 Jdk: jdk1.7.0_72 Eclipse: mars Tomcat: apache-tomcat-7.0.53 Springmvc: 4.1.3 MyBatis: mybatis-3.2.7 MySql: 5.1.28 SM整合包: 1.2.2 5.4.数据库环境 使用【资料\参考案例\sql】下的创建库建表脚本【springmvc.sql】创建我们使用的数据库环境。 5.5.SSM整合步骤 5.5.1.第一步: 新建一个web工程 5.5.2.第三步: 导入jar包 将【资料\jar\ssm整合后jar全集】下的jar包拷贝到WebContent/WEB-INF/lib下, 会自动关联到工程中 5.5.3.第二步: 创建目录结构 根据思路创建工程目录: 1.代码目录: cn.baidu包下创建四个子包 controller: 存放cnotroller层的代码 service : 存放service层的代码 dao: 存放dao层的代码 pojo: 存放pojo的代码 2.配置文件目录: 选择工程右键创建source folder: config, 用于存放全部配置文件. 3.视图目录: 在WebContent/WEB-INF下创建jsp目录,用于存放jsp文件. 5.5.4.第四步: 使用mybatis逆向工程生成代码 1.将【资料\MyBatis逆向工程】下的【MyBatisGeneration】工程导入eclipse。 2.修改配置文件符合当前的开发环境和目录结构。 a)数据库名 b)Pojo包名 c)Mybatis映射文件的包名 d)Mybatis映射接口的包名(与c相等) e)需要生成代码的数据库表 3.注意: a)执行前要把原先旧的代码全部删除。 b)执行完生成程序后第一次刷新的时候表现出来的包名不对,再刷新一次就好了。这是eclipse的一个bug。 4.将生成的代码拷贝到我们的工程中去。 5.5.5.第五步: 创建DAO层配置文件 1.在【资料\参考案例\config】下是mybatis课程中sm整合的时候需要的配置文件,整体导入。 2.整理mybatis的配置文件: a)MyBatisConfig.xml:清空<configuration>标签内全部的内容,保留一个空的配置文件是为了今后对mybatis的扩展。 b)ApplicationContext.xml:保留其中的属性文件、数据源(连接池)、会话工厂、动态代理包扫描的配置,其他的都删除。根据上面的思路它应该属于dao层的spring配置文件,改名为ApplicationContext-dao.xml c)其他配置文件保持不变。 3.修改后的配置文件: 【MyBatisConfig.xml】 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 类型别名的配置 --> <!-- <typeAliases> <typeAlias type="cn.baidu.pojo.UserModel" alias="UserModel"/> <package name="cn.baidu.pojo"/> </typeAliases> --> </configuration> 【ApplicationContext-dao.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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 1 属性文件的配置 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 2 数据源的配置 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="maxActive" value="10" /> <property name="maxIdle" value="5" /> </bean> <!-- 3 MyBatis的会话工厂的配置 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:MyBatisConfig.xml" /> <property name="dataSource" ref="dataSource" /> </bean> <!-- 4 动态代理包扫描的配置 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.baidu.dao" /> </bean> </beans> 5.5.6.第六步: 创建Service层配置文件 创建【ApplicationContext-service.xml】,@Service注解组件的扫描和事务管理 【ApplicationContext-service.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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- service层的组件扫描 --> <context:component-scan base-package="cn.baidu.service" /> <!-- 事物管理配置 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源 --> <property name="dataSource" ref="dataSource"/> </bean> <!-- 通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 传播行为 --> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> <!-- 切面 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.baidu.service.*.*(..))" /> </aop:config> </beans> 5.5.7.第七步: 创建SpringMvc.xml 创建【SpringMvc.xml】,配置@Controller注解组件扫描,注解驱动,视图解析器 配置文件: 【SpringMvc.xml】 <?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:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- controller层的组件扫描 --> <context:component-scan base-package="cn.baidu.controller" /> <!-- 配置注解驱动 --> <mvc:annotation-driven /> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 前缀 --> <property name="prefix" value="WEB-INF/jsp/" /> <!-- 后缀 --> <property name="suffix" value=".jsp" /> </bean> </beans> 5.5.8.第八步: 配置web.xml 配置spring的容器监听、springmvc前端控制器以及它可接收的url地址。 配置文件: 【web.xml】 <?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" id="WebApp_ID" version="2.5"> <display-name>ssm</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 配置spring的容器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:ApplicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置springmvc的前端控制器--> <servlet> <servlet-name>springMvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 指定springmvc核心配置文件的位置 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:SpringMVC.xml</param-value> </init-param> <!-- 标记是否在tomcat启动时就加载当前的servlet --> <load-on-startup>1</load-on-startup> </servlet> <!-- 配置springmvc前端控制器能够接收的url结尾格式 --> <servlet-mapping> <servlet-name>springMvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app> 5.5.9.小结 本节的重点是要掌握整合的思路,有了思路就可以寻着线索进行整合了,不用死记具体的过程。 5.6.整合后的案例程序 5.6.1.需求 使用SSM从数据库查询数据, 实现真正的商品列表的展示. 5.6.2.需求分析 1.沿用SpringMvc入门程序. 2.在此基础上完成service层的代码, 定义service接口和实现类, 并用@autowired自动注入DAO接口对象. 3.完善controller层代码, 用@autowired自动注入service接口对象. 5.6.3.第一步: 创建service层的接口和实现类 1.定义ItemsService.java接口 2.定义ItemsServiceImpl.java实现类,实现这个接口 代码: 【ItemsService.java】 package cn.baidu.service; import java.util.List; import cn.baidu.pojo.Items; public interface ItemsService { public List<Items> findItemsList() throws Exception; } 【ItemsServiceImpl.java】 package cn.baidu.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import cn.baidu.dao.ItemsMapper; import cn.baidu.pojo.Items; @Service public class ItemsServiceImpl implements ItemsService { @Autowired ItemsMapper itemsMapper; @Override public List<Items> findItemsList() throws Exception { // 通过自动生成的接口方法查询商品列表 List<Items> list = itemsMapper.selectByExample(null); return list; } } 注意:selectByExample(null)只检索除了大对象数据类型之外的字段,但items表中有一个detail字段的类型是text,为了把它也检索出来可以使用selectByExampleWithBLOBs(null)这个方法。 package cn.baidu.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import cn.baidu.dao.ItemsMapper; import cn.baidu.pojo.Items; public class ItemsServiceImpl implements ItemsService { @Autowired ItemsMapper itemsMapper; @Override public List<Items> findItemsList() throws Exception { /* * 注意: * selectByExample只检索除了大对象数据类型之外的项目 * selectByExampleWithBLOBs检索包含大对象数据类型的项目 */ // 通过自动生成的接口方法查询商品列表 List<Items> list = itemsMapper.selectByExampleWithBLOBs(null); return list; } } 5.6.4.第二步: 完善Controller层代码 1.把入门程序中的【ItemsController.java】拷贝过来 2.修改里面的【lsit()】方法,调用service接口的方法完成查询。 代码: 【ItemsController.java】 package cn.baidu.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import cn.baidu.pojo.Items; import cn.baidu.service.ItemsService; @Controller public class ItemsController { @Autowired private ItemsService itemsService; @RequestMapping("/list") public ModelAndView list() throws Exception { List<Items> itemsList = itemsService.findItemsList(); // 1. 设置返回页面需要的数据 2. 指定返回页面的地址 ModelAndView modelAndView = new ModelAndView(); // 1. 设置返回页面需要的数据 modelAndView.addObject("itemList", itemsList); // 2. 指定返回页面的地址 modelAndView.setViewName("itemList"); return modelAndView; } } 5.6.5.第三步: 导入jsp 从【资料\参考案例\jsp】中导入【itemList.jsp】到工程的jsp目录下 5.6.6.第三步: 把工程加入tomcat启动、测试 访问地址: http://localhost:8080/springmvc/list.action 数据库: 5.7.本节重点 到本节为止,一个完整的ssm整合就完成了。我们从最初的springmvc入门程序,到认识三大核心组件,到最后ssm整合形成完整的web系统,这就是一个web系统的学习进化过程。 大家重点掌握: 整合的分层思路以及各层代码的编写 大家主要了解: SSM开发环境搭建,这个环境搭建不是大家掌握的重点,只是作为了解,基本会搭即可。