SpringMVC简介
Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分。
JavaEE三层架构
- 表现层 WEB层(采用JSP/Servlet/Struts2/SpringMVC技术):展示数据用的。
- 应用层 Service层(采用Bean/EJB技术):处理业务逻辑,一般if判断,循环之类。
- 数据层 Dao层(准确的说是数据接口,采用JDBC/Hibernate/Mybatis技术):保存数据和访问数据的。
SpringMVC架构
请求流程
- 1、 用户发送请求至前端控制器DispatcherServlet
- 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 3、 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- 4、 DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
- 5、 执行处理器(Controller,也叫后端控制器)。
- 6、 Controller执行完成返回ModelAndView
- 7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
- 8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- 9、 ViewReslover解析后返回具体View
- 10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
- 11、 DispatcherServlet响应用户
组件说明
DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
Handler:处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
下图是许多不同的适配器,最终都可以使用usb接口连接
ViewResolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
View:视图
springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
一.SpringMVC搭建
1、导包
2、配置SpringMVC
<?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:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!--*****************配置各种 注解******************--> <!-- 配置注解驱动(由于默认的已经过时),用于扫描RequestMapping等注解 --> <mvc:annotation-driven /> <!-- 扫描@Controler,@Service... --> <context:component-scan base-package="cn.x5456"/> <!-- 视图解释器 modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp"); ==> modelAndView.setViewName("itemList"); --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
3、配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 配置寻找的配置文件+监听器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 前端控制器 --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <!-- 1. /* 拦截所有 jsp js png .css 真的全拦截 建议不使用 2. *.action *.do 拦截以do action 结尾的请求 肯定能使用 ERP 3. / 拦截所有 (不包括jsp) (包含.js .png.css) 强烈建议使用 前台 面向消费者 www.jd.com/search /对静态资源放行 --> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
4、书写controller
// 将类交由Spring管理 @Controller public class ItemsController { @Autowired private ItemService itemService; // 配置请求的url @RequestMapping("/itemList.action") public ModelAndView queryItemList(){ // 创建页面需要显示的商品数据 List<Item> items = itemService.selectItemsList(); ModelAndView modelAndView = new ModelAndView(); // 放到request域中 modelAndView.addObject("itemList",items); //modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp"); modelAndView.setViewName("itemList"); return modelAndView; }
注:不要导错包
二.与Mybatis整合
1、配置与Mybatis整合的applicationContext.xml
<!-- ****************整合Mybatis**************** --> <!-- 读取配置文件 --> <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> <!-- 建立Mybatis的SQLSessionFactory工厂 --> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注入连接池 --> <property name="dataSource" ref="dataSource"/> <!-- 核心配置文件的位置 --> <property name="configLocation" value="classpath:sqlMapConfig.xml"/> </bean> <!-- Mapper动态代理开发 扫描 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 基本包,会自动扫描子包 --> <property name="basePackage" value="cn.x5456.dao"/> </bean> <!--******************配置 注解 事务********************--> <!-- 配置事务核心管理器,封装了所有事务操作. 依赖于连接池 --> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name="dataSource" ref="dataSource" /> </bean> <!-- 开启使用注解管理aop事务 --> <tx:annotation-driven/>
2、配置sqlMapConfig.xml
<?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="cn.x5456.domain" /> </typeAliases> <mappers> <package name="cn.x5456.dao"/> <!--配置扫描mapper接口(一定要配)--> </mappers> </configuration>
3、db.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8 jdbc.username=root jdbc.password=xxx
4、service层
ItemService.java
public interface ItemService { public List<Item> selectItemsList(); }
ItemServiceImpl.java
@Service public class ItemServiceImpl implements ItemService { @Autowired private ItemDao itemDao; public List<Item> selectItemsList() { List<Item> itemList = itemDao.findItemList(); return itemList; } }
5、Dao层
ItemDao.java
public interface ItemDao { List<Item> findItemList(); }
ItemDao.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.x5456.dao.ItemDao"> <!-- 将当前接口与接口绑定 --> <!-- 查询所有订单 --> <select id="findItemList" resultType="Item"> select * from `item` </select> </mapper>
三.接收参数
方式一:接收HttpServletRequest,HttpServletResponse,HttpSession, Model转Servlet时代的开发
// 获取与当前线程绑定的request,response,session,model @RequestMapping("/itemEdit.action") public ModelAndView itemEdit(HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model){ // 方式一:Servlet时代开发方式 // 1.接受参数 String id = request.getParameter("id"); // 2.获取当前商品信息 Item item = itemService.selectItem(Integer.parseInt(id)); System.out.println(item); // 3.放到request域中 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("item",item); // 4.设置跳转的页面 modelAndView.setViewName("editItem"); return modelAndView; }
方式二:直接接收参数
// 获取与当前线程绑定的request,response,session,model @RequestMapping("/itemEdit.action") public ModelAndView itemEdit(Integer id,HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model){ // 方式二:直接接收参数,字段名必须和表单传来的一样 // 1.接受参数 //String id = request.getParameter("id"); // 2.获取当前商品信息 Item item = itemService.selectItem(id); System.out.println(item); // 3.放到request域中 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("item",item); // 4.设置跳转的页面 modelAndView.setViewName("editItem"); return modelAndView; }
方式三:接收参数,封装到POJO中
// 获取与当前线程绑定的request,response,session,model @RequestMapping("/itemEdit.action") public ModelAndView itemEdit(Item itemPOJO,HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model){ // 方式三:接收参数,封装到POJO中 // 1.接受参数 //String id = request.getParameter("id"); // 2.获取当前商品信息 Item item = itemService.selectItem(itemPOJO.getId()); System.out.println(item); // 3.放到request域中 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("item",item); // 4.设置跳转的页面 modelAndView.setViewName("editItem"); return modelAndView; }
四.其他
1、配置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>
2、配置转换器
applicationContext.xml
<!-- 配置注解驱动(由于默认的已经过时),用于扫描RequestMapping等注解 --> <!-- 配置转换器 --> <mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/> <!-- 配置Conveter转换器 转换工厂 (日期、去掉前后空格)... --> <bean id="conversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 配置 多个转换器--> <property name="converters"> <list> <!--只要是Date格式的,就走这个转换器(因为接受的是Date类型)--> <bean class="cn.x5456.conversion.DateConveter"/> </list> </property> </bean>
DateConveter.java
public class DateConveter implements Converter<String, Date> { @Override public Date convert(String s) { if (s!=null&&!s.equals("")){ try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy:MM-dd HH_mm-ss"); Date realDate = simpleDateFormat.parse(s); return realDate; } catch (ParseException e) { e.printStackTrace(); } } return null; } }