SpringMVC细致讲解

SpringMVC基本用法

SpringMVC是Spring框架的一个模块,SpringMVC和Spring无需通过中间整合层进行整合。SpringMVC是一个基于MVC的web框架,即Spring Web MVC。Spring Web MVC和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来:
在这里插入图片描述

Web MVC原理

首先来一下MVC,MVC是一种开发模式,在大量的软件开发过程中所积累出来的经验,然后根据经验抽象出来的一种开发模式。下面来看一下MVC设计模式B/S架构的系统下的应用:
在这里插入图片描述

SpringMVC框架原理

从上图中看到MVC的基本框架后,那么下面学习SpringMVC框架就有了一个大体的思路。因为SpringMVC就是MVC模型的一种框架。所以学习SpringMVC框架主要就是来看SpringMVC中的C(控制层)、M(模型层)、V(视图层)的各种技术实现即可。如下图所示:
在这里插入图片描述

  • 根据上图所示,使用SpringMVC的步骤如下:
    1、 发起请求到前端控制器DispatcherServlet
    2、 前端控制DispatcherServlet请求HandlerMapping查找Handler,(XML配置或注解)
    3、 处理器映射器HandlerMapping向前端控制器返回handler
    4、 前端控制器调用处理器适配器去执行handler
    5、 处理器适配器执行handler
    6、 handler执行完成后返回给处理器适配器ModelAndView(SpringMVC框架的一个底层对象,包括model、view)
    7、 处理器适配器向前端控制器返回ModelAndView
    8、 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
    9、 视图解析器向前端控制器返回view
    10、前端控制器进行视图渲染,将模型数据(在ModelAndView)填充到request域中。
    11、前端控制器向用户响应结果。
  • 以上步骤涉及到的组件:
    1、 前端控制器DispatcherServlet,作用:接收请求,响应结果,相当于转发(不需要程序人员开发)
    2、 处理器映射器HandlerMapping,作用:根据请求url查找handler(不需要程序人员开发)
    3、 处理器适配器HandlerAdapter,作用:按照特定的规则去执行handler,所谓的特定规则,即HandlerAdapter指定的规则。(不需要程序人员开发)
    4、 Handler处理器。(需要程序人员开发)
    5、 视图解析器Viewresolver,作用:进行视图解析,根据逻辑视图名解析成真正的视图view(不需要程序人员开发)
    6、 视图View,作用:View是一个接口,实现类支持不同的View类型(jsp、freemarker等)(需要程序人员开发,View不需要但是页面需要开发)
SpringMVC入门程序

以商品订单管理为例进行测试开发,涉及表用户表、订单表、订单明细、商品明细表。
第一步:配置SpringMVC的前端控制器
SpringMVC的前端控制器是个Servlet,所以在web应用的web.xml文件中来配置该前端控制器,如下图所示:
在这里插入图片描述
servlet配置完成后,需要对该servlet类来配置相应的servlet-mapping如下图所示:
在这里插入图片描述
url-pattern的配置有两种方式:
第一种: * .action;访问以.action结尾的任何请求都由DispatcherServlet进行解析。
第二种:/,所有访问的地址(jsp除外)都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析,使用此种方式可以实现RESTful风格的url。
第三种: /* , 所有的地址都解析.
第二步:配置处理器适配器
在classpath下的springmvc.xml文件中配置处理器映射器。SpringMVC框架是Spring的一个内部模块,所以springmvc.xml文件肯定需要同spring的配置文件兼容,即保持相同的头信息。如下所示:
在这里插入图片描述
配置完成适配器,适配器的作用就是来执行相应的Handler处理器,那么怎么编写代码才算是一个Handler处理器,通过SimpleControllerHandlerAdapter的原码查看,此类中包含如下一个方法supports,如下所示:
在这里插入图片描述
通过此方法可以得知,只有实现了Controller接口的类,才能够被Handler适配器当成是Handler处理器来进行调用。所以进入下一步,编写Handler。
第三步:编写Handler
在这里插入图片描述
在这里插入图片描述
第四步:配置处理器映射器
在springmvc.xml文件中配置处理器映射器,如下所示:
在这里插入图片描述
上图中的queryItemList.action就是应用中访问的url路径。
第五步:配置视图解析器
在springmvc.xml文件中配置是解析器,如下所示:
在这里插入图片描述
prefix属性:执行访问路径中固定的前缀路径。
suffix属性:执行访问路径中固定的后缀路径。
使用此种方式:第三步中的代码可修改如下:
XXX.setViewName(“item_list”);

5.4 非注解的处理器映射器、适配器

处理器映射器:
通过上面的入门程序中,对于处理器映射器BeanNameUrlHandlerMapping就是一个非注解的处理器映射器,只不过这个映射器稍微有点缺陷。缺陷就是不能对bean的url映射进行集中管理。
SpringMVC还提供了另外一个非注解的处理器映射器SimpleUrlHandlerMapping,这个映射器可以实现对bean
的url的集中管理,首先配置一个handler Bean通过bean ID与property元素中的prop子元素关联,key属性配置的是访问的业务的url,prop元素内容为bean ID,表示当访问到/queryItem1.action业务时,SpringMVC通过映射器查询到itemListhandler,然后将它交由Handler适配器去执行。如下所示:
在这里插入图片描述
注意:对于SpringMVC来说,可以让多个处理器映射器共存,由前端控制器判断用户请求的url能让哪些映射器来处理,就让哪个正确的的映射器处理。
适配器:
在上面的入门程序中,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter就是一个非注解的适配器。此适配器要求所有的Handler处理器必须实现Controller接口。使用方式参考入门程序。
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter是SpringMVC提供的另外一种非注解的处理器适配器,配置如下图所示:
在这里插入图片描述
查看该类的原码如下:
在这里插入图片描述
此适配器要求Handler处理器必须实现HttpRequestHandler接口,测试类如下所示:
在这里插入图片描述
通过上面测试类的编写,大家会发现这种编程非常类似JSP、Servlet中Servlet的代码编写。大家可能会认为这种方式不如上面实现Controller接口的handler更加直观。但是这种方式却比较灵活,因为实现Controller接口的handler返回值就是一个ModelAndView对象,如果需要服务器端响应后,返回json格式的数据,返回image对象数据,它就不能实现。而使用第二种方式,可以通过修改response对象,设置响应格式,所以在开发时可根据需要实现不同类型的handler。
总结:在SpringMVC中多个处理器映射器、适配器是可以共存的。通过用户访问的url路径映射到一个具体的handler对象后,SpringMVC来确定此handler的类型来决定此Handler应该交由哪种适配器去调用执行。
注意:如果在springmvc.xml文件即使不配置处理器映射器、处理器适配器,程序仍然可以正常执行,原因如下:在前端控制器DispatcherServlet所在的包org.springframework.web.servlet下包含一个DispatcherServlet.properites属性文件,在该文件中配置了大量的处理器映射器、处理器适配器、视图解析器等组件,如果在springmvc.xml配置文件中没有配置映射器、适配器,那么SpringMVC就使用该属性文件中默认配置的组件。

如下图所示:(截取属性文件部分内容 )
在这里插入图片描述
在上面的配置文件中同样存在使用注解的配置,AnnotationMethodHandlerAdapter、DefaultAnnotationhadnerMapping,只不过这种注解是比较原始的使用方式,在SpringMVC3.1之前使用,在SpringMVC3.1之后使用另一种注解处理器、适配器。

5.5 注解处理器映射器、适配器

5.5.1 配置注解的映射器、适配器
在这里插入图片描述
在3.1之后的注解的处理器映射器、适配器添加了很多的优化以及参数设置,所以在开发时,推荐使用3.1之后的版本。
在SpringMVC中提供了一个mvc:annotation-driven元素,用于简化映射器、适配器在springmvc.xml文件中的配置。不仅可以替代上面两行的配置,而且mvc:annotation-driven的驱动类还默认加载了多个参数绑定的方法,比如json转换解析器就默认加载。所以开发时推荐使用该方式。如下所示:
在这里插入图片描述
5.5.2 开发注解的处理器Handler
在这里插入图片描述
加载该Handler可以使用Spring的批量加载扫描的方式,如下所示:
在这里插入图片描述
小结:
处理器映射器:
非注解的处理器映射器(了解)
注解的处理器映射器(掌握)
对标记@Controller注解的类,Spring容器自动加载该Bean并管理,对于该Bean中的使用@RequestMapping注解进行修饰的方法进行映射。在@RequestMapping里边定义映射的url路径。使用注解的映射器不需要在xml中配置url和Handler之间的映射关系。
处理器适配器:
非注解的处理器适配(了解)
注解的处理器适配器(掌握)
注解的适配器与注解的映射器是配对使用,也就是说注解的适配器不能使用非注解映射进行映射。

5.6 Spring+SpringMVC+Mybatis整合开发

通过SpringMVC入门程序的学习,以及对非注解、注解处理器映射器、处理器适配器的了解,大体知道了SpringMVC的基本的开发流程,下面就以商品查询功能模块为示例,来学习Spring框架、SpringMVC框架、MyBatis框架的整合开发。
1、引入JAR包
首先将应用所需要的JAR包引入到项目中,包括log4j、mysql、dbcp、commons-io、spring、mybatis等Jar文件。
2、配置资源文件
配置相关的资源文件,比如log4j、数据库链接配置等,如下图所示:
在这里插入图片描述
3、mybatis的sqlMapConfig.xml
编写mybatis框架的配置文件sqlMapConfig.xml,在使用Spring框架进行整合开发时会加入不同框架的配置文件,为了能够方便管理,所以在开发时需要遵循一定的规范,即不同框架的配置文件,放在同的文件夹下单独管理。例如,mybatis的配置文件存储路径为:config/mybatis/sqlMapConfig.xml,如下图所示:
在这里插入图片描述
4、Spring与MyBatis整合
将Spring与mybatis进行整合,配置文件为applicationContext-dao.xml,如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
5、配置应用的Service层
使用Spring框架的配置文件,applicationContext-service.xml文件来配置管理应用的所有Service层。
在这里插入图片描述
6、配置事务管理
事务管理器:对mybatis数据库操作进行事务控制,spring使用jdbc的事务控制类实行事务管理,如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
7、配置SpringMVC控制层
SpringMVC的配置文件,主要配置视图解析器,处理器映射器、处理器适配器,在配置文件中使用mvc:annotation-dirven驱动来加载映射器与适配器。如下图所示:
在这里插入图片描述
8、配置Spring容器(重要)
以上所有配置文件配置完成后,在web.xml文件中通过配置SpringMVC的前端控制器,则可以完成将springmvc.xml配置文件加载到应用的容器中去,如下所示:
在这里插入图片描述
此操作仅仅是完成了SpringMVC模块的加载,但是Spring容器还没有加载到Web应用中来,所以下一步需要将Spring容器加载到Web应用的容器中,通过Spring框架提供的org.springframework.web.context.
ContextLoaderListener监听器来完成,此监听器在启动时会自动加载web.xml配置文件中的context-param元素中指定contextConfigLocation的value值,如下所示:
在这里插入图片描述
到此SpringMVC+Spring+Mybatis的整合全部结束!
5.7 商品查询调试
整合工作完成后,下面来开发商品管理功能模块来进行测试。

  • 5.7.1 dao开发
    1、mapper接口开发以及mapper.xml文件如下所示:
    在这里插入图片描述
    mapper.xml文件如下所示:
    在这里插入图片描述
    在这里插入图片描述
  • 5.7.2 service层开发
    在应用中对Service层使用xml的配置方式进行管理,而不使用spring的自动加载,这是因为在Handler层(Controller)层中对Service层的定义是通过接口定义的,例如ItemService itemservice = null;变量名为itemService而如果使用自动装配的话,那么对于Service层的所有的定义,变量名全部进行了限定。使用xml配置的方式反而更加灵活。如下所示:
    1、接口定义
    在这里插入图片描述
    2、实现类定义
    在这里插入图片描述
    在Spring的配置文件中,配置该Java Bean。对于Service中成员变量itemMapper要遵循一定的规范,Mapper是动态代理的,在Spring的dao配置文件中整合的时候已经被Spring容器加载进来,动态代理的Mapper的Bean Id为类名的首字母小写。而且在进行自动注入时需要通过byName的方式完成,所以变量名要写成Bean Id的值。
  • 5.7.3 Controller层开发
    下面来编写Controller层(Handler层),如下所示:
    在这里插入图片描述
    在Controller类中,使用注解@Controller进行修饰,由Spring框架完成自动加载,用户在访问该url:query_item_list.action时,SpringMVC根据此处理器映射器找到该类,然后再将该类交由SpirngMVC的处理器适配器与执行该类,最后返回一个view。
5.8 商品信息修改

在上面的示例中仅仅是完成最简单的操作,如果需要完成稍微复杂一点的开发,比如限制请求方式、往后台传入参数等,这就需要利用SpringMVC框架提供的注解@RequestMapping,以及处理器Controller层中方法的返回值以及传入参数来完成。本节示例—商品信息修改将利用这几点技术来完成,首先来看一下个技术点的内容。

  • 5.8.1 @RequestMapping
    通过RequestMapping注解可以定义不同的处理器映射规则。
    URL路径映射:@RequestMapping(value="/item")或@RequestMapping("/item),value的值是数组,可以将多个url映射到同一个方法。
    窄化请求映射:在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头,通过此方法对url进行分类管理。
    例如:
    @RequestMapping放在类名上边,设置请求前缀
    @Controller
    @RequestMapping("/item")
    方法名上边设置请求映射url:
    @RequestMapping放在方法名上边,如下:
    @RequestMapping("/queryItem.action ")
    访问地址为:/item/queryItem.action

请求方法限定:
限定GET方法
@RequestMapping(method = RequestMethod.GET)
如果通过Post访问则报错:
HTTP Status 405 - Request method ‘POST’ not supported
例如:
@RequestMapping(value="/editItem",method=RequestMethod.GET)

限定POST方法
@RequestMapping(method = RequestMethod.POST)
如果通过Post访问则报错:
HTTP Status 405 - Request method ‘GET’ not supported

GET和POST都可以
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})

  • 5.8.2 Controller方法的返回值
    在Controller层中,响应处理请求的方法,可以定义如下几种类型,返回一个ModelAndView或者返回一个String字符串,或者使用void修饰。
    返回ModelAndView
    controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。如下所示:
    在这里插入图片描述
    返回String字符串
    使用字符串作为返回值类型时,Controler层中的方法可以实现如下三种功能:1、返回逻辑视图名2、实现重定向3、实现请求转发
    1、返回逻辑视图名
    在这里插入图片描述
    在这里插入图片描述
    controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
    物理视图地址=视图解析器前缀+逻辑视图名+视图解析器后缀
    重点:使用逻辑视图名作为返回值时,就不需要使用ModelAndView这个数据模型对象来封装要显示的数据及显示的JSP页面了,但是String仅仅是表示转向的JSP页面而已,所以数据的封装可以使用形参来进行封装。Controller处理器默认可以使用的形参在后面会讲到。
    2、实现重定向
    重定向的原理与Servlet类中的重定向原理一致,问题是在SpringMVC中将数据模型model放 request域中,而重定向实际是发起了两次请求,那么在第一次请求中获取的数据,是无法与第二次的request进行共享,所以在重定向时,一般做法是让SpringMVC重新执行一次action动作,例如:商品修改完成后,返回到列表页面。
    示例如下:
    在这里插入图片描述
    选中一条记录进行修改,然后将获取到的商品ID放入一个form表单的隐藏域中,然后将隐藏域提交即可,隐藏域与修改的JQuery代码如下:
    隐藏域:
    在这里插入图片描述
    JQuery代码:
    在这里插入图片描述
    最终请求到query_item_forupdate,对应的Controller处理方法如下:
    在这里插入图片描述
    因为在Controller中已经存在一个根据ID来获取商品的方法,所以调用上面已有的方法,但是因为上面的方法返回的视图名不是query_item_forupdate要转到的页面,所以需要重写return语句。返回页面代码如下:
    在这里插入图片描述
    重点:在本次提交后完成重定向操作!
    在这里插入图片描述
    在返回的重定向的字符串中,redirect后面与冒号紧挨着,不能出现空格字符串,慎重!

3、实现请求转发
请求转发与Servlet中的请求转发一致,服务器的多次处理在一个请求范围内,所以数据模型model可以实现共享。如下所示:
在上例中加入商品修改完成后,转入详细页面,则代码如下:
在这里插入图片描述
在上面方法updateItem中返回的字符串为:forward:query_item_detail.action路径,也可以直接写成要访问的JSP页面,但是这样要考虑路径的问题,所以简单来做可以返回一个映射后的url,如query_item_detail.action。
注意:重定向和请求转发,在进行处理时,后面要跟的url是一个handler的url而不能是一个逻辑视图:即不能是一个普通的jsp的路径!

返回void
所谓的返回void实际上是利用了Controller方法的形参,request和response进行开发,变为原始的servlet开发方式了。
1、使用request进行请求转发
request.getRequestDispatcher(“url”).forwart(request,response);
2、使用response进行重定向
response.sendRedirect(“url”);
3、也可以通过response指定响应结果,例如响应json数据
response.setContentType(“application/json”);
response.getWriter().write(“json串”);

5.9 参数绑定

在上一节的内容中,我们看到Controller方法默认支持的形参中包括了request对象,可以通过request对象来获取客户端请求的key/value对的数据,把key/value对绑定到request对象中的这步操作是由SpringMVC框架中的参数绑定组件来帮我们完成的,这步操作就称为参数绑定。

  • 5.9.1 参数绑定过程
    参数绑定的实际过程如下:
    处理器适配器调用Springmvc提供参数绑定组件将key/value数据转成controller方法的形参
    参数绑定组件:在spirngmvc早期版本使用PropertyEditor(只能将字符串转成java对象),后期使用converter(进行任意类型的转换),spirngmvc提供了很多converter(转换器),在特殊情况下需要自定义converter
    例如:对日期数据绑定需要自定义converter
  • 5.9.2 SpringMVC默认支持的类型
    Controller处理器默认执行的形参如下:
    HttpServletRequest
    通过request对象获取请求信息
    HttpServletResponse
    通过response处理响应信息
    HttpSession
    通过session对象得到session中存放的对象
    Model/ModelMap
    ModelMap是Model接口的实现类,通过Model或ModelMap向页面传递数据
  • 5.9.3 SpringMVC支持的简单类型
    当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。默认支持的简单类型为:
    整型
    字符串
    单精度/双精度
    布尔类型
    例如:
    在这里插入图片描述
    // 在Contoller中的方法中直接获取该参数
    public String queryItemForUpdate(String itemId) throws Exception{
    // 可以直接拿到itemId
    }
  • 5.9.4 @RequestParam
    通过@RequestParam可以对简单类型的参数进行绑定。但是不用限制request传入参数名称和controller方法的形参名称一致。
    参考5.9.3中的示例程序可以修改如下:
    public String queryItemForUpdate(@RequestParam(“itemId”) String id) throws Exception{
    // 可以直接拿到itemId
    }
    这种情况下,SpringMVC就会将前面传过来的itemId绑定到参数id上面。
  • 5.9.5 绑定POJO类型(重点)
    普通pojo
    如果在controller的方法中直接定义pojo的形参,如果想要将表单中的数据绑定到pojo对象里面去,需要页面中input的name和controller的pojo形参中的属性名称一致,这样页面中数据将直接绑定到pojo对象上,不需要额外的注解。
    在这里插入图片描述
    Controller中POJO形参的定义:
    在这里插入图片描述
    包装pojo
    对于包装类型的pojo,在进行参数绑定时按照如下规范即可。
    代码1:商品的供应商类
    在这里插入图片描述
    代码2:商品的扩展类
    在这里插入图片描述
    代码3:处理请求的Controller方法
    在这里插入图片描述
    前台页面代码:OGNL(对象导航图语句)
    在这里插入图片描述
  • 5.9.6 自定义类型绑定
    对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。将请求日期字符串转换成日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。
    转换成java.util.Date类型。要转成此种类型,需要向处理器适配器中注入自定义的参数绑定组件。如下所示:
    在这里插入图片描述
    在SpringMVC的处理器适配器中指定conversion-service属性,conversionService是SpringMVC提供的接收自定义的类型转换的服务Bean。此Bean为FormattingConversionServiceFactoryBean类,配置该类时需要为该Bean的converters属性指定一个list集合,集合中存储的就是实现自定转换的服务Bean。如下所示:
    在这里插入图片描述
    在SpringMVC中一个自定义类型转换Bean需要实现Convert接口,如下所示:CustomDateConverter类实现自定义日期格式转换,代码如下:
    在这里插入图片描述
  • 5.9.7 数组、List、Map参数绑定
    数组绑定
    对于数组类型的参数绑定,只需要Controller处理方法中参数名与前台页面中的name属性保持一致即可,例如:批量删除
    在这里插入图片描述
    对于复选框,input标签的name属性值itemId,在Controller中的批量删除方法中所接受的形参列表中的参数名也必须同属性值保持一致。如下所示:
    在这里插入图片描述
    如上方法deleteItems所示:形参变量名为itemId与前台页面复选框中的name属性值保持一致。
    List参数绑定
    对于List集合的参数绑定,需要将List集合作为一个属性封装到一个包装类pojo中才可以。如下所示:
    例如:批量保存。假设需要对字典表中的数据进行更新,对于字典表来说就三、五个字段,完全可以放在一个页面中进行整条记录的维护,而且可以一次性维护多条记录,那么在调用Controller的方法时,传入的参数为List集合对象。
    Controller方法中的形参列表格式如下:
    在这里插入图片描述
    对于dictVo这个包装类,代码如下:
    在这里插入图片描述
    此类中包含的一个dictList集合属性,前台页面中table表格中每条记录对应数据表中一条记录,就三个字段,对应的每个文本框的name属性值为:dictList[${status.index}].dictName,dictList对应形参名,[]中括号对应的索引值,后面dictName集合中每个对象中的dictName属性。
    在这里插入图片描述
    Map集合参数绑定
    原理同List集合绑定一样,也需要一个包装类型的pojo对象,对于Controller方法如下:
    在这里插入图片描述
    包装pojo类代码如下:
    在这里插入图片描述
    前台页面代码如下:
    在这里插入图片描述
5.10 Spring中文乱码解决
配置一个Spring的Filter过滤器即可,如下所示:

在这里插入图片描述

6、SpringMVC高级应用

本节讲解SpringMVC框架的高级使用部分

6.1 SpringMVC的校验
B/S结构的系统对http请求的数据的校验多数在客户端进行,这也是出于简单以及用户体验上考虑,但是在一些安全性要求高的系统,服务端的校验也是不可缺少的。另外目前大部分系统除了客户端是浏览器之外,还有手机客户端、WebService接口调用等。
SpringMVC提供了一种Bean Validation的校验机制,采用了Hibernate Vaildator的校验,但是与Hibernate持久层框架没有任何关系。
  • 6.1.1 理解校验
    服务端校验一般分以下三种情况:
    控制层controller:校验页面请求的参数的合法性。在服务端控制层conroller进行校验,不区分客户端类型(浏览器、手机客户端、远程调用)
    业务层service(使用较多):主要校验关键业务参数,仅限于WebService接口中使用的参数。
    持久层dao:一般是不校验的。
    对于SpringMVC的校验来说,并不是要完成业务的逻辑校验,仅仅是校验参数的合法性,因此SpringMVC的校验是在controller这层完成的。
  • 6.1.2 配置环境
    Hibernate的Validator的校验框架,所需要的JAR包为,如下图所示:
    在这里插入图片描述
    版本号不要出现错误,不然容器出现异常信息。
  • 6.1.3 配置校验器
    Spring框架提供的Context包下,包含了一个LocalValidatorFactoryBean,本地校验器工厂bean,该类可以将已经实现javax.validation.spi.ValidationProvider接口的类当做校验器组件进行管理。使用属性providerClass进行接收,而hibernate-validator包下的org.hibernate.validator.HibernateValidator类已经实现该接口,所以可以将该类注入给providerClass属性:如下所示:
    在这里插入图片描述
    属性validationMessageSource属性用于接收错误消息资源,所以下面配置messageSource错误消息Bean
    在这里插入图片描述
    配置该Bean时需要为besenames属性指定一个数组类型,表示该Bean需要加载的属性文件的名称,例如classpath:errorMessage表示,加载该类加载路径下的errorMessage.properties属性文件。
    在这里插入图片描述
  • 6.1.4 将校验器注入到处理器适配器
    将配置好的校验器注入到处理器适配器的驱动Bean中,如下所示:
    在这里插入图片描述
  • 6.1.5 添加校验规则
    如果需要对用户的传入信息做校验,则需要在对应的pojo类的属性上进行校验,如下所示:
    在这里插入图片描述
    使用注解表示product类的属性p_desc属性不能为空,如果在参数绑定后,传入的product对象中该属性为null了,则校验不通过。
    当校验不通过时,校验器则会抛出错误信息,错误信息为errorMessage.properties属性文件中prod.desc.isNull属性所对应的value值。
  • 6.1.6 捕获校验错误信息
    如果想获取校验器抛出的错误信息,需要在Controller层的处理方法中加入如下注解:
    在这里插入图片描述
    注意:在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息@Validated和BindingResult bindingResult是配对出现,并且形参顺序是固定的(一前一后)。
  • 6.1.7 在页面中显示错误信息
    在这里插入图片描述
  • 6.1.8 SpringMVC的校验注解
    @Null 被注释的元素必须为 null
    @NotNull 被注释的元素必须不为 null
    @AssertTrue 被注释的元素必须为 true
    @AssertFalse 被注释的元素必须为 false
    @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @Size(max=, min=) 被注释的元素的大小必须在指定的范围内
    @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
    @Past 被注释的元素必须是一个过去的日期
    @Future 被注释的元素必须是一个将来的日期
    @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
    Hibernate Validator 附加的 constraint
    @NotBlank(message =) 验证字符串非null,且长度必须大于0
    @Email 被注释的元素必须是电子邮箱地址
    @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
    @NotEmpty 被注释的字符串的不能为非空
    @Range(min=,max=,message=) 被注释的元素必须在合适的范围内
6.2 异常处理器

springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个统一的异常处理逻辑。

  • 6.2.1 异常处理思路
    系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。
    仅管在项目开发完成后,需要进行大量的测试,但仍会存在一些不可预知的错误异常,即使这种错误异常非常少了,但仍不能保证异常一点也不存在,所以针对这种情况,我们就需要由一个统一异常处理机制,来针这种情况(突发异常)进行处理,这就是自定义异常处理机制存在意义。
    系统的dao、service、controller出现的异常都通过throws Exception这种方式向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
    在这里插入图片描述
  • 6.2.2 自定义异常类
    为了区别不同的异常,通常根据异常类型自定义一个统一的异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。
    在这里插入图片描述
  • 6.2.3 自定义异常处理器
    自定义异常类编写完成后,需要使用自定义异常处理器来处理系统异常,自定义异常处理器需要实现HandlerExceptionResolver接口。如下所示:
    在这里插入图片描述
  • 6.2.4 错误页面
    在jsp页面下创建error文件夹,在此文件夹下创建error.jsp文件
    在这里插入图片描述
  • 6.2.5 异常处理器配置
    只需要将异常处理器bean配置在SpringMVC的配置文件中即可,因为该Bean实现了HandlerExceptionResolver接口,SpringMVC框架能自动识别该Bean当成全局的异常处理器。配置如下:
    在这里插入图片描述
  • 6.2.6 异常测试
    修改商品信息,id输入错误提示商品信息不存在。调用service查询商品信息,如果商品信息为空则抛出异常,在service中抛出异常方法同上。
    在这里插入图片描述
6.3 文件上传
如果在开发时需要实现文件上传,则form表单的enctype属性需要指定为multipart/form-data类型,如果使用SpringMVC框架,那么就需要SpringMVC框架来实现对该种数据类型的解析。
  • 6.3.1 SpringMVC对多部件数据类型的解析
    配置SpringMVC框架对multipart属性类型的解析器。如下所示:
    在这里插入图片描述
    虽然该Bean的配置是提供给SpringMVC框架使用,但是与其他提供给框架使用的Bean不同的是,此Bean必须要指定id属性而且id属性值需要写为:multipartResolver,是因为SpringMVC框架需要根据此字符串值来查找该Bean。
    解析器配置完成后还需要添加相应的JAR包,因为该解析器再实现上传时会用到此JAR包的相关类,相关JAR包如下:
    1、 commons-io-2.2.jar
    2、 commons-fileupload-1.2.2.jar
  • 6.3.2 创建图片的虚拟目录
    在普通的web应用中,在项目下创建一个上传图片目录即可,但是如果是个大型的WEB电商平台,则需要
    为图片单独指定一个图片服务器,该服务器的配置可以通过修改Tomcat的配置文件来实现,如下所示:
    修改Tomcat的config目录下的server.xml文件:
    在这里插入图片描述
  • 6.3.3 上传页面代码
    在这里插入图片描述
    如果图片为空,则不显示图片,否则显示图片。
  • 6.3.4 Controller方法中添加MultipartFile类型参数
    在Controller方法中,需要定义MultipartFile类型参数用来接收上传的图片格式类型的数据,如下所示:
    在这里插入图片描述
    在这里插入图片描述
6.4 JSON数据交互

在目前B/S架构的WEB应用开发中,JSON格式的数据类型交互是一种比较常见的应用技术。这是因为JSON格式的数据在接口调用中,html页面中都比较常见。而且JSON格式比较简单,解析还比较方便,所以使用广泛。比如:webService接口、ajax传输json数据等。

  • 6.4.1 SpringMVC对JSON的支持
    在这里插入图片描述
    SpringMVC对JSON格式的数据的支持需要用到注解@RequestBody,此注解可以将json格式的字符串转换成相应的java对象,如果需要输出json格式的字符串需要用到注解@ResponseBody,此注解可以将Java对象转成json串输出。
    SpringMVC框架使用jackson的JAR包进行json转换(@RequestBody和@ResponseBody),如下所示:
    1、 jackson-core-asl-1.9.11.jar
    2、 jackson-mapper-asl-1.9.11.jar
    注意SpringMVC框架中上述两种JSON方式的使用比较:
    请求json、输出json,要求请求的是json串,所以在前端页面中需要将请求的内容转成json,不太方便。
    请求key/value、输出json。此方法比较常用。
  • 6.4.2 配置json转换器
    在注解处理器适配器中配置json转换器,如下所示:
    在这里插入图片描述
    如果使用注解的方式配置处理器映射器,处理器适配置,即:<mvc:annotation-driven />则可以不用定义上面的内容。
  • 6.4.3 请求JSON、输出JSON
    下面使用JQuery的ajax方法进行测试,之所以使用ajax方法进行测试,是因为返回的数据为json格式,是纯粹的数据,可以使用JS脚本进行处理,因此更容易来处理数据,所以在测试的JSP页面需要引入相应的jquery库文件,如下所示。
    在这里插入图片描述
    在该JSP页面中通过JQuery的ajax方法进行请求,请求格式更改为JSON格式,如下所示:
    在这里插入图片描述
    Controller层代码如下:
    在这里插入图片描述
  • 6.4.4 请求类型key/value,输出JSON(常用)
    JS脚本代码如下:
    在这里插入图片描述
    Controller层代码如下:
    在这里插入图片描述
6.5 RESTful支持

RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。
RESTful(即Representational State Transfer的缩写)其实是一个开发理念,是对http的很好的诠释。Representational State Transfer的含义就是“表现层的状态转化”。
使用RESTful这种架构理念就需要对http请求进行一系列的规范:
1、对url规范,写成RESTful的格式的url
非REST的url:http://…/queryitem.action?id=001&itemType=01
REST风格的url:http://…/queryitem/001/01
特点:url简洁,将参数通过url传到服务端
2、http的方法规范
不管是删除、添加、更新、使用url是一致的,如果进行删除,需要设置http的方法为delete,同理添加
后台controller方法:判断http方法,如果是delete执行删除,如果是post执行添加。
3、对http的contentType规范
请求时指定contentType,要json数据,设置成json格式的type。
6.5.1 REST的示例
1、controller层代码如下:
在这里插入图片描述
2、REST方式的前端控制器配置
在这里插入图片描述
3、静态资源的解析
当请求的地址是js或img下的资源时,全部映射到应用中的js或img下的所有资源。
在这里插入图片描述

6.6 SpringMVC拦截器

SpringMVC的拦截器类似于JSP/Servlet中的Filter过滤器,用于对处理器进行预处理和后处理。

  • 6.6.1 拦截器定义
    在SpringMVC中提供了一个HandlerInterceptor接口,实现了该接口的实现类即为SpringMVC的拦截器,如下所示:
    在这里插入图片描述
    在这里插入图片描述
  • 6.6.2 拦截器的配置
    SpringMVC拦截器的配置有两种方式:1、针对单个mapping映射的配置拦截 2、针对所有mapping映射的配置拦截。第一种方式是不推荐的方式,第二种方式推荐使用。
    1、针对单个mapping映射的拦截配置
    在这里插入图片描述
    在BeanNameUrlHandlerMapping中,对属性interceptors属性进行了设置注入,注入内容为Object[]数组,在数组中引用了两个拦截器bean:interceptor1和interceptor2,拦截器按照引用的顺序依次执行。需要注意的是对于拦截器中的preHandle方法,按引用顺序执行,而其他两个方法postHandle和afterCompletion则反向执行。

2、针对所有mapping映射的拦截配置(推荐)
在这里插入图片描述

  • 6.6.3 拦截器正常执行
    拦截器1与拦截器2同时放行,即preHandle方法return为true。测试如下:
    interceptor1——preHandle
    interceptor2 —— preHandle
    interceptor2——postHandle
    interceptor1——postHandle
    interceptor2——afterCompletion
    interceptor1——afterCompletion
    对于拦截器的preHandle方法按配置顺序正常执行,而postHandle、afterCompletion方法则逆向执行
  • 6.6.4 拦截器中断执行
    拦截器1阻止,拦截器2放行。测试如下:
    interceptor1——preHandle
    拦截器1的preHandle方法正常执行,其他两个方法都不执行,而且拦截器2的所有方法都不执行,并且Controller也没有被执行。
    拦截器1放行,拦截器2阻止。测试如下:
    interceptor1——preHandle
    interceptor2——preHandle
    interceptor1——afterCompletion
    拦截器1与拦截器2的preHandle方法正常执行,拦截器2的其他两个方法都不执行,拦截器1的postHandle方法没有调用,只执行了afterCompletion方法。
    总结:preHandle方法按拦截器的配置顺序调用
    postHandler方法按拦截器的配置顺序逆向调用
    afterCompletion方法按拦截器的配置顺序逆向调用
    postHandler方法在拦截器链内的所有拦截器返回为true才调用
    afterCompletion方法在拦截器的preHandle方法返回为true才调用
  • 6.6.5 拦截器应用
    使用拦截器完成一个登陆拦截操作,代码如下所示:
    在这里插入图片描述
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值