02 springmvc和mybatis整合

需求

使用springmvc和mybatis完成商品列表查询

整合思路

springmvc+mybaits的系统架构:

第一步:整合dao层
mybatis和spring整合,通过spring管理mapper接口。
使用mapper的扫描器自动扫描mapper接口在spring中进行注册。

第二步:整合service层
通过spring管理 service接口。
使用配置方式将service接口配置在spring配置文件中。
实现事务控制。

第三步:整合springmvc
由于springmvc是spring的模块,不需要整合。

准备环境

所需要的jar包:
数据库驱动包:mysql5.1
mybatis的jar包
mybatis和spring整合包
log4j包
dbcp数据库连接池包
spring3.2所有jar包
jstl包

log4j.properties

# Global logging configuration\uFF0C\u5EFA\u8BAE\u5F00\u53D1\u73AF\u5883\u4E2D\u8981\u7528debug
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=suntong


整合dao

mybatis和spring进行整合。

  1. 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>

        <!-- 全局setting配置
            根据需要加
         -->
         

        <!-- 配置别名 -->
        <typeAliases>
            <!-- 批量扫描别名 -->
            <package name="cn.itcast.ssm.po"/>
        </typeAliases>
        

        <!-- 配置mapper  
            由于使用spring和mybatis的整合包进行mapper扫描,这里不需要配置 
            必须遵循:mapper.xml和mapper.java文件同名,且在一个目录
        -->
        
</configuration>

  1. applicationContext-dao.xml

配置:
数据源
SqlSessionFactory
mapper扫描器

<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 ">

    <!-- 加载db.properties文件中的内容,db.properties中的key命名要有一定的规则 -->
    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 配置数据源,dbcp -->
    <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="30"/>
        <property name="maxIdle" value="5"/>
    </bean> 
    
    <!-- sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
        <!-- 加载mybatis的全局配置文件 -->
        <property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml" />
    </bean>
    
    <!-- 配置mapper扫描器 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 扫描包路径,如果需要扫描多个包,中间使用半角逗号隔开 -->
        <property name="basePackage" value="cn.itcast.ssm.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>
    
    

</beans>
  1. 逆向工程生成po类及mapper(单表增删改查)

4.手动定义商品查询mapper

针对综合查询mapper,一般情况会有关联查询,建议自定义mapper

  • ItemsMapperCustom.xml

sql语句:
SELECT * FROM items WHERE items.name LIKE '%笔记本%'


<?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.itcast.ssm.mapper.ItemsMapperCustom" >

   <!-- 定义商品查询的sql片段,就是商品查询条件 -->
   <sql id="query_items_where">
    <!-- 使用动态sql,通过if判断,满足条件进行sql拼接 -->
    <!-- 商品查询条件通过ItemsQueryVo包装对象 中itemsCustom属性传递 -->
        <if test="itemsCustom!=null">
            <if test="itemsCustom.name!=null and itemsCustom.name!=''">
                items.name LIKE '%${itemsCustom.name}%'
            </if>
        </if>
    
   </sql>
    
    <!-- 商品列表查询 -->
    <!-- parameterType传入包装对象(包装了查询条件)
        resultType建议使用扩展对象
     -->
    <select id="findItemsList" parameterType="cn.itcast.ssm.po.ItemsQueryVo"
         resultType="cn.itcast.ssm.po.ItemsCustom">
        SELECT items.* FROM items  
        <where>
            <include refid="query_items_where"></include>
        </where>
    </select>
    
</mapper>
  • ItemsMapperCustom.java
package cn.itcast.ssm.mapper;

import cn.itcast.ssm.po.Items;
import cn.itcast.ssm.po.ItemsCustom;
import cn.itcast.ssm.po.ItemsExample;
import cn.itcast.ssm.po.ItemsQueryVo;

import java.util.List;
import org.apache.ibatis.annotations.Param;

public interface ItemsMapperCustom {
    //商品的查询列表
    public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo)throws Exception;
}

整合service

  1. 定义service接口

让spring管理service接口。

ItemsService.java

package cn.itcast.ssm.service;

import java.util.List;

import cn.itcast.ssm.po.ItemsCustom;
import cn.itcast.ssm.po.ItemsQueryVo;

/*
 * 商品管理的service
 * */

public interface ItemsService {

    //商品查询列表
    public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception;
}

实现类ItemsServiceImpl.java

package cn.itcast.ssm.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import cn.itcast.ssm.mapper.ItemsMapperCustom;
import cn.itcast.ssm.po.ItemsCustom;
import cn.itcast.ssm.po.ItemsQueryVo;
import cn.itcast.ssm.service.ItemsService;

/*
 * 商品的管理
 * 
 * */

public class ItemsServiceImpl implements ItemsService {

    @Autowired
    private ItemsMapperCustom itemsMapperCustom;
    
    @Override
    public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {
        // 通过ItemsMapperCustom查询数据库
        return itemsMapperCustom.findItemsList(itemsQueryVo);
    }

}

  1. 在spring容器配置service(applicationContext-service.xml)

创建applicationContext-service.xml,文件中配置service。

<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 ">

    
    <!-- 定义商品管理的service -->
    <bean id="itemsService" class="cn.itcast.ssm.service.impl.ItemsServiceImpl"></bean>

</beans>
  1. 事务控制(applicationContext-transaction.xml)

在applicationContext-transaction.xml中使用spring声明式事务控制方法。

<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 ">

    
    <!-- 事务管理器
        对mybatis操作数据库事务控制,spring使用jdbc的事务控制类
     -->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager.class">
        <!-- 数据源,在另一个文件中配置了 -->
        <property name="dataSource" ref="dataSource"></property>
        
     </bean>
     
     <!-- 通知 -->
     <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 传播行为 -->
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="insert*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
     </tx:advice>
     
     <!-- aop -->
     <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.itcast.ssm.service.impl.*.*(..))"/>
     </aop:config>

</beans>

整合springmvc

  1. springmvc.xml

创建springmvc.xml文件,配置处理器映射器、适配器、视图解析器。

<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-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/context 
        http://www.springframework.org/schema/context/spring-context-4.2.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">
<!-- 顺序无所谓 -->
    
    
    <!-- 可以扫描controller、service。。。
        这里扫描controller,指定controller的包
     -->
    <context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
    
    
    <!--注解映射器 
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    
    注解适配器 
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    
    使用mvc:annotation-driven可以代替上边注解映射器和注解适配器配置
        同时mvc:annotation-driven注解驱动默认加载很多的参数绑定方法,比如json转换解析器默认加载了,如果使用,不用配置
        实际开发用这个mvc:annotation-driven
    -->
    <mvc:annotation-driven></mvc:annotation-driven>
     
    
    
    <!-- 视图解析器
        解析jsp视图,默认使用jstl标签,classpath下得有jstl的包
     -->
     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
        
     </bean>


</beans>
  1. 配置前端控制器

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_mybatis01</display-name>
  
    
 <!-- springmvc前端控制器 -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器、适配器等等)
    如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-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>
    <!-- 
    第一种:*.action,访问以.action结尾 由DispatcherServlet进行解析
    第二种:/,所以访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析
    使用此种方式可以实现 RESTful风格的url
    第三种:/*,这样配置不对,使用这种配置,最终要转发到一个jsp页面时,
    仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错。
    
     -->
    <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>

同入门程序

  1. 编写Controller(就是Handler)

ItemsController.java

package cn.itcast.ssm.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import cn.itcast.ssm.po.Items;
import cn.itcast.ssm.po.ItemsCustom;
import cn.itcast.ssm.service.ItemsService;

/*
 * 商品的Controller
 * 
 * */

@Controller
public class ItemsController {
    
    @Autowired
    private ItemsService itemsService;
    

    //商品查询
    @RequestMapping("/queryItems")
    public ModelAndView queryItems() throws Exception{
        

        //调用service查找数据库,查询商品列表,这里使用静态数据模拟
        List<ItemsCustom> itemsList = itemsService.findItemsList(null);
        

        //返回ModelAndView
        ModelAndView modelAndView = new ModelAndView();
        //相当于request的setAttribute,在jsp页面中通过itemsList取数据
        modelAndView.addObject("itemsList",itemsList);
        
        //指定视图
        //下边的路径如果在视图解析器中配置jsp路径的前缀和后缀,/WEB-INF/jsp/items/itemsList.jsp修改为items/itemsList
        modelAndView.setViewName("items/itemsList");
        
        return modelAndView;
        
    }
    
    
    //商品修改
}

编写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.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
    <td>${item.detail }</td>
    
    <td><a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a></td>

</tr>
</c:forEach>

</table>
</form>
</body>

</html>

加载spring容器

将mapper、service、controller加载到spring容器中。

建议使用通配符加载上边的配置文件。

在web.xml中,添加spring容器监听器,加载spring容器。

<!-- 加载spring容器 -->
  <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/spring/applicationContext-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

商品修改功能开发

需求

操作流程:
1、进入商品查询列表页面
2、点击修改,进入商品修改页面,页面中显示了要修改的商品(从数据库查询)
要修改的商品从数据库查询,根据商品id(主键)查询商品信息

3、在商品修改页面,修改商品信息,修改后,点击提交

开发mapper

mapper:
根据id查询商品信息
根据id更新Items表的数据
不用开发了,使用逆向工程生成的代码。

开发service

接口功能:
根据id查询商品信息
修改商品信息

ItemsService.java


package cn.itcast.ssm.service;

import java.util.List;

import cn.itcast.ssm.po.ItemsCustom;
import cn.itcast.ssm.po.ItemsQueryVo;

/*
 * 商品管理的service
 * */

public interface ItemsService {

    //商品查询列表
    public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception;
    
    //根据id查询商品信息
    public ItemsCustom findItemsById(Integer id) throws Exception;
    
    //修改商品信息
    public void updateItems(Integer id,ItemsCustom itemsCustom) throws Exception;
    
}

ItemsServiceImpl.java

package cn.itcast.ssm.service.impl;

import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import cn.itcast.ssm.mapper.ItemsMapper;
import cn.itcast.ssm.mapper.ItemsMapperCustom;
import cn.itcast.ssm.po.Items;
import cn.itcast.ssm.po.ItemsCustom;
import cn.itcast.ssm.po.ItemsQueryVo;
import cn.itcast.ssm.service.ItemsService;

/*
 * 商品的管理
 * 
 * */

public class ItemsServiceImpl implements ItemsService {

    @Autowired
    private ItemsMapperCustom itemsMapperCustom;
    
    @Autowired
    private ItemsMapper itemsMapper;
    
    @Override
    public List<ItemsCustom> findItemsList(ItemsQueryVo itemsQueryVo) throws Exception {
        // 通过ItemsMapperCustom查询数据库
        return itemsMapperCustom.findItemsList(itemsQueryVo);
    }

    @Override
    public ItemsCustom findItemsById(Integer id) throws Exception {
        
        Items items = itemsMapper.selectByPrimaryKey(id);
        //中间对商品信息进行业务处理
        //....
        //返回ItemsCustom
        ItemsCustom itemsCustom = new ItemsCustom();
        //将items的内容拷贝到itemsCustom
        BeanUtils.copyProperties(items, itemsCustom);
        
        return itemsCustom;
        
        
    }

    @Override
    public void updateItems(Integer id, ItemsCustom itemsCustom) throws Exception {

        //添加业务校验,通常在service接口对关键参数进行校验
        //校验id是否为空,如果为空,抛出异常
        
        
        //更新商品信息
        //使用此方法可以根据id更新items表中所有字段,包括大文本类型
        //要求必须传入id,哪怕是重复操作
        itemsCustom.setId(id);
        itemsMapper.updateByPrimaryKeyWithBLOBs(itemsCustom);
        
    }

}

开发controller

方法:
商品信息修改页面显示
商品信息修改提交

ItemController.java

//商品信息修改页面显示
    @RequestMapping("/editItems")
    public ModelAndView editItems() throws Exception{
        
        //调用service根据商品id查询商品信息
        ItemsCustom itemsCustom = itemsService.findItemsById(1);
        
        //返回ModelAndView
        ModelAndView modelAndView = new ModelAndView();
        
        //将商品信息放到model
        modelAndView.addObject("itemsCusom", itemsCustom);
        
        //商品修改页面
        modelAndView.setViewName("items/editItems");
        
        return modelAndView;
    }
    
    
    
    //商品信息修改提交
    @RequestMapping("/editItemsSubmit")
    public ModelAndView editItemsSubmit() throws Exception{
        
        //调用service更新商品信息,页面需要将商品信息传到此方法
        //....
        
        

        //返回ModelAndView
        ModelAndView modelAndView = new ModelAndView();
        
        //返回一个成功页面
        modelAndView.setViewName("success");
        
        return modelAndView;
        
    }

editItems.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 id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action" method="post" >
<input type="hidden" name="id" value="${itemsCustom.id }"/>
修改商品信息:
<table width="100%" border=1>
<tr>
    <td>商品名称</td>
    <td><input type="text" name="name" value="${itemsCustom.name }"/></td>
</tr>
<tr>
    <td>商品价格</td>
    <td><input type="text" name="price" value="${itemsCustom.price }"/></td>
</tr>
<tr>
    <td>商品生产日期</td>
    <td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
</tr>
<%-- <tr>
    <td>商品图片</td>
    <td>
        <c:if test="${item.pic !=null}">
            <img src="/pic/${item.pic}" width=100 height=100/>
            <br/>
        </c:if>
        <input type="file"  name="pictureFile"/> 
    </td>
</tr> --%>
<tr>
    <td>商品简介</td>
    <td>
    <textarea rows="3" cols="30" name="detail">${itemsCustom.detail }</textarea>
    </td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/>
</td>
</tr>
</table>

</form>
</body>

</html>

@ResultMapping

  • url映射
    定义controller方法对应的url,进行处理器映射使用。

  • 窄化请求映射

  • 限制http请求方法

出于安全性考虑,对http的链接进行方法限制。
如果限制请求为post方法,进行get请求,报错:

controller方法的返回值

  • 返回ModelAndView

需要方法结束时,定义ModelAndView,将model和view分别进行设置。

  • 返回string

如果controller方法返回string,

  1. 表示返回逻辑视图名

真正视图(jsp路径)=前缀+逻辑视图名+后缀

@RequestMapping(value="/editItems",method= {RequestMethod.POST})
    public String editItems(Model model) throws Exception{
        
        //调用service根据商品id查询商品信息
        ItemsCustom itemsCustom = itemsService.findItemsById(1);
        
//      //返回ModelAndView
//      ModelAndView modelAndView = new ModelAndView();
//      
//      //将商品信息放到model
//      modelAndView.addObject("itemsCusom", itemsCustom);
//      
//      //商品修改页面
//      modelAndView.setViewName("items/editItems");
        
        
        //通过形参中的model将model数据传到页面
        //相当于modelAndView.addObject方法
        model.addAttribute("itemsCusom", itemsCustom);
        
        return "items/editItems";
    }
  1. redirect重定向

商品修改提交后,重定向到商品查询列表。
redirect重定向特点:浏览器地址栏中的url会变化。修改提交的request数据无法传到重定向的地址。因为重定向后重新进行request(request无法共享)

@RequestMapping("/editItemsSubmit")
    public String editItemsSubmit() throws Exception{
        
        //调用service更新商品信息,页面需要将商品信息传到此方法
        //....
        
        
        ////重定向到商品列表                        一个controller中不用加根路径
        return "redirect:queryItems.action";
        
        
    }
  1. forward页面转发

通过forward进行页面转发,浏览器地址栏url不变,request可以共享。

@RequestMapping("/editItemsSubmit")
    public String editItemsSubmit(HttpServletRequest request) throws Exception{
        
        //调用service更新商品信息,页面需要将商品信息传到此方法
        //....
        
        
        //重定向到商品列表                        一个controller中不用加根路径
        //重定向
        //return "redirect:queryItems.action";
        
        //转发
        return "forward:queryItems.action";
        
        
    }
  • 返回void

在controller方法形参上可以定义request和response,使用request或response指定响应结果:

1、使用request转向页面,如下:
request.getRequestDispatcher("页面路径").forward(request, response);

2、也可以通过response页面重定向:
response.sendRedirect("url")

3、也可以通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");

参数绑定

参数绑定过程

从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。

springmvc中,接收页面提交的数据是通过方法形参来接收。而不是在controller类定义成员变量接收!!!!

默认支持类型

直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。

  1. HttpServletRequest
    通过request对象获取请求信息

  2. HttpServletResponse
    通过response处理响应信息

  3. HttpSession
    通过session对象得到session中存放的对象

  4. Model/ModelMap
    model是一个接口,modelMap是一个接口实现 。

作用:将model数据填充到request域

简单类型

通过@RequestParam对简单类型的参数进行绑定。
如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可绑定成功。

如果使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致。

通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,报下边错误:

@RequestMapping(value="/editItems",method= {RequestMethod.POST})
//  @RequestParam里面指定request传入的参数名和形参进行绑定
    //通过required属性指定参数是否必须传入
    //通过defaultValue可以设置默认值,如果id参数没有参数,将默认值和形参绑定。
    public String editItems(Model model,@RequestParam(value="id", required=true) Integer item_id) throws Exception{
        
        //调用service根据商品id查询商品信息
        ItemsCustom itemsCustom = itemsService.findItemsById(item_id);
        
//      //返回ModelAndView
//      ModelAndView modelAndView = new ModelAndView();
//      
//      //将商品信息放到model
//      modelAndView.addObject("itemsCusom", itemsCustom);
//      
//      //商品修改页面
//      modelAndView.setViewName("items/editItems");
        
        
        //通过形参中的model将model数据传到页面
        //相当于modelAndView.addObject方法
        model.addAttribute("itemsCusom", itemsCustom);
        
        return "items/editItems";
    }

参考教案 对其它简单类型绑定进行测试。

pojo绑定

页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo。

页面定义:

controller的pojo形参的定义:

自定义参数绑定实现日期类型绑定

对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。
将请求日期数据串传成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致。

所以自定义参数绑定将日期串转成java.util.Date类型。

需要向处理器适配器中注入自定义的参数绑定组件。

  1. 自定义日期类型绑定

CustomDateConverter.java

package cn.itcast.ssm.controller.converter;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.core.convert.converter.Converter;

public class CustomDateConverter implements Converter<String, Date> {

    @Override
    public Date convert(String source) {
        
        //实现日期串转成日期类型(格式"yyyy-MM-dd HH:mm:ss")
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //转成直接返回
            return simpleDateFormat.parse(source);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //如果参数绑定失败返回null
        return null;
    }

}

springmvc.xml

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>


    <!-- 自定义参数绑定 -->
    <bean id="conversionService"
        class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!-- 转换器 -->
        <property name="converters">
            <list>
                <!-- 日期类型转换 -->
                <bean class="cn.itcast.ssm.controller.converter.CustomDateConverter"/>
            </list>
        </property>
    </bean>

springmvc和struts2的区别

  1. springmvc基于方法开发的,struts2基于类开发的。
    springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括了一个method。
    方法执行结束,形参数据销毁。
    springmvc的controller开发类似service开发。

  2. springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。

  3. 经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts建议使用jstl。

问题

post乱码

在web.xml添加post乱码filter

在web.xml中加入:

<!-- post乱码过虑器 -->
    <filter>
        <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

以上可以解决post请求乱码问题。
对于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编码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容