springMVC就是类似于Struts2的mvc框架,提供web层解决方案,属于SpringFrameWork的后续产品。
三层架构
dao:持久层
用来与数据库进行交互
jdbc.jdbc Template dbutils mybatis
service:业务层
处理开发业务逻辑
spring:ioc/aop
web:表现层
servlet:用来处理用户请求和响应页面的数据
表现层框架: struts1,struts2,springMVC
MVC设计模式
–> 一种满足mvc模式的框架
M:model 业务模型
狭义:封装数据.
广义:dao + service + model=模型层
V:view 视图
展示数据,jsp/html
广义: 只要能显示数据,就是视图层
C:controller 控制层
核心.用来处理用户的请求,业务处理
servlet / SpringMVC
SpringMVC
–> 满足MVC设计模式的轻量级框架,属于springFrameWork的后续产品
–> 基于servlet开发:效率高,安全
–> 通过一套注解,让java类成为处理请求的控制器,无须实现任何接口
注意:
web-inf:路径下的页面,必须通过转发才可以访问
重定向:改变路径,清除请求数据
转发:不改变路径,不清楚请求数据
第一步:用户发起request请求,请求至DispatcherServlet前端控制器
第二步:DispatcherServlet前端控制器请求HandlerMapping处理器映射器查找Handler
DispatcherServlet:前端控制器,相当于中央调度器,各各组件都和前端控制器进行交互,降低了各各组件之间耦合度。
第三步:HandlerMapping处理器映射器,根据url及一些配置规则(xml配置、注解配置)查找Handler,将Handler返回给DispatcherServlet前端控制器
第四步:DispatcherServlet前端控制器调用适配器执行Handler,有了适配器通过适配器去扩展对不同Handler执行方式(比如:原始servlet开发,注解开发)
第五步:适配器执行Handler
Handler是后端控制器,当成模型。
第六步:Handler执行完成返回ModelAndView
ModelAndView:springmvc的一个对象,对Model和view进行封装。
第七步:适配器将ModelAndView返回给DispatcherServlet
第八步:DispatcherServlet调用视图解析器进行视图解析,解析后生成view
视图解析器根据逻辑视图名解析出真正的视图。
View:springmvc视图封装对象,提供了很多view,jsp、freemarker、pdf、excel。。。
第九步:ViewResolver视图解析器给前端控制器返回view
第十步:DispatcherServlet调用view的渲染视图的方法,将模型数据填充到request域 。
第十一步:DispatcherServlet向用户响应结果(jsp页面、json数据。。。。)
DispatcherServlet:前端控制器,由springmvc提供
–> 前端控制器就是springMVC中的唯一的servlet
–> 流程控制中心,调用其他组件处理请求,降低耦合性
HandlerMappting:处理器映射器,由springmvc提供
–> 用户请求经由控制器到达处理器映射器,找到对应的方法,
HandlerAdapter:处理器适配器,由springmvc提供
–> 执行处理器,通过扩展适配器可以对更多的处理器进行执行
Handler:处理器,需要程序员开发
–> 开发中需要编写的具体业务控制器, 根据不同的业务需求,开发具体的方法/类…
ViewResolver:视图解析器,由springmvc提供
–> 根据视图映射具体的网址,展示给用户观看
View:真正视图页面需要由程序编写
–> 多数使用jsp/html等前端技术
需要的jar包
使用spring3.2.0(带springwebmvc模块)
前端控制器
在web.xml中配置:
springmvc.xml
在springmvc.xml中配置springmvc架构三大组件(处理器映射器、适配器、视图解析器)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
例:
<!--扫描包-->
<context:component-scan base-package="com.itheima"></context:component-scan>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/"></property>
<!--后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
工程结构
处理器映射器
在springmvc.xml中配置:
BeanNameUrlHandlerMapping: 根据请求url(XXXX.action)匹配spring容器bean的 name找到对应的bean(程序编写的Handler)
BeanNameUrlHandlerMapping:表示将定义的Bean名字作为请求的url,需要将编写的controller在spring容器中进行配置,且指定bean的name为请求的url,且必须以.action结尾。
所有处理器映射器都实现HandlerMapping接口。
处理器适配器
在springmvc.xml配置:
所有的适配器都是实现了HandlerAdapter接口。程序编写Handler根据适配器的要求编写。
SimpleControllerHandlerAdapter适配器要求:
通过supports方法知道Handler必须要实现哪个接口:
Handler编写
需要实现Controller接口:
配置Handler
在springmvc.xml配置Handler由spring管理Handler。
配置视图解析器
配置视图解析,能够解析jsp视图:
编写TestController类
@Controller
public class HelloController {
@RequestMapping("hello")
public ModelAndView hello(){
System.out.println("hello springmvc....");
//创建ModelAndView对象
ModelAndView mav = new ModelAndView();
//设置模型数据
mav.addObject("msg", "hello springmvc...");
//设置视图名字
mav.setViewName("/WEB-INF/jsp/hello.jsp");
return mav;
}
}
工程部署
访问:http://localhost:8080/springfrist1110/itemList.action
异常
HandlerMapping没有找到Handler
HandlerMapping没有找到Handler,404后边不显示jsp路径
jsp页面地址错误
HandlerMapping处理器映射器
HandlerMapping 负责根据request请求找到对应的Handler处理器及Interceptor拦截器,将它们封装在HandlerExecutionChain 对象中给前端控制器返回。
其它非注解处理器映射器和适配器
BeanNameUrlHandlerMapping
BeanNameUrl处理器映射器,根据请求的url与spring容器中定义的bean的name进行匹配,从而从spring容器中找到bean实例。
<!—beanName Url映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
SimpleUrlHandlerMapping
simpleUrlHandlerMapping是BeanNameUrlHandlerMapping的增强版本,它可以将url和处理器bean的id进行统一映射配置。
-----> 多个映射处理器可以同时存在
-----> 要求程序员实现Controller接口
<!—简单url映射 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/items1.action">controller的bean id</prop>
<prop key="/items2.action">controller的bean id</prop>
</props>
</property>
</bean>
HandlerAdapter处理器适配器
HandlerAdapter会根据适配器接口对后端控制器进行包装(适配),包装后即可对处理器进行执行,通过扩展处理器适配器可以执行多种类型的处理器,这里使用了适配器设计模式。
SimpleControllerHandlerAdapter
SimpleControllerHandlerAdapter简单控制器处理器适配器,所有实现了org.springframework.web.servlet.mvc.Controller 接口的Bean通过此适配器进行适配、执行。
适配器配置如下:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
HttpRequestHandlerAdapter
HttpRequestHandlerAdapter,http请求处理器适配器,所有实现了org.springframework.web.HttpRequestHandler 接口的Bean通过此适配器进行适配、执行。
适配器配置如下:
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
Controller实现如下:
public class ItemList2 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 商品列表
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone5 苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
// 填充数据
request.setAttribute("itemsList", itemsList);
// 视图
request.getRequestDispatcher("/WEB-INF/jsp/order/itemsList.jsp").forward(request, response);
}
}
从上边可以看出此适配器器的handleRequest方法没有返回ModelAndView,可通过response修改定义响应内容,比如返回json数据:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
配置Handler
使用简单url映射器:
DispatcherServlet前端控制器加载 DispatcherServlet.properoties 配置文件,从而默认加载各各组件,如果在springmvc.xml中配置了处理器映射器和适配器,以sprintmvc.xml中配置的为准
注解映射器和适配器
Controller的代码
@Controller
public class ItemList3 {
@RequestMapping("/queryItem.action")
public ModelAndView queryItem() {
// 商品列表
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
// 创建modelAndView准备填充数据、设置视图
ModelAndView modelAndView = new ModelAndView();
// 填充数据
modelAndView.addObject("itemsList", itemsList);
// 视图
modelAndView.setViewName("order/itemsList");
return modelAndView;
}
}
组件扫描器
使用组件扫描器省去在spring容器配置每个controller类的繁琐。使用<context:component-scan自动扫描标记@controller的控制器类,配置如下:
<context:component-scan base-package=“cn.itcast.springmvc.controller.first”/>
RequestMappingHandlerMapping
注解式处理器映射器,对类中标记@ResquestMapping的方法进行映射,根据ResquestMapping定义的url匹配ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器,HandlerMethod对象中封装url对应的方法Method。
从spring3.1版本开始,废除了DefaultAnnotationHandlerMapping的使用,推荐使用RequestMappingHandlerMapping完成注解式处理器映射。
不要求实现任何接口,需要和RequestMappingHandlerMapping注解映射器配对使用,主要解析Handler方法中的形参
配置如下:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
注解描述:
@controller表示此类是一个控制器
@RequestMapping:定义请求url到处理器功能方法的映射
@Target({ElementType.METHOD},{ElementType.TYPE})
--> 说明该注解可以放在类和方法中
@RequestMapping("/.....",method=......GET)
--> 可在该处设置接受请求的类型
params属性详解
/**
* params={"name","money>100"}---请求中必须符合参数条件
* params={"!name"}--请求中不能包含name
* @return
*/
@RequestMapping(value="/saveUser",params={"name","money>100"})
public String saveUser(){
System.out.println("保存用户");
return "show";
}
@RequestParam(“name”, required = false default-value = “rose”):当属性名,与表单中的name属性不一致时,可使用此方法作为映射
required = false : 是否是必要属性 true:必要,false非必要
default-value = “rose” : 设置默认值,若参数未提供,则使用默认值(分页时使用此参数)
前端参数提交的方式
前端(简单pojo对象)
<form action="${pageContext.request.contextPath}/user/save" method="post">
姓名<input type="text" name="username">
年龄<input type="text" name="age">
<input type="submit" value="提交">
--若pojo中包含pojo,则<input type="text" name="(pojo包含的pojo属性).属性">--
--若pojo中包含list集合,则
集合中的第一个元素<input type="text" name="list[0]">
集合中的第二个元素<input type="text" name="list[1]">--
(将集合当成普通属性,根据索引对应)
--若pojo中包含pojo的list集合,则
集合中的第一个pojo对象,第一个元素<input type="text" name="list[0].username">
集合中的第一个pojo对象,第二个元素<input type="text" name="list[0].age">
集合中的第二个pojo对象,第一个元素<input type="text" name="list[1].username">
集合中的第二个pojo对象,第二个元素<input type="text" name="list[1].age">--
(将集合中的每个list中的pojo属性单独对应)
--若pojo中包含map集合,则
(输入格式 one = 'role角色' two = 'role角色' )
map集合中的,第一个元素(其中一个属性)<input type="text" name="map[''one].username">
map集合中的,第二个元素(其中一个属性)<input type="text" name="map['two'].username">
--
</form>
后端
/**
* 读取前端数据封装到pojo对象中,后台数据可直接获取
* @param user
* @return
*/
@RequestMapping(value = "/save", method = RequestMethod.POST)
public String save(User user){
System.out.println(user.getUsername());
System.out.println(user.getAge());
return "show";
}
RequestMappingHandlerAdapter
注解式处理器适配器,对标记@ResquestMapping的方法进行适配。
从spring3.1版本开始,废除了AnnotationMethodHandlerAdapter的使用,推荐使用RequestMappingHandlerAdapter完成注解式处理器适配。
配置如下:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
mvc:annotation-driven
springmvc使用mvc:annotation-driven自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter,可用在springmvc.xml配置文件中使用mvc:annotation-driven替代注解处理器和适配器的配置。
springmvc处理流程源码分析
1. 用户发送请求到DispatherServlet前端控制器
2. DispatherServlet调用HandlerMapping(处理器映射器)根据url查找Handler
3. DispatherServlet调用HandlerAdapter(处理器适配器)对HandlerMapping找到Handler进行包装、执行。HandlerAdapter执行Handler完成后,返回了一个ModleAndView(springmvc封装对象)
DispatherServlet 找一个合适的适配器:
适配器执行Hanlder
4. DispatherServlet拿着ModelAndView调用ViewResolver(视图解析器)进行视图解析,解析完成后返回一个View(很多不同视图类型的View)
视图解析:
5. DispatcherServlet进行视图渲染,将Model中数据放到request域,在页面展示
将model数据放在request域: