一、SpringMVC 概述
Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一
Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架
Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请 求的控制器,而无须实现任何接口。
支持 REST 风格的 URL 请求
采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性
SpringMVC和Spring的关系:
软件开发的三层架构: web层【表示层、表现层】---->Service层---->Dao[DataBase Access Object]---->数据库!
SpringMVC实际上是Spring的一个子模块,我们用SpringMVC来代替这个JavaWEB部分!
MVC:也是一种设计模式:M:Model【模型】-->V[View]--->C[Controller]!
Model用来封装数据的,View:用来显示数据 Controller:用于接收前端页面发送的请求,然后调用Service层处理,拿到处理结果,将该结果返回给前端页面!
SpringMVC:相当于MVC架构中的C以及V!
SpingMVC是基于SpingMVC4.x
二、SpringMVC之HelloWorld
1.加入JAR包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
–commons-logging-1.1.3.jar –spring-aop-4.0.0.RELEASE.jar –spring-beans-4.0.0.RELEASE.jar –spring-context-4.0.0.RELEASE.jar –spring-core-4.0.0.RELEASE.jar –spring-expression-4.0.0.RELEASE.jar –spring-web-4.0.0.RELEASE.jar –spring-webmvc-4.0.0.RELEASE.jar
2.配置前端控制器【DispatcherServlet】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- The front controller of this Spring Web application, responsible for handling all application requests --> <!--向服务器注册前端控制器! --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <!--DispatcherServlet指的是SpringMVC的前端控制器!,给服务器使用,创建servlet对象! --> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 初始化参数contextConfigLocation用于指定SpringMVC配置文件的路径以及名称 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 数字0或者大于0的数字表示的是:在服务器启动的时候创建Servlet对象,而不是第一次访问的时候创建 小于0的数字指的是:在第一次访问的时候创建Servlet对象. 在数字大于O的情况下,数字越小,优先级越高! --> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <!-- 用 servlet-mapping指定请求映射的路径--> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <!-- 用url-pattern指定拦截 的请求路径! --> <url-pattern>/</url-pattern> </servlet-mapping>
3.创建SpringMVC的配置文件并添加要扫描的包
注意:1)创建SpringMVC配置文件的名字要和上面在web.xml文件中指定的名字一致!
2)我们创建SpringMVC配置文件的时候使用的是Spring Bean Configuration File创建的,不是XML!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- 配置SpingMVC容器要扫描的包! -->
<context:component-scan base-package="com.neuedu.controller"></context:component-scan>
4.在springMVC扫描的包下创建控制器类[Controller/Handler],注意要加入@Controller注解
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 我们通过@RequestMapping做请求URL的映射! * @return */ @RequestMapping("/sayHello") public String sayHello(){ return "/WEB-INF/views/success.jsp"; }
注意:在类的方法上我们使用的是@RequestMapping,然后在括号里指定请求url的请求路径!
5.创建页面!
注意:1)当我们不用init-param指定springMVC配置文件的路径好位置的时候,SpringMVC默认会去 /WEB-INF/<servlet-name>-servlet.xml
2)配置视图解析器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!--InternalResourceViewResolvers 是视图解析器 ,它会将逻辑视图转换成实际的物理视图,做一个转发操作! 也就是说具体步骤:prefix + 方法的返回值 + suffix--> <!-- /WEB-INF/views/success.jsp --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean>
3)请求一个SpringMVC的流程!
三、使用 @RequestMapping 映射请求
Spring MVC 使用 @RequestMapping 注解为控制器指定可以处理哪些 URL 请求, 在控制器的类定义及方法定义处都可标注
@RequestMapping
– 类定义处:提供初步的请求映射信息。相对于 WEB 应用的根目录
– 方法处:提供进一步的细分映射信息。相对于类定义处的 URL。若 类定义处未标注 @RequestMapping,则方法 处标记的 URL 相对于 WEB 应用的根目录
DispatcherServlet 截获请求后,就通过控制器上@RequestMapping 提供的映射信息确定请求所对应的处理方法。
映射请求参数、请求方法或请求头
@RequestMapping 除了可以使用请求 URL 映射请求外,还可以使用请求方法、请求参数及请求头映射请求
@RequestMapping 的 value、method、params 及 heads 分别表示请求 URL、请求方法、请求参数及请求头的映射条件,他们之间是与的关系,联合使用多个条件可让请求映射 更加精确化。
params 和 headers支持简单的表达式:
– param1: 表示请求必须包含名为 param1 的请求参数
– !param1: 表示请求不能包含名为 param1 的请求参数
– param1 != value1: 表示请求包含名为 param1 的请求参数,但其值 不能为 value1
–{“param1=value1”, “param2”}: 请求必须包含名为 param1 和param2 的两个请求参数,且 param1 参数的值必须为 value1!
使用 @RequestMapping 映射请求
Ant 风格资源地址支持 3 种匹配符:
– :匹配文件名中的一个字符
– *:匹配文件名中的任意字符
– **:** 匹配多层路径
@RequestMapping 还支持 Ant 风格的 URL:
–/user/*/createUser: 匹配
/user/aaa/createUser、/user/bbb/createUser 等 URL
–/user/**/createUser: 匹配
/user/createUser、/user/aaa/bbb/createUser 等 URL
–/user/createUser: 匹配
/user/createUseraa、/user/createUserbb 等 URL
@PathVariable 映射 URL 绑定的占位符
带占位符的 URL 是 Spring3.0 新增的功能,该功能在 SpringMVC 向 REST 目标挺进发展过程中具有里程碑的 意义
通过 @PathVariable 可以将 URL 中占位符参数绑定到控 制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过
@PathVariable("xxx") 绑定到操作方法的入参中,需要注意的是:该注解的value属性值要与占位符保持一致。
四、REST( Representational State Transfer)
作用: (资源)表现层状态转化。是目前最流行的一种互联网软件架。 它结构清晰、符合标准、易于理解、扩展方便, 所以正得到越来越多网站的采用.
HTTP 协议里面,四个表示操作方式的动 词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获 取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
示例:
–/order/1 HTTP GET :得到 id = 1 的 order
–/order/1 HTTP DELETE:删除 id = 1的 order
–/order/1 HTTP PUT:更新id = 1的 order
–/order HTTP POST:新增 order
HiddenHttpMethodFilter:浏览器 form 表单只支持 GET 与 POST 请求,而DELETE、PUT 等 method 并不支 持,Spring3.0 添加了一个过滤器,可以将这些请求转换 为标准的 http 方法,使得支持 GET、POST、PUT 与 DELETE 请求。
POST请求转化为put请求和delele请求过程
1)在web.xml文件中配置:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- HiddenHttpMethodFilter过滤器可以将POST请求转化为put请求和delete请求! --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2)在表单域中需要携带一个name值为_method,value值为put或者delete的参数,如下所示:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<form action="${pageContext.request.contextPath }/order/1" method="post"> <input type="hidden" name="_method" value="put"/> <input type="submit" value="Submit"/> </form> <form action="${pageContext.request.contextPath }/order/1" method="post"> <input type="hidden" name="_method" value="delete"/> <input type="submit" value="Submit"/> </form>
五、请求处理方法签名
Spring MVC 通过分析处理方法的签名,将 HTTP 请求信 息绑定到处理方法的相应人参中。 Spring MVC 对控制器处理方法签名的限制是很宽松的, 几乎可以按喜欢的任何方式对方法进行签名。 必要时可以对方法及方法入参标注相应的注解(@PathVariable、@RequestParam、@RequestHeader 等)、SpringMVC 框架将 HTTP请求的信息绑定到相应的方法入参中,并根据方法的返回值类型做出相应的后续处理。
1、使用 @RequestParam 绑定请求参数值
在处理方法入参处使用 @RequestParam 可以把请求参 数传递给请求方法
– value:参数名
– required:是否必须。默认为 true, 表示请求参数中必须包含对应 的参数,若不存在,将抛出异常
2、@RequestParam可以接收请求的参数,相当于Servlet的getParameter()方法
注意:要把@RequestParam和@PathVariable区分开
三个默认属性:
value:这个字段要与请求参数的name属性值一致!
required:布尔值,默认是true,当指定为false的时候,说明这个参数不是必须的,可以不带!
defaultValue:在我们不传值的时候,默认使用defaultValue的值,传递参数的时候,使用我们传递的参数值!
3、@RequestHeader:获取请求头信息,默认属性:
value:这个字段要与请求参数的name属性值一致!
required:布尔值,默认是true,当指定为false的时候,说明这个参数不是必须的,可以不带!
defaultValue:在我们不传值的时候,默认使用defaultValue的值,传递参数的时候,使用我们传递的参数值!
4、使用 @CookieValue 绑定请求中的 Cookie 值
@CookieValue 可让处理方法入参绑定某个 Cookie 值
5、使用 POJO 对象绑定请求参数值
Spring MVC 会按请求参数名和 POJO 属性名进行自动匹 配,自动为该对象填充属性值。支持级联属性。 如:dept.deptId、dept.address.tel 等
6、.MVC 的 Handler 方法可以接受哪些 ServletAPI 类型的参数
HttpServletRequest
HttpServletResponse
HttpSession
六、处理模型数据
Spring MVC 提供了以下几种途径输出模型数据:
–ModelAndView: 处理方法返回值类型为 ModelAndView时, 方法体即可通过该对象添加模型数据
–Map 及 Model: 入参为 org.springframework.ui.Model、org.springframework.ui. ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
–@SessionAttributes: 将模型中的某个属性暂存到HttpSession 中,以便多个请求之间可以共享这个属性
– @ModelAttribute: 方法入参标注该注解后, 入参的对象 就会放到数据模型中.
1、ModelAndView
控制器处理方法的返回值如果为 ModelAndView, 则其既 包含视图信息,也包含模型数据信息。
添加模型数据:
–MoelAndView addObject(String attributeName, Object attributeValue)
–ModelAndView addAllObject(Map<String, > modelMap)
设置视图:
–void setView(View view)
–void setViewName(String viewName)
2、Model AND MAP
Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口存 储模型数据
具体步骤
– Spring MVC 在调用方法前会创建一个隐 含的模型对象作为模型数据的存储容器。
– 如果方法的入参为 Map 或 Model 类 型,Spring MVC 会将隐含模型的引用传 递给这些入参。在方法体内,开发者可以通过这个入参对象访问到模型中的所有数 据,也可以向模型中添加新的属性数据
3、多个请求之间共用某个模型属性数据
方法: 可以在控制器类上标注一 个 @SessionAttributes, SpringMVC将在模型中对应的属性暂存到 HttpSession 中。
@SessionAttributes 除了可以通过属性名指定需要放到会话中的属性外,还可以通过模型属性的对象类型指定哪些 模型属性需要放到会话中
–@SessionAttributes(types=User.class) 会将隐含模型中所有类型为 User.class 的属性添加到会话中。
–@SessionAttributes(value={“user1”, “user2”})
–@SessionAttributes(types={User.class, Dept.class})
–@SessionAttributes(value={“user1”, “user2”}, types={Dept.class})
@ModelAttribute[使用场景]
在方法定义上使用 @ModelAttribute 注解:Spring MVC在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute 的方法。
在方法的入参前使用 @ModelAttribute 注解:
– 可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数绑定到对象中,再传入入参
– 将方法入参对象添加到模型中
4、针对POST请求乱码的处理
在web.xml文件中加上CharacterEncodingFilter
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
七、转发、重定向
1、转发
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- 配置直接转发的页面 -->
<!-- 可以直接转发到响应的页面,而无需再经过Handler的方法了 -->
<mvc:view-controller path="/success" view-name="success"/>
<!-- 访问静态资源! -->
<mvc:default-servlet-handler/>
<!-- 将ConversionService再作为annotation-driven的一个属性存在! -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
2、重定向
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
如果返回的字符串中带 forward: 或 redirect: 前缀 时,SpringMVC 会对他们进行特殊处理:将 forward: 和 redirect: 当成指示符,其后的字符串作为 URL 来处理
–redirect:/success.jsp:会完成一个到 success.jsp 的重定向的操作
–forward:/success.jsp:会完成一个到 success.jsp 的转发操作
可以在spingmvc配置文件中配置 <mvc:view-controller path="/j1sp" view-name="success"/>标签,就可以让我们的请求不经过Controller,直接进入另一个目标页面!
<!-- 但是此时原来访问正常的@RequestMapping URL现在却不能正常访问了,如果想正常访问,需要加入<mvc:annotation-driven>该标签-->
<mvc:annotation-driven></mvc:annotation-driven>
八、SpringMVC确定目标方法POJO类型入参的过程:
1.确定一个key
1).若目标方法的POJO类型的参数木有使用@ModelAttribute作为修饰,则key为POJO类名第一个字母的小写。
2).若使用@ModelAttribute修饰,则key为@ModelAttribute注解的value属性值
2.在implicitModel中查找key对应的对象,若存在,则作为入参传入。
1).若在@ModelAttribute标记的方法中在Map保存过,且key和1确定的key一致,则会获取到!
3.implicitModel
在implicitModel中不存在key对应的对象,则检查当前的Handler是否使用@SessionAttribute注解修饰,若使用了该主机,且@SessionAttributes注解的value属性值中包含了 key,则会从HttpSession中来获取key所对应的value值,若存在则直接传入到目标方法的入参中,若不存在则将抛出异常。
4.若没有标识@SessionAttributes注解或者@SessionAttributes注解的value值中不包含key,则会通过反射来创建POJO类型的参数,传入为目标方法的参数。
5.SpringMVC会把key和POJO对象保存到implicitModel中,进而会保存到request域中!
注意:1)@ModelAttribute标记的方法,会在每个目标方法执行之前被SpringMVC调用!
2)@ModelAttribute注解可以来修饰目标方法POJO类型的入参,其value属性值有如下作用:
a.SpringMVC会使用value属性值在implicitModel中查找对应的对象,若存在则会直接传入到目标方法的入参中
b.SpringMVC会以value为key,POJO类型的对象为value,存入到request域中。
九、数据类型转换以及数据格式化标签
数据类型转换【了解】
1. 自定义类型转换器实现Converter<S,T>接口并加入到SpringMVC的IOC容器中,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Component public class EmployeeConverter implements Converter<String, Employee>{ @Override public Employee convert(String source) { System.out.println(source); if(source != null){ String[] vals = source.split("-"); if(vals != null && vals.length ==5){ String name = vals[0]; String email = vals[1]; Integer gender = Integer.parseInt(vals[2]); Department department = new Department(); department.setId(Integer.parseInt(vals[3])); Employee employee = new Employee(null, name, email, gender, department); return employee; } } return null; } }
2.配置自定义转换器到FormattingConversionServiceFactoryBean工厂中!、
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- 将ConversionService再作为annotation-driven的一个属性存在! -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 配置ConversionService,id必须为conversionService -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="employeeConverter"/>
</set>
</property>
</bean>
十、SpringMVC处理JSON数据
1.加入json的3个jar包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
jackson-annotations-2.1.5.jar jackson-core-2.1.5.jar jackson-databind-2.1.5.jar
2. 编写目标方法,使其返回 JSON 对应的对象或集合
1)controller
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//获取并返回Json数据 @ResponseBody @RequestMapping("/getRequestJson") public List<String> getRequestJson(@RequestBody String body){ List<String> list=new ArrayList<String>(); list.add("张三"); list.add("李四"); list.add("王五"); System.out.println(body); return list; }
2)页面
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script type="text/javascript"> $(function(){ //获取并返回Json数据 $("#btn01").click(function(){ $.ajax({ type: "POST", url: "${pageContext.request.contextPath}/getRequestJson", // data: JSON.stringify({"name":"手机 ","age":13}), data: "'name':'手机 ','age':13", contentType:'application/json;charset=utf-8', //解决乱码问题 success: function(msg){ alert( "Data Saved: " + msg ); } }); }); }); </script>
3. 在方法上添加 @ResponseBody 注解
@responseBody注解的使用
作用1:
@responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者 是XML 数据,需要注意的呢,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
作用2
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@RequestMapping("/login") @ResponseBody public User login(User user){ return user; }
User字段:userName pwd
那么在前台接收到的数据为:'{"userName":"xxx","pwd":"xxx"}'
效果等同于如下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@RequestMapping("/login") public void login(User user, HttpServletResponse response){ response.getWriter.write(JSONObject.fromObject(user).toString()); }
十一、文件上传、下载
Spring MVC 上下文中默认没有为文件上传提供了直接的支持,因 此默认情况下不能处理文件的上传工作,如果想使用 Spring 的文件上传功能,需现在上下文中配置 CommonsMultipartResovler:
1、上传
1)加入jar包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
commons-fileupload-1.3.1.jar
commons-io-2.4.jar
2)在SpringMVC配置文件中配置CommonsMultipartResovler
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- 配置CommonsMultipartResolver,id必须为multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<!-- 以字节为单位 -->
<property name="maxUploadSize" value="1024000"></property>
</bean>
3)表单:POST请求,file类型,enctype="multipart/form-data"
文件上传
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@RequestMapping(value="testUpload",method=RequestMethod.POST) public String testUpload(HttpServletRequest request,@RequestParam(value="desc",required=false) String desc,@RequestParam("photo") CommonsMultipartFile file) throws Exception{ ServletContext servletContext = request.getServletContext(); String realPath = servletContext.getRealPath("/upload"); File file1 = new File(realPath); if(!file1.exists()){ file1.mkdir(); } OutputStream out; InputStream in; //uuid_name.jpg String prefix = UUID.randomUUID().toString(); prefix = prefix.replace("-",""); String fileName = prefix+"_"+file.getOriginalFilename(); System.out.println(fileName); out = new FileOutputStream(new File(realPath+"\\"+fileName)); in = file.getInputStream(); IOUtils.copy(in, out); out.close(); in.close(); return "success"; }
2、用ResponseEntity<byte[]> 返回值完成文件下载
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@RequestMapping(value="testResponseEntity") public ResponseEntity<byte[]> testResponseEntity(HttpServletRequest request) throws Exception{ byte[] body = null; ServletContext servletContext = request.getServletContext(); String fileName = "风吹麦浪.mp3"; String path = servletContext.getRealPath("/WEB-INF/"+fileName); File file = new File(path); InputStream in = new FileInputStream(file); body = new byte[in.available()]; in.read(body); HttpHeaders headers = new HttpHeaders(); fileName = new String(fileName.getBytes("gbk"),"iso8859-1"); headers.add("Content-Disposition", "attachment;filename="+fileName); HttpStatus statusCode=HttpStatus.OK; ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body, headers, statusCode); return response; }
十二、自定义拦截器
Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必 须实现HandlerInterceptor接口
1.自定义实现类实现 HandlerInterceptor接口
– preHandle():该方法在目标方法之前被调用,
若返回值为true,则继续调用后续的拦截器和目标方法
若返回值为false,则不会再调用后续的拦截器和目标方法
可以考虑做权限,日志或者事务等!
– postHandle():调用目标方法之后,但渲染视图之前被调用
可以对请求域中的属性或者视图做出修改!
– afterCompletion():渲染视图之后被调用,
可以在该方法中进行一些资源清理的操作。
2.在springmvc配置文件中配置相对应的拦截器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<mvc:interceptors>
<!--配置自定义拦截器 ,所有的路径都拦截 -->
<bean class="com.neuedu.springmvc.filter.MyFilter"></bean>
</mvc:interceptors>
关于拦截器的配置:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<mvc:interceptors> <!--配置自定义拦截器 ,所有的路径都拦截 --> <bean class="com.neuedu.springmvc.filter.MyFilter"></bean> <!-- 关于拦截器的配置问题 ,可以通过<mvc:interceptor>来配置使用哪个拦截器来【不】拦截的路径--> <mvc:interceptor> <!-- 用<mvc:mapping>标签指定要拦截的路径 --> <mvc:mapping path="/employ"/> <!-- 指定使用哪个拦截器进行拦截 --> <bean class="com.neuedu.springmvc.filter.SecondFilter"></bean> </mvc:interceptor> </mvc:interceptors>
十三、异常处理
1、SpringMVC基于注解的异常处理
1)加上<mvc:annotation-driven>标签
2)在当前Handler中定义由@ExceptionHandler注解修饰的方法,用于处理异常信息!
注意:
a)@ExceptionHandler方法修饰的入参中可以加入Exception类型的参数,该参数即对应发生的异常信息
b)@ExceptionHandler方法的入参中不能传入Map.若希望把异常信息传到页面上,需要使用ModelAndView作为方法的返回值。
3)@ExceptionHandler 注解定义的方法优先级问题:
例如:发 生的是NullPointerException,但是声明的异常有 RuntimeException 和 Exception,此候会根据异常的最近 继承关系找到继承深度最浅的那个 @ExceptionHandler 注解方法,即标记了 RuntimeException 的方法
4)ExceptionHandlerMethodResolver 内部若找不 到@ExceptionHandler 注解的话,会找@ControllerAdvice 中的@ExceptionHandler 注解方法
2、基于xml配置的异常处理
如果希望对所有异常进行统一处理,可以使用 SimpleMappingExceptionResolver,它将异常类名映射为 视图名,即发生异常时使用对应的视图报告异常
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 指定在在request域中获取异常信息所需要的key:即ex -->
<property name="exceptionAttribute" value="ex"></property>
<!-- 指定异常映射 -->
<property name="exceptionMappings">
<props>
<!-- 由prop标签的key属性指定发生异常的全类名,由值指定出现异常去哪个页面! -->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
</bean>
十四、spring和springmvc的整合
实际上SpringMVC就运行在Spring环境之下,还有必要整合么?
SpringMVC和Spring都有IOC容器,是不是都需要保留呢?
答案是:通常情况下,类似于数据源,事务,整合其他框架都是放在spring的配置
文件中(而不是放在SpringMVC的配置文件中),实际上放入Spring配置文件对
应的IOC容器中的还有Service和Dao.而SpringMVC也搞自己的一个IOC容器,在
SpringMVC的容器中只配置自己的Handler信息。
1.导入Spring和SpringMVC的所有jar包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2.在web.xml文件中分别配置SpringMVC和Spring的配置信息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
3.配置spring的配置文件和springmvc的配置文件
spring的配置文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
springmvc的配置文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
加入jdbc.properties文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
4.创建Controller类与Service类
并创建这两个类的无参构造器,分别输出一句话!
5.启动项目
发现controller构造器和service构造器都执行了两次!
问题:若Spring的IOC容器和SpringMVC的IOC容器扫描的包有重合的部分,就会导致有的bean会被创建2次!
解决:
1.使Spring的IOC容器扫描的包和SpringMVC的IOC容器扫描的包没有重合的部分!
controller层都在controller包,service层都在service包
2.但是有的时候开发的时候是分模块开发的,这样不太容易做到,所以:可以在component-scan标签下面中使用如下子标签来规定只能扫描的注解:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
所以在springMVC的配置文件中我们可以按着如下配置,只扫描controller及ControllerAdvice注解:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
而在spring的配置文件中:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
此时再重新启动项目就会发现spring和springmvc的对象都创建了一份!
6.Spring的IOC容器和SpringMVC的IOC容器的关系
注意:
1)SpringMVC容器中的bean可以引用Spring容器中的bean,也就是在Controller中我们可以注入service层对象
2)反之则不行,就是说:在spring扫描的service层不能引用springmvc的handler
3)实际上Spring的容器和Spring容器有父子间关系,就想儿子可以继承父亲的基因一样,父亲没法继承儿子的基因!
而且从另一个角度也说明了Handler是可以依赖Service层的,但是Service层却不可以依赖Handler层!
十五、视图和视图解析器
请求处理方法执行完成后,最终返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,SpringMVC 也会在内部将它们装配成一ModelAndView 对象,它包含了逻辑名和模型对象的视图
Spring MVC 借助视图解析器(ViewResolver)得到最终 的视图对象(View),最终的视图可以是 JSP ,也可能是 Excel、JFreeChart等各种表现形式的视图
视图
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。
为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View
视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题。
视图解析器:
图解析器的作用比较单一:将逻辑视图解析为一个具体 的视图对象。
所有的视图解析器都必须实现 ViewResolver 接口
自定义视图:
1.自定义视图,实现view接口或者继承AbstractView抽象类,并加入到IOC容器中。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Component public class AView extends AbstractView{ @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // TODO Auto-generated method stub } }
2.在springmvc配置文件中配置BeanNameViewResolver视图解析器。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!-- 通过BeanNameViewResolver视图解析器:使用视图的名字来解析视图 -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
3.注意:每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可 以通过 order 属性指定解析器的优
先顺序,order越小优先级越高。SpringMVC 会按视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则将抛出 ServletException 异
十三、用 Spring 的表单标签
通过 SpringMVC 的表单标签可以实现将模型数据 中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显。
一般情况下,通过 GET 请求获取表单页面,而通过 POST 请求提交表单页面,因此获取表单页面和提交表单 页面的 URL 是相同的。只要满足该最佳条件的契 约,<form:form> 标签就无需通过 action 属性指定表单 提交的 URL
可以通过 modelAttribute 属性指定绑定的模型属性,若 没有指定该属性,则默认从 request 域对象中读取 command 的表单 bean,如果该属性值也不存在,则会 发生错误
SpringMVC 提供了多个表单组件标签,如<form:input/>、<form:select/> 等,用以绑定表单字段的属性值,它们的共有属性如下:
– path:表单字段,对应 html 元素的 name 属性,支持级联属性
form:input、form:password、form:hidden、form:textarea:对应 HTML 表单的 text、password、hidden、textarea标签
form:radiobutton:单选框组件标签,当表单 bean 对应的 属性值和 value 值相等时,单选框被选中
form:radiobuttons:单选框组标签,用于构造多个单选框
–items:可以是一个 List、String[] 或 Map
–itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个 属性值
–itemLabel:指定 radio 的 label 值
–delimiter:多个单选框可以通过 delimiter 指定分隔符
表单标签
form:checkbox:复选框组件。用于构造单个复选框
form:checkboxs:用于构造多个复选框。使用方式同 form:radiobuttons 标签
form:select:用于构造下拉框组件。使用方式同 form:radiobuttons 标签
form:option:下拉框选项组件标签。使用方式同 form:radiobuttons 标签
form:errors:显示表单组件或数据校验所对应的错误
– <form:errors path= “ *” /> :显示表单所有的错误
–<form:errors path= “ user*” /> :显示所有以 user 为前缀的属性对应的错误
–<form:errors path= “ username” /> :显示特定表单对象属性的错误
当需要表单回显或者使用下拉列表的时候,就使用form表单标签,而如果使用遍历的标签就使用JSTL标签【导包】!