Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分
Springmvc处理流程
入门程序
springMVC是表现层框架,需要搭建web工程开发
1、导入jar包
2、加入配置文件
创建SpringMVC的核心配置文件
SpringMVC本身就是Spring的子项目,对Spring兼容性很好,不需要做很多配置。这里只配置一个Controller扫描就可以了,让Spring对页面控制层Controller进行管理。
springmvc.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.ithou.springmvc"/>
</beans>
3、配置前端控制器
在web.xml中配置SpringMVC的前端控制器DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>SpringMVC_01</display-name>
<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>
<!-- 配置SpringMVC前端控制器 -->
<servlet >
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定SpringMVC配置文件 -->
<!-- SpringMVC的配置文件的默认路径是/WEB-INF/${servlet-name}-servlet.xml -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
1. /* 拦截所有 jsp js png .css 真的全拦截,建议不使用
2. *.action *.do 拦截以action、do结尾的请求 肯定能使用,ERP
3. / 拦截所有(不包括jsp)(包括 .js .png .css)强烈建议使用,前台,面向消费者
-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
4、加入jsp页面
5、实现显示商品列表页
分析页面,查看页面需要的数据
创建pojo
public class Item {
// 商品id
private int id;
// 商品名称
private String name;
// 商品价格
private double price;
// 商品创建时间
private Date createtime;
// 商品描述
private String detail;
创建带参数的构造器
set/get。。。
}
6、创建ItemController
ItemController是一个普通的java类,不需要事先任何接口。
需要在类上添加@Controller注解,把Controller交由Spring管理。
在方法上面添加@RequestMapping注解,里面指定请求的url。其中的”.action“可以加也可以不加
@Controller
public class ItemController {
// @RequestMapping:里面放的是请求的url,和用户请求的url进行匹配
// action可以写也可以不写
@RequestMapping("/item/itemList.action")
public ModelAndView itemList() {
// 创建ModelAndView,用来存放数据和视图
ModelAndView mav = new ModelAndView();
// 创建页面需要显示的商品数据
List<Item> list = new ArrayList<Item>();
list.add(new Item(1, "1华为 荣耀8", 2399, new Date(), "质量好!1"));
list.add(new Item(2, "2华为 荣耀8", 2399, new Date(), "质量好!2"));
list.add(new Item(3, "3华为 荣耀8", 2399, new Date(), "质量好!3"));
list.add(new Item(4, "4华为 荣耀8", 2399, new Date(), "质量好!4"));
list.add(new Item(5, "5华为 荣耀8", 2399, new Date(), "质量好!5"));
list.add(new Item(6, "6华为 荣耀8", 2399, new Date(), "质量好!6"));
// 设置数据到模型中
mav.addObject("itemList", list);
// 设置视图jsp,需要设置视图的物理地址
mav.setViewName("/WEB-INF/jsp/itemList.jsp");
return mav;
}
}
测试
启动项目,浏览器访问地址
http://localhost:8080/SpringMVC_01/item/itemList.action
SpringMVC架构
架构流程
- 用户发送请求至前端控制器DispatcherServlet
- DispatcherServlet收到请求调用HandlerMapping处理器映射器
- 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
- DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
- 执行处理器(Controller,也叫后端控制器)
- Controller执行完成返回ModelAndView
- HandleAdapter将controller执行结果ModelAndView返回给DispatcherSerlvet
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- ViewReslover解析后返回具体View
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet相应用户
组件说明
以下组件通常使用框架提供实现:
DispatcherServlet:前端控制器(核心)
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由他调用其他组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
HandlerMapping:处理器映射器(springmvc三大组件之一)
HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
Handler:处理器(需要手动编写)
Handler是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler
HandlerAdapter:处理器适配器(springmvc三大组件之一)
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
ViewResolver:视图解析器(springmvc三大组件之一)
ViewResolver负责将处理结果生成view视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
View:视图(需要手动编写)
springmvc框架提供了很多的View试图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
一般情况下需要通过页面标签或页面模板技术将模型数据通过页面展示给用户,需要有程序员根据业务需求开发具体的页面。
说明:再springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。、
需要由用户开发的组件由handler、view
组件扫描器
使用组件扫描器省去在spring容器配置每个Controller类的繁琐。
使用<context:component-scan>自动扫描标记@Controller的控制器类,
在springmvc.xml配置文件中配置如下:
<!-- 配置controller扫描包,多个包之间用,分隔 -->
<context:component-scan base-package="com.ithou.springmvc"/>
注解映射器和适配器
- 配置处理器映射器
注解式处理器映射器,对类中标记了@ResquestMapping的方法进行映射。根据@ResquestMapping定义的url匹配@ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。
HandlerMethod对象中封装url对应的方法Method。
从spring3.1版本开始,废除了DefaultAnnotationHandlerMapping的使用,推荐使用RequestMappingHandlerMapping完成注解式处理器映射。
在springmvc.xml配置文件中配置如下:
<!-- 配置处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping RequestMappingHandlerMapping"/>
注解描述:@RequestMapping:定义请求url到处理器功能方法的映射
- 配置处理器适配器
注解式处理器适配器,对标记@ResquestMapping的方法进行适配。
从spring3.1版本开始,废除了AnnotationMethodHandlerAdapter的使用,推荐使用RequestMappingHandlerAdapter完成注解式处理器适配。
在springmvc.xml配置文件中配置如下:
<!-- 配置处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter RequestMappingHandlerAdapter"/>
注解驱动
直接配置处理器映射器和处理器适配器比较麻烦,可以使用注解驱动来加载。
SpringMVC使用<mvc:annotation-driven>自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter
可以在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解处理器和适配器的配置。
<!-- 注解驱动:相当于上面两个配置 -->
<mvc:annotation-driven/>
视图解析器
视图解析器使用SpringMVC框架默认的InternalResourceViewResolver,这个视图解析器支持JSP视图解析
在springmvc.xml配置文件中配置如下:
<!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" ->
"/WEB-INF/jsp/test.jsp" -->
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置逻辑视图的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 配置逻辑视图的后缀 -->
<property name="suffix" value=".jsp" />
</bean>
逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为ItemList,则最终返回的jsp视图地址:“WEB-INF/jsp/itemList.jsp”
最终jsp物理地址:前缀+逻辑视图名+后缀
整合mybatis
(spring、springmvc、mybatis三者整合)
- applicatioinContext.xml(spring)
<?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: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.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/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="10" />
<property name="maxIdle" value="5" />
</bean>
<!-- 配置SqlSessioinFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 加载mybatis核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Mapper动态代理开发 扫描 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 基本包 -->
<property name="basePackage" value="com.ithou.springmvc.dao"/>
</bean>
<!-- 注解事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
</bean>
<!-- 开启注解 -->
<tx:annotation-driven/>
</beans>
- SqlMapConfig.xml(mybatis)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.ithou.springmvc.pojo"/>
</typeAliases>
</configuration>
- springmvc.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 扫描@Controler @Service -->
<context:component-scan base-package="com.ithou.springmvc"/>
<!-- 配置处理器映射器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping RequestMappingHandlerMapping"/> -->
<!-- 配置处理器适配器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter RequestMappingHandlerAdapter"/> -->
<!-- 注解驱动:相当于上面两个配置 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
实现商品列表需求
实现商品查询列表,从mysql数据库查询商品信息
ItemService接口
//查询商品列表
public List<Items> selectItemsList();
ItemServiceImpl实现类
@Autowired
private ItemsMapper itemsMapper;
//查询商品列表
@Override
public List<Items> selectItemsList() {
return itemsMapper.selectByExampleWithBLOBs(null);
}
ItemController
@Autowired
private ItemsService itemsService;
@RequestMapping("/item/itemList.action")
public ModelAndView itemList() {
ModelAndView mav = new ModelAndView();
List<Items> list = itemsService.selectItemsList();
mav.addObject("itemList",list);
mav.setViewName("itemList");
return mav;
}
参数绑定
- 默认支持的参数类型
需求:打开商品编辑页面,展开商品信息
ItemService接口
//根据id查询商品
public Items selectById(Integer id);
ItemServiceImpl实现类
//根据id查询商品
public Items selectById(Integer id) {
return itemsMapper.selectByPrimaryKey(id);
}
ItemController
页面点击修改按钮,发起请求,需要从请求的参数中把请求的id取出来。Id包含在Request对象中。可以从Request对象中取id。
想获得Request对象只需要在Controller方法的形参中添加一个参数即可。Springmvc框架会自动把Request对象传递给方法。
@RequestMapping("/item/itemEdit")
public ModelAndView itemEdit(HttpServletRequest request,HttpServletResponse response,HttpSession session,Model model) {
String id = request.getParameter("id");
Items items = itemsService.selectById(Integer.parseInt(id));
ModelAndView mav = new ModelAndView();
mav.addObject("item",items);
mav.setViewName("editItem");
return mav;
}
默认支持的参数类型:处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值
HttpServletRequest:通过request对象获取请求信息
HttpServletResponse:通过response处理响应信息
HttpSession:通过session对象得到session中存放的对象
Model/ModelMap
- Model
除了ModelAmdView以外,还可以使用Model来向页面传递数据,Model是一个接口,在参数里直接声明model即可。
如果使用Model则可以不使用ModelAndView对象,Model对象可以向页面传递数据,View对象则可以使用String返回值代替。
不管是Model还是ModelAndView,其本质都是使用Request对象向jsp传递数据。
例如:
/**
* 根据id查询商品,使用Model
*
* @param request
* @param model
* @return
*/
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, Model model) {
// 从request中获取请求参数
String strId = request.getParameter("id");
Integer id = Integer.valueOf(strId);
// 根据id查询商品数据
Item item = this.itemService.queryItemById(id);
// 把结果传递给页面
// ModelAndView modelAndView = new ModelAndView();
// 把商品数据放在模型中
// modelAndView.addObject("item", item);
// 设置逻辑视图
// modelAndView.setViewName("itemEdit");
// 把商品数据放在模型中
model.addAttribute("item", item);
return "itemEdit";
}
- ModelMap
ModelMap是Model接口的实现类,也可以通过ModelMap向页面传递数据。
使用Model和ModelMap的效果一样,如果直接使用Model,springmvc会实例化ModelMap。
/**
* 根据id查询商品,使用ModelMap
*
* @param request
* @param model
* @return
*/
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, ModelMap model) {
// 从request中获取请求参数
String strId = request.getParameter("id");
Integer id = Integer.valueOf(strId);
// 根据id查询商品数据
Item item = this.itemService.queryItemById(id);
// 把结果传递给页面
// ModelAndView modelAndView = new ModelAndView();
// 把商品数据放在模型中
// modelAndView.addObject("item", item);
// 设置逻辑视图
// modelAndView.setViewName("itemEdit");
// 把商品数据放在模型中
model.addAttribute("item", item);
return "itemEdit";
}
- 绑定简单类型
ItemController
// 参数绑定:简单类型
@RequestMapping("/item/itemEdit2")
public ModelAndView itemEdit2(Integer id,HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model) {
Items items = itemsService.selectById(id);
ModelAndView mav = new ModelAndView();
mav.addObject("item", items);
mav.setViewName("editItem");
return mav;
}
支持的数据类型:参数类型推荐使用包装类型,因为基础数据类型不可以为null。
整形:Integer、int 字符串:String 单精度:Float、float 双精度:Double、double 布尔型:Boolean、boolean
说明:对于布尔型的参数,请求的参数值为true或false。或者1或0
请求url:http://localhost:8080/xxx.action?id=2&status=false
处理器方法:public String editItem(Model model,Integer id,Boolean status)
@RequestParam
使用@RequestParam常用于处理简单类型的绑定。
定义如下:
// 参数绑定:简单类型
@RequestMapping("/item/itemEdit2")
public ModelAndView itemEdit2(@RequestParam(value = "itemId", required = true, defaultValue = "1",HttpServletRequest request, HttpServletResponse response, HttpSession session,Model model) {
Items items = itemsService.selectById(id);
ModelAndView mav = new ModelAndView();
mav.addObject("item", items);
mav.setViewName("editItem");
return mav;
}
- value:参数名字,即入参的请求参数名字,如value=”itemId“表示请求的参数区中的名字为itemId的参数的值将传入
- required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错TTP Status 400 - Required Integer parameter 'XXXX' is not present
- defaultValue:默认值,表示如果请求中没有同名参数时的默认值
- 使用pojo接收表单数据
要求:pojo对象中的属性名和表单中input的name属性一致。
ItemService接口
//修改商品信息
public void updateItemsById(Items item);
ItemService实现类
使用updateByPrimaryKeySelective(item)方法,忽略空参数
@Override
public void updateItemsById(Items item) {
item.setCreatetime(new Date());
itemsMapper.updateByPrimaryKeyWithBLOBs(item);
}
ItemController
//参数绑定:pojo类型
@RequestMapping("updateitem")
public ModelAndView updateItem(Items item) {
itemsService.updateItemsById(item);
ModelAndView mav = new ModelAndView();
mav.addObject("item", item);
mav.setViewName("success");
return mav;
}
注意:提交的表单中不要有日期类型的数据,否则会报400错误。如果想提交日期类型的数据需要用到后面的自定义参数绑定的内容。
解决post乱码问题
在web.xml中加入:
<!-- 解决POST提交乱码问题 -->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
对于get请求中文参数出现乱码解决方法有两个:
- 修改tomcat配置文件添加编码与工程编码一致,如下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
- 另外一种方法对参数进行重新编码:
String userName new
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
- 绑定包装pojo
需求:使用包装的pojo接收商品信息的查询条件。
包装对象定义如下:
public class QueryVo {
private Item item;
set/get。。。
}
接收查询条件:
// 绑定包装数据类型
@RequestMapping("/queryItem")
public String queryItem(QueryVo queryVo) {
System.out.println(queryVo.getItem().getId());
System.out.println(queryVo.getItem().getName());
return "success";
}
页面定义如下图:
- 自定义参数绑定
需求:在商品修改页面可以修改商品的生产日期,并且根据业务需求自定义日期格式。
由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。
前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。可以在springmvc处理器适配器上自定义转换器Converter进行参数绑定。
一般使用<mvc:annotation-driven/>注解驱动加载处理器适配器,可以在此标签上进行配置。
自定义Converter
/**
* 转换日期类型的数据
* S:页面传递过来的数据
* T:转换后的类型
* @author dell
*
*/
public class DateConverter implements Converter<String,Date>{
@Override
public Date convert(String source) {
try {
if(null != source) {
DateFormat df = new SimpleDateFormat("yyyy:MM-dd HH_mm-ss");
return df.parse(source);
}
}catch(Exception e){
}
return null;
}
}
配置Cpnverter
在springmvc.xml中配置Converter
<!-- 注解驱动:相当于上面两个配置 -->
<mvc:annotation-driven conversion-service="conversionService" />
<!-- 配置Converter转换器 转换工厂(日期、去掉前后空格) -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 配置多个转换器 -->
<property name="converters">
<list>
<bean class="com.ithou.springmvc.converter.DateConverter" />
</list>
</property>
</bean>
springmvc与struts2不同
- springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过滤器
- springmvc是基于方法开发(一个url对应一个开发方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
- Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面。jsp视图解析器默认使用jstl。