什么是SpringMVC?
一、什么是SpringMVC?
1.SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于SpringFrameWork的后续产品,已经融合在 Spring Web Flow 中。
2.SpringMVC = Spring +MVC
- spring mvc类似于struts的一个MVC开框架,其实都是属于spring,spring mvc需要有spring的架包作为支撑才能跑起来.
spring是一个一站式的框架,提供了表现层(springmvc)到业务层(spring)再到数据层(springdata)的全套解决方案;spring的两大核心IOC(控制反转)和AOP(面向切面编程)更是给我们的程序解耦和代码的简介提供了支持。
Spring框架图:
从Spring的结构图可以看出,springMVC位于spring web端的一个框架,是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦。附:基于请求驱动指的就是使用请求-响应模型。
从名字上就可以窥探出,Spring>SpringMVC,那么事实上,spring和SpringMVC是一种父子关系。SpringMVC是spring扩展出的一个应用于web端的框架。在这里需要注意的一点,就是到底什么是父子容器关系:
spring主要的作用是黏合其他模块组件,进行统一管理,springmvc则主要是负责web端。那么,我们都知道,我们在应用spring的时候,可以使用注入。这个时候,如果我们的web端是用的SpringMVC,这个时候,controller理论上是通过SpringMVC去注入,但是,使用spring注入,同样是可行的。同理,service等层,使用SpringMVC配置的统一扫描装配也是可以的。所以,如果说只是为了使用spring的依赖注入,是大可不必将springMVC和spring同时使用的。他们完全可以分开!
但是,尽管SpringMVC和spring都可以进行自动装配扫描,值得注意的是:spring(父容器)并不能直接访问SpringMVC(子容器)所注入的对象,但是SpringMVC却可以访问到spring装载的对象。所以,在配置自动装配的时候,应该注意到这一点。
- MVC
概念:
M:Model,模型。JavaBean
* 完成具体的业务操作,如:查询数据库,封装对象
V:View,视图。JSP
* 展示数据
C:Controller,控制器。Servlet
* 获取用户的输入
* 调用模型
* 将数据交给视图进行展示
二、SpringMVC的组件解析、执行流程
1.组件解析
2.springmvc的流程:
1、 用户发送请求至前端控制器DispatcherServlet;
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器;
3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器,执行处理器(Controller,也叫后端控制器);
5、Controller执行完成返回ModelAndView,并返回给HandlerAdapter,HandlerAdapter将结果返回给DispatcherServlet;
6、DispatcherServlet将ModelAndView传给ViewReslover视图解析器,ViewReslover解析后返回具体View给DispatcherServlet;
7、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)后返回给给客户
3.组件
1、前端控制器DispatcherServlet(不需要攻城狮开发),由框架提供
作用:接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之间的耦合度。
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2、处理器映射器HandlerMapping(不需要攻城狮开发),由框架提供
作用:根据请求的url查找Handler
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
4、处理器Handler(需要攻城狮开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要攻城狮根据业务需求开发Handler。
5、视图解析器View resolver(不需要攻城狮开发),由框架提供
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由攻城狮根据业务需求开发具体的页面。
6、视图View(需要攻城狮开发jsp...)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)
2.文件配置
web.xml:
<!--mvc核心控制器--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
springmvc.xml:
<beans> <!-- 配置映射处理器:根据bean(自定义Controller)的name属性的url去寻找handler;springmvc默认的映射处理器是BeanNameUrlHandlerMapping--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <!-- 配置处理器适配器来执行Controller ,springmvc默认的是SimpleControllerHandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 配置自定义Controller --> <bean id="myController" name="/hello.do" class="org.controller.MyController"></bean> <!-- 配置sprigmvc视图解析器:解析逻辑视图; 后台返回逻辑视图:index 视图解析器解析出真正物理视图:前缀+逻辑视图+后缀====/WEB-INF/jsps/index.jsp --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsps/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
详图:
三、SpringMVC常用注解
1.@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
RequestMapping注解有六个属性,下面我们把她分成三类进行说明(下面有相应示例)。
1、 value, method;
value: 指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
method: 指定请求的method类型, GET、POST、PUT、DELETE等;
2、consumes,produces
consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
3、params,headers
params: 指定request中必须包含某些参数值是,才让该方法处理。
headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求。
2.@Resource和@Autowired
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
1、共同点
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。
2、不同点
(1)@Autowired
@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。
public class TestServiceImpl {
// 下面两种@Autowired只要使用一种即可
@Autowired
private UserDao userDao; // 用于字段上
@Autowired
public void setUserDao(UserDao userDao) { // 用于属性的方法上
this.userDao = userDao;
}
}
@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。如下:
public class TestServiceImpl {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
}
(2)@Resource
@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
public class TestServiceImpl {
// 下面两种@Resource只要使用一种即可
@Resource(name="userDao")
private UserDao userDao; // 用于字段上
@Resource(name="userDao")
public void setUserDao(UserDao userDao) { // 用于属性的setter方法上
this.userDao = userDao;
}
}
注:最好是将@Resource放在setter方法上,因为这样更符合面向对象的思想,通过set、get去操作属性,而不是直接去操作属性。
@Resource装配顺序:
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。
3.@ModelAttribute和 @SessionAttributes
代表的是:该Controller的所有方法在调用前,先执行此@ModelAttribute方法,可用于注解和方法参数中,可以把这个@ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行@ModelAttribute方法。
@SessionAttributes即将值放到session作用域中,写在class上面。
具体示例参见下面:使用 @ModelAttribute 和 @SessionAttributes 传递和保存数据
4.@PathVariable
用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。如:
@Controller
public class TestController {
@RequestMapping(value="/user/{userId}/roles/{roleId}",method = RequestMethod.GET)
public String getLogin(@PathVariable("userId") String userId,
@PathVariable("roleId") String roleId){
System.out.println("User Id : " + userId);
System.out.println("Role Id : " + roleId);
return "hello";
}
@RequestMapping(value="/product/{productId}",method = RequestMethod.GET)
public String getProduct(@PathVariable("productId") String productId){
System.out.println("Product Id : " + productId);
return "hello";
}
@RequestMapping(value="/javabeat/{regexp1:[a-z-]+}",
method = RequestMethod.GET)
public String getRegExp(@PathVariable("regexp1") String regexp1){
System.out.println("URI Part 1 : " + regexp1);
return "hello";
}
}
5.@requestParam
@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),它有三个常用参数:defaultValue = "0", required = false, value = "isApp";defaultValue 表示设置默认值,required 铜过boolean设置是否是必须要传入的参数,value 值表示接受的传入的参数类型。
6.@ResponseBody
作用: 该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
使用时机:返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用;
四、SpringMVC的文件上传
1.文件上传的原理
2.单文件上传
3.多文件上传
五、SpringMVC的拦截器
1 <!--配置权限拦截器--> 2 <mvc:interceptors> 3 <mvc:interceptor> 4 <!--配置对哪些资源执行拦截操作--> 5 <mvc:mapping path="/**"/> 6 <!--配置哪些资源排除拦截操作--> 7 <mvc:exclude-mapping path="/user/login"/> 8 <bean class="com.itheima.interceptor.PrivilegeInterceptor"/> 9 </mvc:interceptor> 10 </mvc:interceptors>
六、SpringMVC异常处理机制
1.异常处理的思路
2 异常处理两种方式
① 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
② 实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器 。
1.简单异常处理器SimpleMappingExceptionResolver
SpringMVC已经定义好了该类型转换器,在使用时可以根据项目情况进行相应异常与视图的映射配置
1 <!--配置简单映射异常处理器--> 2 <bean class=“org.springframework.web.servlet.handler.SimpleMappingExceptionResolver”> 3 <property name=“defaultErrorView” value=“error”/> 默认错误视图 4 <property name=“exceptionMappings”> 5 <map> 异常类型 错误视图 6 <entry key="com.itheima.exception.MyException" value="error"/> 7 <entry key="java.lang.ClassCastException" value="error"/> 8 </map> 9 </property> 10 </bean>
2.自定义异常处理步骤
①创建异常处理器类实现HandlerExceptionResolver
1 public class MyExceptionResolver implements HandlerExceptionResolver { 2 @Override 3 public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex) { 4 //处理异常的代码实现 5 //创建ModelAndView对象 6 ModelAndView modelAndView = new ModelAndView(); 7 modelAndView.setViewName("exceptionPage"); 8 return modelAndView; 9 } 10 }
②配置异常处理器
1 <bean id="exceptionResolver" 2 class="com.itheima.exception.MyExceptionResolver"/>