是 SpringMVC
springmvc是spring框架的一个模块,springmvc和spring无需通过中间层进行整合;
springmvc是一个基于MVC的web框架;
~ mvc在B/S系统下的应用
mvc是一个设计模式,mvc在B/S系统下的应用:
~ SpringMVC 框架原理
SpringMVC执行过程:
1、客户发起请求到前端控制器(DispatcherServlet);
2、前端控制器请求HandlerMapping查找Handler;可以xml配置、或注释进行查找;
3、处理器映射器HandlerMapping向前端控制器返回Handler;
4、前端控制器调用处理器适配器去执行Handler;
5、处理器适配器去执行Handler;
6、Handler执行完成,给适配器返回ModelAndView;
7、处理器适配器向前端控制器返回ModelAndView;ModelAndView是SpringMVC框架的一个底层对象,包括Model和View;
8、前端控制器请求视图解析器去进行试图解析;(根据逻辑视图名解析成真正的视图:jsp…)
9、视图解析器向前端控制器返回View;
10、前端控制器进行视图渲染;
11、前端控制器向用户响应结果;
SpringMVC重要组件:
1、前端控制器DispatcherServlet (不需要程序员开发)
作用:接收请求啊,响应结果;相当于转发器,中央处理器;有了DispatcherServlet减少了其他组件之间的耦合度;
2、处理器映射器HandlerMapping (不需要程序员开发)
作用:根据请求的url查找Handler;
3、处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler;
4、处理器Handler (需要程序员开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler;
5、视图解析器View resolver (不需要程序员开发)
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
6、视图View (需要程序员开发jsp)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)
>> 入门程序:springmvc
~ 需求
以案例作为驱动:SpringMVC和mybatis使用一个案例(商品订单管理)
功能需求:商品列表查询;
~ 环境准备
1、搭建数据库,4张表:User、Orders、OrderDetail、OItems;
2、创建一个动态Javaweb项目:
3、加入需要的jar包:spring所有jar包、jstl的jar包、logging的jar包、数据库驱动包;
~ 项目结构
~ po类:User、Orders、Orderdetail、Items
// User.java
public class User {
private Integer id; // 用户id
private String username; // 用户姓名
private String sex; // 用户性别
private Date birthday; // 用户生日
private String address; // 用户地址
}
// Orders.java
public class Orders {
private Integer id; // 订单id
private Integer userId; // 下单用户id
private String number; // 订单号
private Date createtime; // 创建订单时间
private String note; // 备注
}
// Orderdetail.java
public class Orderdetail {
private Integer id;
private Integer ordersId; // 订单id
private Integer itemsId; // 商品id
private Integer itemsNum; // 商品购买数量
}
// Items.java
public class Items {
private Integer id;
private String name; // 商品名称
private Float price; // 商品定价
private String pic; // 商品图片
private Date creametime; // 生产日期
private String detail; // 商品描述
}
~ web.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>springmvc</display-name>
<!-- springmvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器、适配器等)
如果不配置contextConfigLocation,
默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<!-- url-pattern 有3种配置方式:
1、*.action,访问以.action为结尾的地址,由DispatcherServlet进行解析;
2、斜杠/,所有访问的地址,都由DispatcherServlet进行解析,
对于静态文件的解析需要配置不让DispatcherServlet进行解析;
使用此种方式可以实现RESTful风格的url;
3、/*,这样配置不对,使用这种配置,最终要转发到一个jsp页面,
仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到Handler,会报错; -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
~ springmvc.xml 文件头
// 在Beans声明处添加aop、context等命名空间的Schema定义文件的说明,这样在配置文件中就可以使用这些命名空间下的配置标签了;
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd ">
// -----------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.2.xsd">
~ springmvc.xml 文件
// 文件头......
<!-- 配置非注解 Handler -->
<bean id="ItemsController1" name="/queryItems.action"
class="cn.itcast.ssm.controller.ItemsController1" />
<bean id="ItemsController5" class="cn.itcast.ssm.controller.ItemsController1" />
<!-- 多个映射器可以并存,前端控制器判断url能让哪些映射器去映射,就让正确的映射器处理; -->
<!-- (1)非注解的处理器映射器:将bean的name作为url进行查找,需要在配置handler时指定beanname(就是url)
在bean里面配置url -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!-- (2)非注解的简单处理器映射器:简单url映射; 将url和handler集中进行配置; -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props> <!-- 同一个bean可以有多个url -->
<!-- 对ItemsController1进行url映射,url是/queryItems1.action -->
<prop key="/queryItems1.action">ItemsController1</prop>
<prop key="/queryItems2.action">ItemsController1</prop>
<prop key="/queryItems5.action">ItemsController5</prop>
</props>
</property>
</bean>
<!-- (1)非注解的处理器适配器1:所有处理器适配器都实现HandlerAdapter接口;
要求:handler实现Controller接口; -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- (2)非注解的处理器适配器2:所有处理器适配器都实现HandlerAdapter接口;
要求:handler实现HttpRequestHandler接口; -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
推荐使用下面这种情况:
<!-- (3)对于注解的Handler可单独配置(不需要写id、name);
实际开发中建议使用组件扫描;可扫描controller、service、...... -->
<!-- <bean class="cn.itcast.ssm.controller.ItemsController3" /> -->
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan> 配置注解的handler
<!-- (3)注意:注解的映射器和适配器必须配对使用! -->
<!-- (3)注解的映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
<!-- (3)注解的适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
<!-- 使用mvc:annotation-driven代替上边的注解映射器和注解适配器配置;
mvc:annotation-driven默认加载很多的参数绑定方法,比如json转换解析器就默认加载了,
如果使用mvc:annotation-driven就不用再配置
上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter了;
实际开发中使用mvc:annotation-driven -->
<!-- <mvc:annotation-driven></mvc:annotation-driven> --> 配置MVC注解驱动
<!-- 视图解析器:解析jsp页面,默认使用jstl标签,classpath系需要有jstl的jar包 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
~ Handler - ItemsController1.java
public class ItemsController1 implements Controller { // 实现Controller接口的处理器 ,根据配置是不使用注解方式
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 调用service查找数据库,查询商品列表,这里使用静态数据模拟;
List<Items> itemsList = new ArrayList<Items>();
Items items1 = new Items(); // 向List中填充静态数据;
items1.setName("联想笔记本");
items1.setPrice(6000f);
items1.setDetail("我的联想笔记本");
Items items2 = new Items();
items2.setName("小米手机");
items2.setPrice(2000f);
items2.setDetail("我的小米手机");
itemsList.add(items1);
itemsList.add(items2);
// 返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 相当于request的setAttribute,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsList", itemsList);
// 指定视图
// modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
modelAndView.setViewName("/items/itemsList");
return modelAndView;
}
}
~ Handler - ItemsController2.java
public class ItemsController2 implements HttpRequestHandler{
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Items> itemsList = new ArrayList<Items>(); //........造数据
// 设置视图模型
request.setAttribute("itemsList", itemsList);
// 设置转发的视图
request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);
// 使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据;
// response.setCharacterEncoding("utf-8");
// response.setContentType("application/json;charset=utf-8");
// response.getWriter().write("json串");
}
}
~ Handler - ItemsController3.java
@Controller // 使用Controllerz注释标识它是一个控制器
public class ItemsController3 { // 注解开发Handler
// 方法1:查询商品列表
// @RequestMapping实现对queryItemsAnnotation方法和url进行映射,一个方法对应一个url
// 一般建议方法名和url写成一样;
@RequestMapping("queryItemsAnnotation")
public ModelAndView queryItemsAnnotation() throws Exception {
List<Items> itemsList = new ArrayList<Items>();
Items items1 = new Items(); // 向List中填充静态数据;
items1.setName("联想笔记本");
items1.setPrice(6000f);
items1.setDetail("我的联想笔记本");
Items items2 = new Items();
items2.setName("小米手机");
items2.setPrice(2000f);
items2.setDetail("我的小米手机");
itemsList.add(items1);
itemsList.add(items2);
// 返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 相当于request的setAttribute,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsList", itemsList);
// 返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 相当于request的setAttribute,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsList", itemsList);
// 指定视图
// 下边的路径,如果在视图解析器中配置jsp路径的前缀和jsp路径的后缀,
// 上边的路径配置可以不在程序中指定jsp路径的前缀和jsp路径的后缀;
// modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
modelAndView.setViewName("items/itemsList");
return modelAndView;
}
// 方法2:添加商品......
}
~ itemsList.jsp
~ itemsList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/item/queryItem.action" method="post">
查询条件:<table width="100%" border="1">
<tr><td><input type="submit" value="查询" /></td></tr>
</table>
商品列表:<table width="100%" border="1">
<tr><td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td> </tr>
<c:forEach items="${itemsList}" var="item">
<tr> <td>${item.name}</td>
<td>${item.price}</td>
<td><fmt:formatDate value="${item.creametime}" pattern="yyyy-MM-dd HH:mm:ss" /></td>
<td>${item.detail}</td>
<td><ahref="${pageContext.request.contextPath}/item/queryItem.action?id=${item.id}}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
~ SpringMVC开发步骤
1、在 web.xml
文件中配置前端控制器:
2、在 springmvc.xml 文件中配置处理器适配器:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
通过查看源代码,可以看出此适配器能执行实现Controller接口的Handler;
3、开发ItemsController1.java:**Handler需要实现Controller接口,才能由org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter适配器执行;
4、编写itemsList.jsp:
5、配置Handler:将编写的Handler在spring容器中加载
<bean name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1" />
6、在 springmvc.xml 文件中配置处理器映射器:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
7、springmvc.xml 文件中配置视图解析器:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />
8、部署调试:访问地址:http://localhost:8080/springmvc/queryItems.action
注意:启动程序的时候使用debug模式,不使用start启动;debug方式启动代码才能实现修改代码时不加方法、参数,不用重启Tomcat,这个叫做热部署,debug才支持热部署;
~ 非注解的处理器映射器
多个映射器可以并存,前端控制器判断url能让哪些映射器去映射,就让正确的映射器处理;
(1)class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"
(2)class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
~ 非注解的处理器适配器
(1)class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"
要求:handler实现Controller接口;
(2)class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"
要求:handler实现HttpRequestHandler接口;
>>>>再次上面的处理器映射器和处理器适配器可以不配对使用
~ 注解的映射器和适配器
配置
(除了使用MVC 注解驱动以外,处理器映射器和处理器适配器必须成对使用, 注意:下面图MVC:annotation-driven应该关闭才对)
注解开发Handler:
在Spring容器中加载Handler: 使用组件扫描
- **部署调试:**访问地址:
http://localhost:8080/springmvc/queryItemsAnnotation.action
~ 视图解析器前缀和后缀
~ 源码分析
- 1、从
web.xml
文件中进入前端控制器,通过前端控制器源码,分析springmvc的执行过程:<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
; - 2、前端控制器接收请求,调用doDispatch()方法:
- 3、前端控制器调用处理器映射器查找Handler:映射器根据request中的url找到了Handler,最后返回一个在执行器链,链里面包含Handler;
- 4、调用处理器适配器去执行Handler,得到执行的结果ModelAndView:
- 5、视图渲染,将Model的数据填充到request域: