springMVC学习笔记一:springMVC架构、springmvc绑定各种类型参数,springMVC与struts2的区别

1. SpringMVC学习笔记一: springMVC架构

1.1. springMVC架构

  1. springMVC架构是Struts2架构的替代框架,springMVC是Apache自己开发的,与spring有很好的兼容,同属于web层框架,两者很多地方很相似。
  2. springMVC简单架构

springMVC学习笔记一:springMVC架构、springmvc绑定各种类型参数,springMVC与struts2的区别

1.2. springMVC框架的搭建

  1. 创建web工程
  2. 导包
    • 4个核心包:Bean、Context、core、expression,context-support包
    • 日志包logging
    • jstl包
    • aop,aspect
    • jdbc、tx事务
    • jms,messageing
    • web,webmvc
    • 共15个必备包
  3. 配置springmvc.xml配置包,并对其配置
    • springMVC本身就是spring的一个子项目,对spring兼容性很好,不需要做很多配置,这里只配置一个Controller扫描就行了,让spring对页面控制层Controller进行管理。
    • 添加约束,对Controller即:web层进行扫描。
<?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">

    <!-- 配置controller扫描包 -->
    <context:component-scan base-package="cn.it.springmvc.controller" />

</beans>
  1. 配置前端控制器
    • 在web.xml中配置,类似于配置struts2的核心组件
    • 指定springmvc.xml的配置文件
    • 拦截所有请求,让其进入前端控制器中。
    • 先配置前端控制器,然后再拦截所有请求,让所有请求都要经过前端控制器,在前端控制器中加载springmvc.xml的核心组件。用于扫描所有的Controller包中的类。
<?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-first</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-first</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-first</servlet-name>
        <!-- 设置所有以action结尾的请求进入SpringMVC -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>
  1. springmvc.xml如何获取注入的内容
    • 通过扫描会将com.it包下的所有注解都扫描一下
    • spring就会去自动扫描base-package对应的路径或者该路径的子包下面的java文件,如果扫描到文件中带有@Service,@Component,@Repository,@Controller等这些注解的类,则把这些类注册为bean
    • 注:在注解后加上例如@Component(value=”abc”)时,注册的这个类的bean的id就是adc.
    • 总之通过扫描这些注入的内容就可以获取注入的值。
<!-- 扫描@Controler  @Service   -->
<context:component-scan base-package="com.it"/>
  1. Controller代码
    • RequestMapping提供了请求路径
    • ModelAndView是springMVC提供的,在springMVC的前端控制器层,
    • mav.addObject()表示将list集合添加到itemList的view对象中,由view通过jstl表达式获取。
    • mav.setViewName()。 表示显示view对象页面,view对象通过jstl表达式获取itemList的值。填充数据。响应用户。
@RequestMapping(value = "/item/itemlist.action")
public ModelAndView itemList(){
    // 创建页面需要显示的商品数据
    List<Items> list = new ArrayList<Items>();
    list.add(new Items(1, "1华为 荣耀8", 2399f, new Date(), "质量好!1"));
    ModelAndView mav = new ModelAndView();
    //数据
    mav.addObject("itemList", list);
    mav.setViewName("WEB-INF/jsp/itemList.jsp");
    return mav;
}

1.3. springMVC框架详解

  1. 框架结构

springMVC学习笔记一:springMVC架构、springmvc绑定各种类型参数,springMVC与struts2的区别

  1. 架构流程
    • 用户发送请求,会被web.xml的拦截器拦截送到前端控制器DispatcherServlet
    • DispatcherServlet获得请求后会调用处理器映射器HandMapping。
    • HandMapping会根据url寻找处理的方法,并创建处理器对象,然后将对象返回给DispatcherServlet。
    • DispatcherServlet通过HandlerAdapter处理器适配器调用处理器Handler。
    • Handler处理器会执行处理器Controller,也叫后端控制器。
    • Handler处理器执行完,会将执行结果ModelAndView返回给DispatcherServlet前端控制器。
    • DispatcherServlet前端控制器会将ModelAndView传给ViewReslover视图解析器。
    • ViewReslover解析后返回具体的view给DispatcherServlet,例如上面的itemList集合,封装了数据。
    • DispatchereServlet再将view进行渲染,就是填充具体的数据。生成jsp等页面。
    • DispatcherServlet响应用户。
    • 可以看出DispatcherServlet充当了中间人的效果。

1.4. springmvc组件详解

  1. DispatcherServlet前端控制器
    • DispatcherServlet是整个流程的控制中心,用户发出的请求会被送到DispatcherServlet,DispatcherServlet类似于Struts2框架的控制器,可以调用其他组件。来完成请求操作。
  2. HandlerMapping处理器映射器
    • HandlerMapping:处理器映射器,用于根据用户请求url找到Handler即处理器,springMVC提供了不同的映射器实现不同的映射方式,包含,配置文件方式、接口实现方式、注解方式。
  3. Handler处理器
    • 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体用户请求进行处理,这个需要程序员进行开发。
  4. HandlerAdapter:处理器适配器
    • 用于适配更多类型的处理器进行执行。
  5. ViewResolver视图解析器
    • 将处理结果生成view视图,根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成view视图对象,里面包含了各种数据参数
  6. view视图
    • springmvc框架提供了很多view视图类型的支持,包括jsp,freemarkerView等。
  7. 这六个组件只有view视图,handler处理器需要程序员开发,其他的springmvc在启动时Controller时就会默认加载。省去了不少麻烦。

1.5. 默认加载组件与动态配置jsp页面

  1. 从上面配置的springmvc.xml中看出我们只配置了扫描注入的组件,就能运行项目,是因为springmvc默认加载了DispatherServlet、HandlerMapping、HandlerAdapter适配器。但是这些默认组件随着时间变化已经过期了,必须配置新的组件。
    • 使用注解驱动的方式配置新的组件
    • 下面一个顶上面两个。
<!-- 处理器映射器 -->
<!--         <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->
<!-- 处理器适配器 -->
<!--         <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
<!-- 注解驱动 -->
<mvc:annotation-driven/>
  1. 上面测试代码仍然有个问题就是:访问视图时还要填写路径,这个问题会降低开发的效率,如果不用考虑路径问题就提高了开发效率,springmvc提供了这种机制。
    • 添加视图解释器
    • 在配置中添加路径,和后缀。
<!-- 视图解释器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
  • 这样代码直接写成一个jsp名字就行了
ModelAndView mav = new ModelAndView();
//数据
mav.addObject("itemList", list);
mav.setViewName("itemList");
return mav;

2. springMVC和struts2的区别

  1. 请求入口不同,springMVC接收到请求后会通过web.xml中设置的前端控制器,Struts2接收到请求后会先进入web.xml定义的filter过滤器。
  2. springMVC是基于方法开发,一个url对应一个方法,可以设计为单例或者多例,(建议单例)所谓的多例是实例化对象,比如struts2每次请求就会创建一个Action对象,这就是多例。
  3. Struts2采用值栈存储请求和响应数据,通过OGNL表达式获取数据,springMVC是通过参数解析器将request请求内容解析,并给方法形参赋值,相当于将请求参数给封装了,是对request的封装,即:request.getparameter(),不用写了。将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面,jsp视图解析器默认使用jstl.
  4. 第三个也就是一个有值栈一个没值栈。

3. 整合springmvc+spring+mybatis

3.1. 整合spring+mybatis

  1. 使用****对entity类逆向生成代码和xxxMapper.java
  2. 配置sqlMapConfig.xml
    • 配置约束
    • 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感
    • 本来还要指定扫描代理接口的包的,但是spring框架提供了扫描Mybatis代理接口的包,就不用在sqlMapConfig.xml中写了。在applicationContext.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>
        <!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 -->
        <package name="com.it.springmvc.pojo" />
    </typeAliases>

</configuration>
  1. 添加db.properties,log4j.properties
  2. 配置springmvc.xml
    • 主要包含约束,对控制层的扫描。
    • 注解驱动
    • 视图解释器
<!-- 扫描@Controler  @Service   -->
<context:component-scan base-package="com.itheima"/>
<!-- 注解驱动 -->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
<!-- 视图解释器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>
  1. 配置applicationContext.xml
    • 配置加载外部文件
    • 配置数据库连接池
    • 配置mybatis的session的工厂
    • 配置mapper代理开发
    • 配置事务的注解
    • 配置开启注解
<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的工厂 -->
<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="com.it.springmvc.dao"/>
</bean>
<!-- 注解事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
  1. 配置web.xml
    • 加载applicationContext.xml
    • 加载spring监听器,项目一启动,就加载spring
    • 配置过滤器,用于处理post提交乱码问题。
    • 配置过滤器拦截条件
    • 配置springmvc 前端控制器
    • 配置前端控制器拦截内容
  • 加载spring配置
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
  • 加载监听器
<!-- Spring监听器 -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
  • 解决乱码问题
<!-- 处理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>
  • 前端控制器
<!-- 前端控制器 -->
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 默认找 /WEB-INF/[servlet的名称]-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 拦截以do action 结尾的请求     肯定能使用   ERP  
    3. /  拦截所有 (不包括jsp) (包含.js .png.css)  强烈建议使用     前台 面向消费者  www.jd.com/search   /对静态资源放行
    -->
    <url-pattern>*.action</url-pattern>
</servlet-mapping>
  1. 写Controller层代码
    • 属于中心位置,通过调用其他组件分析请求,并将请求传递到对应的处理器。
    • 本例子是通过注解的方式,让spring配置文件通过扫描注入相应的对象。实例化本身就是spring干的事。
    • 由于springmvc是基于方法开发的,一个url一个方法,因此使用@RequestMapping()来查找请求方法。
    • @Autowired是自动匹配的意思,自动将扫描的结果给属性赋值。
@Controller
public class ItemController {
    @Autowired
    private ItemService itemService;
    //入门程序 第一   包类 + 类包 + 方法名
    @RequestMapping(value = "/item/itemlist.action")
    public ModelAndView itemList(){
        //从Mysql中查询
        List<Items> list = itemService.selectItemsList();
        ModelAndView mav = new ModelAndView();
        //数据
        mav.addObject("itemList", list);
        mav.setViewName("itemList");
        return mav;
    }
  1. 调用service层,service层实现接口后调用代理Mapper接口,完成数据库操作,并将返回的数据封装到ModelAndView对象中。
@Service
public class ItemServiceImpl implements ItemService {
    @Autowired
    private ItemsMapper itemsMapper;
    //查询商品列表
    public List<Items> selectItemsList(){
        return itemsMapper.selectByExampleWithBLOBs(null);
    }

4. 默认参数绑定

4.1. springMVC获取请求参数

  1. springMVC封装了请求参数的获取,相对于struts2要获取请求的参数需要从request中取。
request.getparameter();
  1. springMVC不需要再写这段代码了,因为内部已经封装,只需要在方法内写上参数名字就行了。
  2. 例如对于http://127.0.0.1:8080/springmvc-web/itemEdit.action?id=1 传来的参数id只需要在方法上添加一个参数就能获取request请求的id值。
  3. 当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。这样,从Request取参数的方法就可以进一步简化。
public ModelAndView toEdit(Integer id,
                           HttpServletRequest request,HttpServletResponse response
			,HttpSession session,Model model){

4.2. springMVC默认支持的参数类型

  1. 处理器形参中添加这些类型的参数处理适配器会默认识别并进行赋值。
    • HttpServletRequest:通过request对象获取请求信息。
    • HttpServletResponse:通过Response处理响应信息。
    • HttpSession:通过session对象得到session中存放的对象。
    • Model:Model是一个接口,有一个实现类ModelMap,springMVC会自动实例化这个类。Model作为参数可以向页面传递数据,那么这个时候方法的返回值就不用ModelAndView对象了。可以写一个String。

4.3. springMVC绑定简单类型

  1. 参数推荐使用包装类型
public String editItem(Model model,Integer id,Boolean status)
  1. 如果请求的url里的参数和方法中的参数不一致需要添加@RequestParam,用于处理简单类型的绑定。
    • value:url中参数的名字
    • required:默认true表示请求中一定要有该参数
    • defaultValue:设置默认值。
public ModelAndView toEdit(@RequestParam(value = "id",required = false,defaultValue = "1") Integer idaaq,

4.4. springMVC绑定pojo类型

  1. 如果提交大量参数,比如整个实体类的所有属性,在应用中属于添加新的记录时,这就需要springMVC绑定pojo类型了,当然也可以使用多个参数获取。参数多了貌似也不好看。
  2. 绑定pojo类型也很简单直接在方法参数后面写上pojo类和对象,不过要注意一点,前台提交的参数一定要与实体类中的属性一样,否则会报错。

4.5. springMVC绑定包装类型的pojo类

  1. 创建一个包装的pojo实体类,即:将实体类作为新的包装类的属性,并生成get(),set()方法。
  2. 那么在Controller层传递的对象参数就应该是包装类。
  3. jsp页面填写参数时要这样:属性对象.属性值。
public ModelAndView updateitem(QueryVo vo){
    //修改
    itemService.updateItemsById(vo.getItems());
    ModelAndView mav = new ModelAndView();
    mav.setViewName("success");
    return mav;
}

4.6. spingMVC绑定自定义类型

4.6.1. 自定义转换日期类型
  1. 日期类型种类很多,springmvc无法将字符串变成日期格式,这就需要自定义类了。
4.6.2. 绑定自定义日期转换类型步骤
  1. 前台将日期字符串提交,需要通过映射器找方法,映射器找到后传递给前端控制器DispatcherServlet,DispathcerServlet调用适配器寻找合适的处理器。在这个过程中可以将时间参数进行转换,spring提供了转换的工厂,我们只需要自己实现这个转换类。
  2. 配置注解驱动,从转换工厂中获取转换类。
    • 日期转换工厂:FormattingConversionServiceFactoryBean
<!-- 注解驱动 -->
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>

<!-- 配置Conveter转换器  转换工厂 (日期、去掉前后空格)。。 -->
<bean id="conversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <!-- 配置 多个转换器-->
    <property name="converters">
        <list>
            <bean class="com.it.springmvc.conversion.DateConveter"/>
        </list>
    </property>
</bean>
  1. 日期转换类
    • 目的将SimpleDateFormat()中的字符串转换成格林威治日期。
/**
 * 转换日期类型的数据
 * S : 页面传递过来的类型
 * T : 转换后的类型
 *
 */
public class DateConveter implements Converter<String, Date>{

    public Date convert(String source) {
        // TODO Auto-generated method stub
        try {
            if(null != source){//2016:11-05 11_43-50
                DateFormat df = new SimpleDateFormat("yyyy:MM-dd HH_mm-ss");
                return df.parse(source);
            }
        } catch (Exception e) {
        }
        return null;
    }
}
  1. 通过类的转换继续提交参数。

5. springMVC和struts2区别再总结

  1. Struts2绑定前端传来的参数是绑定在成员属性上,SpringMVC绑定在方法形参上。
  2. Struts2存数据是存放在值栈中,通过OGNL存取数据。而spingMVC是存放在request域中。没有值栈。
  3. springMVC入口是servlet前端控制器DispatcherServlet,而Struts2是filter过滤器
  4. Struts2只能多例,每一次请求创建一个Action,springMVC基于方法,的是单例,也可以多例。