1. 第一天(基础知识)<br />1、什么是SpringMVC?<br /> 概述:就是spring框架的一个模块(属于springweb模块),springmvcspring无<br /> 需通过中间整合层(就是jar包)进行整合。<br /> Springmvc是一个基于mvcweb框架。表现层的框架。 ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012153358-a1accbde-0ab6-44bd-b4f6-107fdc0b74f9.png#height=317&width=402)<br />2、什么是MVC?<br /> MVC是一个设计模式。<br />设计模式就是日常开发中总结了很好的编成方法和习惯,将这些组成的一种模式。<br /> 在b/s系统下的应用: ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012153661-bc7fafb0-8479-40f1-a77b-cb9b54c24f27.png#height=193&width=415) <br />3、SpringMVC框架原理(掌握)<br /> SpringMVC的执行步骤:<br /> 第一步:发起请求到前端控制器(DispatcherServlet),接受用户请求<br /> 第二步:前端控制器请求处理器映射器(HandlerMapping)查找处理器(Handler)<br /> 可以根据xml配置或者注解来查找<br />第三步:处理器映射器向前端控制器返回一个执行链(HandlerExecutionChain),内<br />含多个拦截器和一个处理器<br />第四步:前端控制器调用处理器适配器(HandlerAdapter)去执行处理器<br />第五步:处理器适配器去执行处理器<br />第六步:处理器执行完成后,向处理器适配器返回ModelAndView<br />第七步:处理器适配器向前端控制器返回ModelAndView<br /> ModelAndView是SpringMVC的底层对象,包括Model和View<br />第八步:前端控制器请求视图解析器(ViewResolver)去进行视图解析。<br /> 根据逻辑视图名解析成真正的视图(jsp,pdf,execl…)<br />第九步:视图解析器向前端控制器返回View<br />第十步:前端控制器进行视图渲染,将模型数据填充到request域中<br /> 模型数据在ModelAndView对象中<br />第十一步:前端控制器响应回用户<br /> <br />SpringMVC的组件:<br />(1)前端控制器(DispatcherServlet,一般不需要程序员开发)<br /> 作用:接受请求,响应结果,相当于转发器。<br /> 有了前端控制器,就减少了其它组件之间的耦合度<br />(2)处理器映射器(HandlerMapping,一般不需要程序员开发)<br /> 作用:根据请求的url来查找处理器(Handler)<br /> 查找的方式:xml配置,注解<br />(3)处理器(Handler,需要程序员开发)<br /> 开发的原则:要按照HandlerAdapter的要求规则去编写<br />(4)处理器适配器(HandlerAdapter,一般不需要程序员开发)<br /> 作用:按照特定的规则(HandlerAdapter要求的规则)来执行处理器<br /> 注意:编写处理器时就要按照HandlerAdapter的要求去做,这样处理器适<br /> 配器才可以正确的去执行处理器。<br />(5)视图解析器(ViewResolver,一般不需要程序员开发)<br /> 作用:进行视图解析,根据逻辑视图名进行解析成真正的视图(View)<br /> (6)视图(View,需要程序员来开发jsp)<br /> View是一个接口,实现类支持不同的View类型(jsp,freemarker,pdf…)<br /> <br />4、springmvc入门程序(商品订单管理)<br /> 需求:商品列表查询<br /> 搭建环境:<br />A、 数据库环境:mydb6<br />B、 Java环境:jdk1.8+tomcat7<br />C、 Jar包:G:/jar包/springmvc包(文件夹内所有jar包)<br /> <br />配置前端控制器:<br /> 配置的位置: 在web.xml中配置。<br />所在的jar包:spring-webmvc.jar/org.springframework.web.servlet/<br /> DispatcherServlet.class<br /> 标签:<servlet><br /> 子标签:<servlet-class> 指定DispatcherServlet全路径名<br /> <param-name>:contextConfigLocation <br />作用: 加载springmvc加载的配置文件(配置处理器、适配器等)。<br />如果不配置contextConfigLocation,默认记载/WEB-<br />INF/servlet名称-servlet.xml<br /> 标签:<servlet-mapping><br /> 子标签:<url-pattern><br /> 第一种:*.action 访问以.action结尾由DispatcherServlet来解析<br /> 第二种:/ 所有访问地址都由DispatcherServlet进行解析,对于<br /> 静态文件的解析需要配置不让DispatcherServlet进<br /> 行解析。使用此种方式可以实现RESTful风格的url<br /> 第三种:/* 这样配置不对,使用这种配置,请求最终会转发到<br /> Jsp页面,当DispatcherServlet解析jsp页面时,不<br /> 能根据jsp页面找到Handler,所以会报错。<br /> <br />配置处理器适配器:(所有的处理器适配器都实现了HandlerAdapter)<br /> 配置的位置:Config/springmvc.xml<br /> 标签:<bean><br /> 配置:<bean class="org.springframework.web.servlet.mvc.<br />SimpleControllerHandlerAdapter"></bean><br />全类名:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter<br /> 通过查看源代码:<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012153946-12057fdc-9c44-4f83-9a67-66d355a0aee5.png#height=79&width=308)<br /> 此适配器能够执行实现Controller接口的Handler。也就是程序员要<br />编写的处理器要实现Controller接口。<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012154239-a74d990e-431e-485f-851f-6b95dcd66dc0.png#height=121&width=299)<br /> <br />编写和配置处理器Handler:<br /> 实现的接口:Controller<br /> 创建ModelAndView:ModelAndView modelAndView=new ModelAndView();<br /> 往ModelAndView中添加数据:addObject(String,Object);<br /> 指定视图路径:setViewName(String );<br /> 配置处理器:<br /> 配置的位置:Config/springmvc.xml<br /> 配置: <bean name="/queryItems.action"<br />class="Controller.ItemsController1"></bean><br /> <br />编写视图(jsp页面):(略)/WEB-INF/jsp/items/itemsList.jsp<br /> <br />配置处理器映射器:<br /> 配置的位置:Config/springmvc.xml<br />类名:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping<br />导入spring约束:包括tx,context,aop,mvc<br />标签:<bean><br /> 配置:<bean class="org.springframework.web.servlet.handler.<br />BeanNameUrlHandlerMapping"></bean><br /> 作用:将处理器bean的name作为url进行查找,需要在配置处理器时指<br /> bean标签的name属性值(也就是url)<br /> <br />配置视图解析器:<br /> 需要配置解析jsp的视图解析器。<br /> 配置的位置:Config/springmvc.xml<br /> 标签:<bean><br /> 类:org.springframework.web.servlet.view.InternalResourceViewResolver<br /> 用来解析jsp的视图解析器,默认使用jstl标签。Classpath下必须要<br /> 有jstl包。<br /> 配置:<bean class="org.springframework.web.servlet.view.<br />InternalResourceViewResolver"></bean><br /> <br />部署调试:<br /> 在调试时,访问的页面路径为处理器Handler所配置的name属性。<br /> <br /> 目的:通过入门程序,对前端控制器、处理器映射器、处理器适配器、视图解析器学习<br />5、非注解的处理器映射器、处理器适配器<br /> (1)处理器映射器:<br /> 所有的处理器映射器都实现了HandlerMapping接口。<br />A、第一种<br /><bean class="org.springframework.web.servlet.handler.<br />BeanNameUrlHandlerMapping"></bean><br /> 这种处理器映射器,访问的地址配置在Handler的name属性中<br /> <br /> <br />B、第二种<br /> 此种配置方式,prop标签的key为访问的路径,值为Handler的id。<br /> 这种方式可以将一个Handler配置多个url路径。<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012154493-d8fb3c7a-b650-4c46-b95e-081711f669d3.png#height=97&width=371)<br /> 总结:多个处理器映射器可以并存,且每个映射器配置的url都时可以访问的。<br /> (2)处理器适配器:<br /> A、第一种<br /> <bean class="org.springframework.web.servlet.mvc.<br />SimpleControllerHandlerAdapter"></bean><br />要求:编写的Handler必须实现Controller接口<br /> B、第二种<br /><bean class="org.springframework.web.servlet.mvc.<br />HttpRequestHandlerAdapter"></bean><br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012154734-022335d8-3743-4af4-96b9-c8324ef1ecbd.png#height=75&width=416)<br />要求:编写的Handler必须实现HttpRequestHandler接口<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012155010-60ca5c4b-07c9-442f-af27-e144a487d97e.png#height=158&width=339) <br />6、DispatcherServlet.properties<br /> 前端控制器从这个文件中加载处理器映射器、适配器、视图解析器等组件,如果不在<br /> Springmvc.xml中配置,就使用默认加载的。<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012155233-646d1eff-234d-49b9-a10f-ab8bb9c79d98.png#height=53&width=415)<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012155431-aa066a8a-67cd-4ee2-957c-ccfe62b5e623.png#height=254&width=159)<br /> <br />7、注解的处理器映射器、处理器适配器(掌握)<br />(1)注解的处理器映射器:<br /> 在spring3.1之前,使用org.springframework.web.servlet.mvc.annotation.<br />DefaultAnnotationHandlerMapping注解映射器。<br />在spring3.1之后,使用org.springframework.web.servlet.mvc.method.annotation.<br />RequestMappingHandlerMapping注解映射器。<br /> (2)注解的处理器适配器<br /> 在spring3.1之前,使用org.springframework.web.servlet.mvc.annotation.<br />AnnotationMethodHandlerAdapter注解适配器<br />在spring3.1之后,使用org.springframework.web.servlet.mvc.method.annotation.<br />RequestMappingHandlerAdapter注解适配器。<br /> (3)配置注解的处理器映射器和处理器适配器<br /> 因为springmvc.xml会默认加载注解的映射器和适配器,但是默认加载的已经是<br /> 旧版本的了,不适合现在使用。所以需要自己配置注解的映射器和适配器。<br /> A、处理器映射器<br /> 配置:<bean class="org.springframework.web.servlet.mvc.method.<br />annotation.RequestMappingHandlerMapping"></bean><br /> B、处理器适配器<br /> 配置:<bean class="org.springframework.web.servlet.mvc.method.annotation.<br />RequestMappingHandlerAdapter"></bean><br /> C、配置mvc的注解驱动(实际开发中使用这种方式)<br /> 配置:<mvc:annotation-driven></mvc:annotation-driven><br /> 作用:代替了上边的注解映射器和注解适配器的配置。默认还加载了很多<br />的参数绑定方法。比如:json转换解析器就默认加载了。<br /> (4)编写注解Handler<br /> 注解的映射器和注解的适配器必须配对使用。<br /> 代码实现:SpringMVC_day01项目 Controller包的ItemsController3<br /> @Controller<br /> 包:org.springframework.stereotype.Controller<br /> 使用:在类上使用<br /> 作用:指定这个类是一个注解的Handler/Controller <br /> <br />@RequestMapping(“url”)<br /> 包:org.springframework.web.bind.annotation.RequestMapping<br />使用:在方法上使用<br /> 作用:指定url,访问此url时就调用此方法。建议将方法名和url一样。<br /> url后可加.action也可以不加。<br /> <br />(5)在spring容器中加载Handler<br /> 位置:在springmvc.xml中<br /> 配置:使用bean标签,只需要指定class属性即可。<br /> <bean class="Controller.ItemsController3"></bean><br /> 实际开发中建议使用组件扫描,标签:<context:component-scan> <br /> <context:component-scan base-package="Controller"></context:component-scan><br /> <br />8、视图解析器配置前缀和后缀<br /> 作用:配置了前缀和后缀后,在ModelAndView中不用在设置复杂的jsp路径了。<br /> 配置:<property><br /> 属性:prefix 指定视图路径的前缀<br /> suffix 指定视图路径的后缀<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012155625-4bfdb232-1a6e-4d32-9855-1157fb283a27.png#height=32&width=291)<br /> 处理器Handler的代码中:<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012155815-7cf9bc32-f77e-4944-a432-2f3e13864393.png#height=19&width=287)<br /> <br />9、springmvc和mybatis的整合(掌握)<br /> (1)需求:使用springmvc和mybatis来完成商品列表查询<br />(2)整合思路 ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012156035-65c3a852-21a9-4b09-92c4-0c6eff275c05.png#height=161&width=385)<br /> <br /> 第一步:整合dao层<br /> Mybatis和Spring的整合,通过Spring来管理mapper接口<br /> 使用mapper的扫描器自动扫描mapper接口在spring进行注册<br /> 第二步:整合service层<br /> 通过Spring来管理Service层<br /> 使用xml配置方式将service层配置在spring的配置文件中<br /> 实现事务控制<br /> 第三步:整合springmvc<br /> Springmvc是Spring的模块,不需要整合<br />(3)环境准备<br /> 第一步:创建项目<br /> 创建SSM项目<br /> 第二步:导入jar包<br /> jar包的路径在:G:\jar包\SSM包<br /> 第三步:创建包<br /> 创建Service,Mapper,Domain,Controller包<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012156353-49352127-747f-4d2b-9c4f-a62b5058a496.png#height=71&width=104)<br /> 第四步:创建Source Folder<br /> 创建名为:config的Source Folder<br /> 创建相关的配置文件:db.properties log4j.properties SqlMapConfig.xml<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012156493-def6d246-1ff5-45ae-81ad-d62abf9ef0f9.png#height=64&width=139)<br /> (4)整合dao层(Mapper包)<br /> Spring和mybatis的整合<br /> 第一步:编写SqlMapConfig.xml<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012156678-b6720a13-f9d6-4791-8a20-fc8e0a92bf96.png#height=167&width=327)<br /> 第二步:编写applicationContext.xml<br /> 配置SqlSessionFactory,dataSource,Mapper扫描器。(略)<br /> 第三步:逆向工程生成javabean类和Mapper类(单表的增删改查)<br /> 第四步:编写商品查询mapper.java和mapper.xml(略)<br /> (5)整合Service层(Service包)<br /> Spring来 管理Service层。<br /> 第一步:编写ItemsService(略)<br /> 第二步:在applicationContext.xml中配置Service层(略)<br /> 不需要使用<context:component-scan>标签<br /> 第三步:在applicationContext.xml中配置事务控制(xml配置方式)<br /> 对mybatis操作数据库进行事务控制,spring使用jdbc的事务控制类。<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012156966-17648462-a925-45cc-b844-f2c728d1255f.png#height=154&width=329)<br /> (6)整合Controller层(Controller包)<br /> 第一步:配置处理器映射器,视图解析器,处理器适配器<br /> 第二步:配置前端控制器<br /> 第三步:编写Handler<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012157204-369c8f13-e27b-4ebe-8eef-a57aecadfc9a.png#height=128&width=302) <br /> 第四步:编写itemsList.jsp页面(略)<br /> (7)自动加载Spring容器<br /> 在web.xml中配置Spring监听器,监听器会自动创建Spring容器。<br /> 可以使用通配符的方式来加载多个Spring配置文件:applicationContext-*.xml<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012157440-c002df35-2bcd-4edb-ac14-994c3923f959.png#height=97&width=351)<br /> <br />10、springmvc的注解开发<br /> 代码实现:SSM项目<br /> 需求:修改商品的信息<br /> 操作流程:<br /> 1、进入商品查询列表页面<br /> 2、点击修改,进入商品修改页面,页面中显示了要修改的商品<br /> 根据商品的id查询商品信息<br /> 3、在商品修改页面,修改商品信息,修改后,点击提交<br /> 根据商品的id更新商品信息<br /> 第一步:开发Mapper包<br /> Mapper:<br /> 根据id查询商品信息<br /> 根据id更新Items表的数据<br /> A、编写mapper.xml<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012157682-ad5de48f-0c6c-4600-8be8-be88f43e2996.png#height=72&width=332)<br /> B、编写mapper.java<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012157874-00b4052f-012d-4830-9628-7e10ab8c9d67.png#height=69&width=338)<br /> 第二步:开发Service包<br /> Service:<br /> 根据id查询商品信息<br /> 修改商品信息<br /> 第三步:开发Controller包<br /> 方法:<br /> 商品信息修改页面显示<br /> 商品信息修改的提交<br /> <br />11、@RequestMapping<br />作用:<br /> (1)在方法上使用,定义controller方法对应的url<br />(2)在类上使用,定义Controller类的访问url根路径<br /> (3)限制HTTP的请求方法<br /> 属性:value 指定访问的url<br /> method 数组 {} 限定此url的访问方法为POST或GET<br /> 值为:RequestMethod.XXX<br /> <br />12、Controller方法的返回值:<br />(1)ModelAndView<br /> 需要在方法结束时,定义ModelAndView,将model和view分别进行设置。<br />(2)String<br /> A、表示返回逻辑视图名。<br /> 真正视图(jsp路径)=前缀+逻辑视图名+后缀<br /> 方法中添加Model类型的形参,添加数据时,使用<br /> addAttribute(String ,Object object)方法<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012158117-655ff68a-81d1-4d3a-9667-4110479b8822.png#height=81&width=286)<br /> B、redirect重定向<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012158289-16e48894-f6a2-4d4b-b6bf-e906c38f6046.png#height=28&width=268)<br /> C、forword页面转发<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012158465-53b957c3-8129-49d8-9d35-e54b948ad637.png#height=27&width=258)<br />(3)void<br /> 在controller方法的形参中定义request和response,根据这两个变量可以实现转发<br />和重定向和添加request域数据。<br /> <br />13、参数绑定<br />SpringMVC的参数绑定过程:<br />从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller<br />方法的形参上。<br /> SpringMVC的参数接收:<br />接受页面提交的数据是通过方法形参来接收,而不是定义成员变量来接收。<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012158703-5dffd855-a519-4b89-922d-e81597e5bce2.png#height=170&width=331) <br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012158885-8ba1a70b-48f8-4228-a6ed-e9000fc03e07.png#height=46&width=305)<br /> (1)默认支持的类型<br /> 直接在Controller方法形参上定义下边类型的对象,就可以使用这些对象。在<br /> 参数绑定过程中,如果遇到下边类型直接进行绑定。<br /> A、HttpServletRequest<br /> 通过request对象获取请求信息<br /> B、HttpServletResponse<br /> 通过response处理响应信息<br /> C、HttpSession<br /> 通过session对象得到session中存放的对象<br /> D、Model/ModelMap<br /> model是一个接口,modelMap是一个接口实现<br /> 作用:将model数据填充到request域<br /> (2)简单类型<br /> A、形参中定义的简单类型变量名和页面所传的参数名必须一致,才能绑定。<br /> B、使用@RequestParam对简单类型参数进行绑定时,不用限制变量名和参数<br />名一致。<br /> 使用的位置:在Controller方法的形参中使用<br /> 属性:value 指定页面传入的参数名<br /> required 指定参数是否必须要传入<br /> defaultValue 如果参数没有传入,可以设置参数的默认值<br />在注解后面则是需要和参数名绑定在一起的方法形参名。<br /> (3)javabean对象<br /> 条件:<br /> 页面中name属性和controller的形参的javabean对象的属性名称一致。<br /> 遇到的问题:post乱码<br /> 解决的办法:在web.xml中添加post乱码过滤器<br /> <br /> Get乱码: <br />(1)修改tomcat配置文件,添加编码与工程编码一致<br /> <Connector URIEncoding=”utf-8” connectionTimeout=”20000” port=”8080”<br /> Protocol=”HTTP/1.1” redirectPort=”8443”/><br />(2)对参数进行重新编码<br /> String userName=new String(request.getParamter(“userName”).<br />getBytes(“ISO8859-1”),”utf-8”);<br /> (4)自定义参数绑定<br /> 需求:将页面请求的日期数据串(字符串)转成日期类型,要转换的日期<br /> 类型和对象中日期属性的类型保持一致。<br /> 概述:对于Controlller方法的形参中有javabean对象,如果属性中有日期类<br />型,需要自定义参数绑定。<br /> A、在springmvc.xml中配置<br /> 需要向处理器适配器中注入自定义的参数绑定组件。即向<br /><mvc:annotation>标签配置conversion-service属性,值为参数绑定组<br />件bean的id。 <br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012159079-89315ff8-5148-4c32-b9b1-973e6aed8452.png#height=39&width=415)<br />标签:<bean> 配置参数绑定组件<br />类:org.springframework.format.support.<br />FormattingConversionServiceFactoryBean<br /> 属性:id 指定参数绑定组件的id<br /> class 指定参数绑定组件的全类名<br /> 子标签:<property><br /> 属性:name 指定为converters<br /> 子标签:<list><br /> 子标签:<bean> 配置自定义的参数绑定类<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012159477-7cbd60b3-42fc-41f1-a6c7-8be34be7ada7.png#height=117&width=330)<br /> B、编写自定义参数绑定类<br /> 要求:必须实现Converter<T,S>类<br /> T:什么类型要转换<br /> S:要转换成什么类型<br /> 实现的类:org.springframework.core.convert.converter.Converter<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012160422-6ccb81e6-398e-49dc-b54a-ed10233fec25.png#height=143&width=383)<br /> <br />11、springmvc和struts2的区别<br /> (1)springmvc是基于方法开发的,struts2是基于类开发的<br /> Springmvc将url和controller方法映射,映射成功后,springmvc生成一个Handler<br /> 对象,对象中只包括了一个method。方法执行结束,形参数据销毁。<br /> Springmvc的controller方法开发,类似于service层开发。<br />(2)springmvc可以进行单例开发,并且建议使用单例开发。Struts2通过类的成员变<br /> 量来接收参数,无法使用单例开发,只能使用多例开发。<br />(3)经过实际测试,struts2速度慢,在于使用了struts标签,使用struts建议使用jstl。<br /> 第二天(高级应用)<br />1、包装类型的javabean参数绑定<br /> 需求:商品查询实现商品查询条件<br /> 代码实现:SSM项目<br /> 实现方法:<br /> 第一种:在形参中添加HttpServletRequest request参数,通过request接收查<br />询条件参数(不建议使用)<br /> 第二种:在形参中让包装类型的javabean对象来接收查询条件参数<br /> 页面参数和controller方法形参的定义:<br /> 页面参数:商品名称:<input type="text" name="itemsCustom.name"><br /> 使用“对象.属性名”的形式来传参给形参<br /> Controller方法形参:<br />public ModelAndView findAllItems(ItemsQueryVo itemsQueryVo) throws Exception{<br /> <br />2、集合类型的参数绑定<br />(1)数组类型<br /> 需求:商品批量删除,用户在页面选择多个商品,进行批量删除<br /> 页面参数和controller方法形参的定义: <br />页面:<input type="checkbox" name="items_id" value="${item.id}"><br />Controller方法实现:<br /> public String deleteItems(Integer[] items_id) throws Exception{<br />(2)list类型<br /> 通常在需要批量提交数据时,将提交的数据绑定到list<javabean对象>中<br /> 需求:批量商品修改,在页面输入多个商品信息,将多个商品信息提交到controller<br />方法中。<br /> 页面参数和controller方法形参的定义:<br /> Controller方法定义:<br /> 1、进入批量商品修改页面(页面样式参考商品列表实现)<br /> 2、批量修改商品提交<br /> 使用List接受页面提交的批量数据,通过包装类接收,在包装类中定义list<br />属性。<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012160648-9d70be5c-3468-4a34-94ff-a40ff38caa3d.png#height=68&width=415)<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012160825-73bb35a7-2a45-4adb-9d5f-84f5ed8103d7.png#height=99&width=415)<br /> 页面:<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012161050-3f673fa5-982d-4b83-88d4-cd33cfd56b90.png#height=79&width=381)<br />3、Springmvc的服务端校验<br /> (1)校验理解<br /> 项目中,通常使用较多是前端的校验,比如页面中js校验,对于安全要求较<br />高点建议在服务端进行校验。<br />服务端校验:<br /> 控制层ocntroller:校验页面请求的参数的合法性。在服务端控制层<br /> controller校验,不区分客户端类型(浏览器、手<br />机客户端、远程调用)<br />业务层service(使用较多):主要校验关键业务参数,仅限于service接<br />口中使用的参数<br /> 持久层dao/Mapper:一般是不校验的。<br /> (2)springmvc校验<br /> springmvc使用hibernate的校验框架(和hibernate没有任何关系)<br /> 校验思路:<br /> 页面提交请求的参数,请求到controller方法中,使用validation进行<br />校验。如果校验出错,将错误信息展示到页面。<br /> 需求:商品修改,添加校验(校验商品名称长度,生产日期的非空校验),如<br />果校验出错,在商品修改页面显示错误信息。<br /> 代码实现:SSM项目<br />(3)准备环境<br /> Hibernate的validation校验框架所需的jar包。<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012161211-dc5ec929-baef-4313-87a1-66ddb92469cb.png#height=56&width=180)<br />(4)配置校验器<br /> 校验器是由Handler执行的。<br /> 校验类:<br /> org.springframework.validation.beanvalidation.LocalValidatorFactoryBean<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012161400-565238d6-8ab7-47c0-b7a2-4b394419d937.png#height=69&width=416)<br /> <br />校验错误信息类:<br />org.springframework.context.support.ReloadableResourceBundleMessageSource<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012161611-6a7e0258-9eb0-47d8-8f81-76990a3b3d28.png#height=118&width=415)<br />(5)将校验器注入到处理器适配器中<br /> 配置<mvc:annotation-driven>标签的属性validator。<br /> validator:引用校验器的id<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012161809-5405957f-b951-48dd-b18d-eaef037a3f8d.png#height=32&width=415) (6)在javaBean类中添加校验规则<br /> 在Items.java中添加校验规则: ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012162009-828d206e-085c-4069-b163-dfdaa7ff013b.png#height=60&width=415)<br /> <br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012162226-3b6c3bf9-bf54-49ce-a11a-d57abce6a3c8.png#height=58&width=415)<br /> <br />(7)编写校验错误提示文件:CustomValidationMessages.properties ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012162454-2164dcc5-320b-4e37-b688-83153c9abaa8.png#height=41&width=415)<br /> (8)捕获校验错误信息<br />在需要校验的Controller方法的形参前添加:@Validated<br /> 在形参后添加多一个BindingResult类型的参数,用来接受错误信息。<br /> @Validated和BindingResult是配对出现的。并且顺序是固定的(一前一后)<br /> BindingResult的方法:<br />判读是否有错误:hasErrors()<br />获取错误信息对象:getAllErrors() 返回值List<ObjectError><br />ObjectError的方法:<br />获取错误信息字符串:getDefaultMessage()<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012162708-139db20c-52ea-4e69-a6fd-1d39b7492dd3.png#height=124&width=373)<br /> (9)在页面中显示校验错误信息<br /> 在Contorller方法中将错误信息传到页面即可。<br /> 使用Model对象的addAttribute(“”,Object)方法<br /> 页面显示错误信息:<br /> 1、在java代码中获取错误信息字符串是通过get方法<br /> 2、在页面中使用jstl表达式时,直接“.属性名”即可,属性名第一个<br />字母小写。<br /> <c:forEach items="allErrors" var="errors"><br /> ${errors.defaultMessage}<br /></c:forEach><br />(10)问题总结<br />在javabean类中定义校验规则,而该类是被多个Controller方法所共用,当不同的Controller方法对同一个类进行校验,但是每个Controller方法需要不同的校验规则。此时就需要进行分组校验了。<br /> (11)分组校验<br /> 需求: 商品修改提交时,只校验商品名称,不校验商品的生产日期是否为空。<br /> 代码实现:SSM项目 Validation包<br /> 解决办法:定义多个校验分组(是一个java接口),每个Controller方法<br /> 使用不同的校验分组。<br /> A、创建一个包,包内定义校验分组的接口<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012162872-959ae155-ab36-4d8c-b177-ed1150ece37a.png#height=48&width=129)<br /> B、接口中不需要定义任何方法,仅是对不同的校验规则进行分组 ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012163087-0609245f-b65d-41ce-bf59-f11a491d52b3.png#height=90&width=342)<br /> C、在校验规则中添加分组<br /> 在javabean类中的属性上方的校验规则注解中添加属性grounps<br /> 属性:groups 指定校验分组的类名<br /> 类型:Class[]<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012163285-0c050773-f06f-4fa0-887e-5811f9d63f6f.png#height=18&width=288)<br /> D、在Controller方法使用指定的分组校验<br /> 在@Validated内添加属性value。<br /> 属性:value 指定校验分组的类名<br /> 类型:Class[]<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012163526-d9b14dd0-7cdc-4354-bcf4-f91aeb6c5995.png#height=31&width=357)<br />4、数据回显<br /> 概述:提交失败后,将刚才提交的数据回显到刚才的提交页面。<br /> (1)javabean数据回显方法<br /> 1、Springmvc默认对javabean对象的数据进行回显<br />Javabean对象的数据传入Controller方法后,springmvc自动对象放入<br />request域,key为类名(首字母小写)。<br /> 2、@ModelAttribute(“”)<br /> 作用:<br />(1)使用在行参前,用来指定javabean对象回显到页面request中<br />的key<br /> (2)使用在方法上方,表示将方法的返回值传到request域中,作<br />为key<br /> 3、最简单的方法<br /> 使用Model对象的addAttribute()方法,将对象加入Model。<br /> (2)简单类型<br /> Springmvc默认不支持对简单类型进行回显。需要使用Model对象的<br />addAttribute()方法。<br /> <br />5、异常处理<br /> (1)异常分类<br /> 预期异常:通过捕获异常从而获取异常信息<br /> RuntimeException:通过代码开发、测试手段减少运行时异常的发生<br /> (2)异常处理思路<br />Springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。<br /> (3)异常处理的步骤:<br /> 对于RuntimeException则抛出“未知错误”,预期异常则对应各自错误。<br />A、自定义异常类<br /> 对不同的异常类型定义异常类,继承Exception。<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012163752-fa7f36fb-2eea-490f-bba1-af31026527be.png#height=146&width=415)<br /> B、编写全局异常处理器<br /> 抛异常的步骤:dao抛给service,service抛给controller,controller<br />抛给前端控制器,前端控制器调用全局异常处理器。<br /> 全局异常处理器的处理思路:<br /> 1、解析出异常类型<br />2、如果该异常类型是系统自定义异常,直接取出异常信息,在错误<br />页面展示。<br />3、如果该异常类型不是系统自定义的异常,构造一个自定义的异常<br />类型(异常信息为“未知错误”))<br /> 实现的接口:HandlerExceptionResplver<br /> 必须实现的方法的形参:<br /> 1、Object类型的形参:处理器适配器要执行的Handler对象(只<br />有映射的那个method)<br /> 2、Exception类型的形参:系统抛出的异常<br /> <br />C、编写错误页面<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012163961-2e8ef9f4-90f4-4f56-9bc7-4f8bed9cd0aa.png#height=108&width=224)<br /> D、在springmvc.xml中配置全局异常处理器<br /> 只要实现了HandlerExceptionResolver接口,就是全局异常处理器。<br /> <bean class="Exception.CustomExceptionResolver"></bean><br /> E、异常测试<br /> 在controller、service、dao中任意一处手动抛出异常。<br /> 如果是程序中手动抛出异常,在错误页面中显示自定义的异常信息,如果<br /> 不是手动抛出异常,说明是一个运行时异常,在错误页面显示“未知错误”。<br /> <br /> 在商品查询的controller方法内抛出异常:<br /> if(itemsCustom==null) {<br /> throw new CustomException("修改的商品不存在!");<br /> }<br /> 如果与业务功能相关的异常,建议在service层中抛出异常<br /> 如果与业务功能没有关系的异常,建议在contorller方法中抛出异常<br />3、上传图片<br /> (1)需求:在修改商品页面,添加上传商品图片的功能<br /> (2)Springmvc中对多部件类型解析<br /> 在页面form中提交enctype=”multipart/form-data”的数据时,需要<br />Springmvc对multipart类型的数据将进行解析。<br />在springmvc.xml中配置multiparat类型解析器:<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012164210-e8996e9d-c856-4c46-806f-fe474fd13a5a.png#height=90&width=415) <br /> (3)导入jar包<br /> 解析器需要使用以下的jar包。<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012164379-c32a53d4-17a0-4576-84e9-95558bd00fce.png#height=36&width=155)<br />(4)创建图片的虚拟目录来存储图片<br /> 两种方法:<br /> 第一种:通过修改tomcat的配置文件(server.xml)<br /> <Context docBase=”G:\upload\temp”path=”/pic”<br />reloadable=”false”/><br /> 第二种:通过图形界面的形式 ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012164548-d753e440-bf99-479c-876e-3f8db488d7de.png#height=113&width=416)<br /> 注意:在图片的虚拟目录中,一定将图片目录分级创建(提高i/o性能),一<br />般我们采用按日期(年、月、日)进行分级创建<br /> (5)编写上传图片的代码<br /> 修改controller方法的更新商品的代码。<br /> 第一步:在方法中添加形参来接受商品图片<br /> MultipartFile items_pic<br />第二步:编写上传图片的代码 ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012164749-90b6101c-aa50-442a-981a-9d34f80b289c.png#height=163&width=364)<br /> <br />(6)编写jsp页面<br /> input标签的name属性必须和形参名一致。<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012164971-85422488-f1c5-48fd-bc1b-19f637ce41df.png#height=70&width=320)<br /> <br />4、json数据交互<br />(1)为什么要进行json数据交互<br /> json数据格式在接口调用中、html页面中较常用,json格式比较简单,解析比<br />较方便。<br />(2)springmvc进行json交互<br /> 1、请求json(@RequestBody),输出json(@ResponseBody),要求请求的是json<br />串,所以在前端页面中需要将请求的内容转成json,不太方便<br /> 2、请求key/value,输出json串(@RespnseBody)。此方法比较常用。<br />(3)环境准备<br /> 1、springmvc默认用MappingJacksonHttpMessageConverter对json数据进行<br />转换,需要加入jackson的包,如下图:<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012165169-5ce583b4-e12c-4d7e-aeae-5b2126f5b047.png#height=51&width=156)<br /> 2、配置json转换器<br /> 第一种:如果是单独配置了处理器适配器,需要在内部配置json转换器<br /> <property name=”messageConverters”><br /> <list><br /> <bean class=”..MappingJackonHttpMessageConverter”><br /></bean><br /> </list><br /> <property><br /> 第二种:如果使用了<mvc:annotation-driven/>,则不用定义上边内容<br /> (4)json交互的测试<br /> 代码测试:SSM项目 jsp/jsonTest.jsp页面<br /> 1、输入的json串,输出的是json串<br /> A、编写一个jsp页面<br /> 使用jquery的ajax提交json串,对输出的json结果进行解析。<br /> 需要设置contentType为:application/json;charset=utf-8;<br /> B、编写controller方法<br /> 2、输入key/value,输出的是json串<br /> A、编写一个jsp页面<br /> 使用jquery的ajax提交json串,对输出的json结果进行解析。<br /> 不需要设置contentType,使用默认的即可。 <br />B、编写controller方法<br />5、RESTful的支持<br />(1)什么是RESful<br /> 其实就是一个开发理念,是对http的很好的诠释。<br /> 1、对url进行规范,写RESTful格式的url<br /> 非REST的url:[http://...//queryItems.action?id=001&type=T01](http://.../queryItems.action?id=001&type=T01)<br /> REST的url风格:[http://...items/001](http://...items/001)<br /> 特点:url简洁,将参数通过url传到服务端<br /> <br />2、对http的方法进行规范(实际应用时并没有遵循)<br /> GET:获取资源 POST:新建资源或更新资源 PUT:更新资源 DELETE:删除资源<br /> 不管是删除、添加、更新, 使用的url是一致的,如果进行删除,需要<br />设置http的方法为delete。后台controller方法,判断http方法,如<br />果是delete执行删除,如果是post执行添加。<br /> <br />3、对http的contentType规范<br /> 请求时指定contenteType,要json数据,设置成json格式的type。<br />(2)RESTful的例子<br /> 实现了以上的1和3两个规范。<br /> 需求:查询商品信息,返回json数据<br /> 1、controller方法<br /> A、定义方法,进行url映射,使用RESTful风格的url,将查询商品信息的<br />id传入controller方法。<br />(1)URL模版映射<br /> {XXX}占位符,通过在方法中使用@PathVariable获取{XXX}的值<br /> @PathVariable用于将请求URL中的模版变量映射到功能处理方<br />法的参数上 <br /> (2)配置支持RESTful风格url的前端控制器 ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012165359-6338b077-6906-48b0-8cd3-d79c881418c9.png#height=26&width=305)<br />B、输出json,使用@ResponseBody将java对象输出json<br /> (3)对静态资源的解析<br /> 问题:配置前端控制器的url-pattern为/时,对静态资源的解析会出现问题。<br /> 解决方法:在springmvc.xml中配置静态资源的解析方法<br /> 静态资源的种类:js,css,image,<br />配置:<br /> 标签:<mvc:resources/><br /> 属性:<br /> location 静态资源的前缀路径<br /> mapping 静态资源映射的真实路径 使用通配符<br /> ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012165577-9c7752fe-8ddb-41df-b2d1-1b7f768092e4.png#height=22&width=287)<br />6、拦截器<br />(1)拦截器定义<br /> 实现HandlerInterceptor接口。接口中提供三个方法:<br /> A、preHandle<br /> 执行时间:进入Handler方法之前执行,<br />作用:用于身份认证、身份授权<br /> 例子:比如身份认证,如果认证不通过标识当前用户没有登陆,需要此方<br />法拦截不向下执行。<br />return false 表示拦截,不向下执行<br />return true 表示放行<br /> B、postHandle<br /> 执行时间:进入Handler方法之后,返回modelAndView之前执行<br /> 作用:从modelAndView出发,将公用的模型数据在这里传到视图,也可<br />以在这里统一指定视图<br /> C、afterCompletion<br /> 执行时间:执行Handler后执行此方法<br />作用:统一异常处理,统一日志处理<br />(2)拦截器配置<br /> Springmvc拦截器针对HandlerMapping进行拦截设置<br /> 如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的<br />Handler最终才使用该拦截器。<br />A、针对HandlerMapping进行拦截设置(一般不推荐使用)<br /> 如果在某个HandlerMapping中配置拦截,经过该HandlerMapping映射成功的<br />Handler最终才使用该拦截器。<br /> 在某个HandlerMapping内配置:<br /> <property name=”interceptors”><br /> <list><br /> <ref bean=”拦截器bean的id”><br /> <list><br /> <property><br />B、类似全局的拦截器配置<br /> 标签:<mvc:interceptors> 多个拦截器,按顺序执行<br /> 子标签:<mvc:interceptor><br /> 子标签:<mvc:mapping path=””><br />指定拦截的url路径 /**表示拦截所有url路径和子路径 <bean class=“”> 指定拦截器<br />(3)多个拦截器测试<br /> 需求:拦截器1和拦截器2都放行 <br />A、编写两个拦截器<br /> 代码实现:SSM项目 Interceptor.HandlerInterceptor1/2<br /> B、控制台打印结果<br /> HandlerInterceptor1...preHandle<br />HandlerInterceptor2...preHandle<br />HandlerInterceptor2...postHandle<br />HandlerInterceptor1...postHandle<br />HandlerInterceptor2...afterCompletion<br />HandlerInterceptor1...afterCompletion<br />C、总结<br /> preHandle方法按顺序执行<br />postHandle和afterCompletion按逆向顺序执行<br /> <br />需求:拦截器1放行,拦截器2不放行<br /> A、编写两个拦截器<br /> 代码实现:SSM项目 Interceptor.HandlerInterceptor1/2<br /> B、控制台打印结果<br /> HandlerInterceptor1...preHandle<br />HandlerInterceptor2...preHandle<br />HandlerInterceptor1...afterCompletion<br />C、总结<br /> 拦截器1放行,拦截器2 preHandle才会执行。<br /> 拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion<br />不会执行。<br />只要有一个拦截器不放行,postHandle都不会执行。<br /> <br />需求:拦截器1不放行,拦截器2不放行<br /> A、编写两个拦截器<br /> 代码实现:SSM项目 Interceptor.HandlerInterceptor1/2<br /> B、控制台打印结果<br /> HandlerInterceptor1...preHandle<br />C、总结<br /> 拦截器1不放行,拦截器2 不会执行。<br /> <br />(4)小结<br /> 根据以上测试结果,对拦截器应用。<br /> 比如:统一日志处理拦截器,一定要该拦截器放行且放在拦截器链第一的位置 比如:登陆认证拦截器,放在拦截器链中第一个。权限校验拦截器,放在登陆 认证拦截器之后(因为登陆成功后才校验权限)<br />(5)实现登陆认证拦截器<br /> 需求:用户请求url,拦截器进行拦截校验,如果用户session不存在,跳转到登<br />陆页面,如果用户session存在,放行。<br />如果请求的url是公开地址(无需登陆就可以访问),放行。<br />A、编写拦截器 ![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012165821-92f01f4f-801d-4256-87d7-39ac40c673da.png#height=104&width=344)<br /> B、配置拦截器(略)<br /> C、编写controller方法<br />![](https://cdn.nlark.com/yuque/0/2020/png/471109/1608012166002-f66e845f-5f2a-4076-83ff-25ac6a07b298.png#height=140&width=415)