Top

JAVA SPRINGMYBATIS02 UNIT06

  1. Spring声明式事务-注解应用
  2. Spring声明式事务-XML配置
  3. Spring声明式事务-回滚机制
  4. RESTful应用案例

1 Spring声明式事务-注解应用

1.1 问题

使用Spring注解实现声明式事务,管理Controller中各业务方法的事务。

1.2 方案

Spring事务注解使用步骤:

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:测试未管理事务的情况

复制项目SpringUnit05,创建新项目SpringUnit06。

在EmpController中,增加批量添加员工的方法,并模拟实现,代码如下:

  1. package com.tarena.controller;
  2.  
  3. import javax.annotation.Resource;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.transaction.annotation.Transactional;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import com.tarena.dao.EmpDao;
  8. import com.tarena.entity.Emp;
  9.  
  10. @Controller
  11. @RequestMapping("/emp")
  12. public class EmpController {
  13.     
  14.     @Resource
  15.     private EmpDao empDao;
  16.  
  17.     //其他方法略
  18.  
  19.     /**
  20.      * 模拟批量添加员工
  21.      */
  22.     @RequestMapping("/addEmps.do")
  23.     public String addBatch() {
  24.         // 插入第一个员工
  25.         Emp e1 = new Emp();
  26.         e1.setEname("刘备");
  27.         e1.setJob("皇叔");
  28.         e1.setSal(1000.0);
  29.         e1.setEmpno(10);
  30.         empDao.save(e1);
  31.         
  32.         // 模拟异常
  33.         Integer.valueOf("abc"); //ClassCastException
  34.         
  35.         // 插入第二个员工
  36.         Emp e2 = new Emp();
  37.         e2.setEname("关羽");
  38.         e2.setJob("候");
  39.         e2.setSal(1000.0);
  40.         e2.setEmpno(10);
  41.         empDao.save(e2);
  42.         
  43.         return "redirect:findEmp.do";
  44.     }
  45.  
  46. }

在TestEmpController中,增加测试方法,测试批量添加员工,代码如下:

  1. package com.tarena.test;
  2.  
  3. import org.junit.Test;
  4. import org.springframework.context.ApplicationContext;
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;
  6. import com.tarena.controller.EmpController;
  7.  
  8. public class TestEmpController {
  9.     
  10. //其他方法略
  11.  
  12.     /**
  13.      * 测试批量添加员工
  14.      */
  15.     @Test
  16.     public void test2() throws ClassNotFoundException {
  17.         ApplicationContext ctx = new ClassPathXmlApplicationContext(
  18.                 "applicationContext.xml");
  19.         EmpController ctl = ctx.getBean(EmpController.class);
  20.         ctl.addBatch();
  21.     }
  22.     
  23. }

没有执行该测试方法前,员工表中的数据如下图:

图-1

执行该测试方法后,员工表中的数据如下图:

图-2

可见,员工刘备添加成功。但EmpController.addBatch()方法是业务方法,体现了完整的业务逻辑,发生异常时应该整个业务失败,而不是一部分成功一部分失败,因此添加刘备成功是不符合要求的,应该引入事务管理机制来解决此问题。

步骤二:声明事务组件

在applicationContext.xml中声明事务组件,关键代码如下:

  1.     <!-- 声明事务管理组件 -->
  2.     <bean id="txManager"
  3.         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  4.         <property name="dataSource" ref="ds"/>
  5.     </bean>

步骤三:开启事务注解扫描

在applicationContext.xml中,开启事务注解扫描,关键代码如下:

  1.     <!-- 声明事务管理组件 -->
  2.     <bean id="txManager"
  3.         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  4.         <property name="dataSource" ref="ds"/>
  5.     </bean>
  6.     
  7.     <!-- 开启事务注解扫描 -->
  8.     <tx:annotation-driven
  9.         transaction-manager="txManager" proxy-target-class="true"/>

步骤四:使用注解标识类/方法

在EmpController中,使用注解对该方法启用事务管理,代码如下:

  1. package com.tarena.controller;
  2.  
  3. import javax.annotation.Resource;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.transaction.annotation.Transactional;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import com.tarena.dao.EmpDao;
  8. import com.tarena.entity.Emp;
  9.  
  10. @Controller
  11. @RequestMapping("/emp")
  12. @Transactional
  13. public class EmpController {
  14.     
  15.     @Resource
  16.     private EmpDao empDao;
  17.  
  18. //其他方法略
  19.  
  20.     /**
  21.      * 模拟批量添加员工
  22.      */
  23.     @RequestMapping("/addEmps.do")
  24.     public String addBatch() {
  25.         // 插入第一个员工
  26.         Emp e1 = new Emp();
  27.         e1.setEname("刘备");
  28.         e1.setJob("皇叔");
  29.         e1.setSal(1000.0);
  30.         e1.setEmpno(10);
  31.         empDao.save(e1);
  32.         
  33.         // 模拟异常
  34.         Integer.valueOf("abc"); //ClassCastException
  35.                 
  36.         // 插入第二个员工
  37.         Emp e2 = new Emp();
  38.         e2.setEname("关羽");
  39.         e2.setJob("候");
  40.         e2.setSal(1000.0);
  41.         e2.setEmpno(10);
  42.         empDao.save(e2);
  43.         
  44.         return "redirect:findEmp.do";
  45.     }
  46.  
  47. }

步骤五:测试

手动删除员工表中的刘备,执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:

图-3

可见,在引入了事务管理机制后,业务方法发生异常时,由于事务回滚,所以没有成功插入员工刘备,从而保证了业务的完整性。

1.4 完整代码

本案例的完整代码如下所示:

EmpController完整代码如下:

TestEmpController完整代码如下:

applicationContext.xml完整代码如下:

2 Spring声明式事务-XML配置

2.1 问题

使用XML配置代替注解,实现Spring声明式事务。

2.2 方案

XML配置声明式事务,关键代码如下:

  1.     <!-- XML配置声明事务范围及类型 -->
  2.     <tx:advice id="txAdvice" transaction-manager="txManager">
  3.         <tx:attributes>
  4.             <tx:method name="find*" read-only="true" />
  5.             <tx:method name="add*" propagation="REQUIRED"
  6.                 rollback-for="java.lang.Exception"/>
  7.             <tx:method name="update*" propagation="REQUIRED"
  8.                 rollback-for="java.lang.Exception"/>
  9.             <tx:method name="delete*" propagation="REQUIRED"
  10.                 rollback-for="java.lang.Exception"/>
  11.         </tx:attributes>
  12.     </tx:advice>
  13.     <aop:config proxy-target-class="true">
  14.         <aop:advisor advice-ref="txAdvice"
  15.             pointcut="within(com.tarena.controller..*)" />
  16.     </aop:config>

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:取消事务注解

在applicationContext.xml中,去掉开启事务注解扫描的代码,使事务注解失效,关键代码如下:

  1.     <!-- 开启事务注解扫描 -->
  2.     <!-- <tx:annotation-driven
  3.         transaction-manager="txManager" proxy-target-class="true"/> -->

步骤二:使用XML配置声明式事务

在applicationContext.xml中,使用XML配置声明式事务,关键代码如下:

  1.     <!-- XML配置声明事务范围及类型 -->
  2.     <tx:advice id="txAdvice" transaction-manager="txManager">
  3.         <tx:attributes>
  4.             <tx:method name="find*" read-only="true" />
  5.             <tx:method name="add*" propagation="REQUIRED" />
  6.             <tx:method name="update*" propagation="REQUIRED" />
  7.             <tx:method name="delete*" propagation="REQUIRED" />
  8.         </tx:attributes>
  9.     </tx:advice>
  10.     <aop:config proxy-target-class="true">
  11.         <aop:advisor advice-ref="txAdvice"
  12.             pointcut="within(com.tarena.controller..*)" />
  13.     </aop:config>

步骤三:测试

执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:

图-4

可见,XML配置的声明式事务与注解方式效果一样。

2.4 完整代码

本案例的完整代码如下所示:

applicationContext.xml完整代码如下:

3 Spring声明式事务-回滚机制

3.1 问题

默认情况下,声明式事务只能捕获RuntimeException,并使事务回滚,请处理非RuntimeException情况下的事务回滚。

3.2 方案

使用注解实现声明式事务时,按如下方式指定异常:

@Transactional(rollbackFor=ClassNotFoundException.class)

使用XML配置实现声明式事务时,按如下方式指定异常:

<tx:method name="update*" propagation="REQUIRED"

rollback-for="java.lang.ClassNotFoundException"/>

本案例中演示第二种方式。

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:测试非RuntimeException异常的情况

修改EmpController.addBatch()方法,将模拟的异常换成非RuntimeException,代码如下:

  1. package com.tarena.controller;
  2.  
  3. import javax.annotation.Resource;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.transaction.annotation.Transactional;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import com.tarena.dao.EmpDao;
  8. import com.tarena.entity.Emp;
  9.  
  10. @Controller
  11. @RequestMapping("/emp")
  12. @Transactional
  13. public class EmpController {
  14.     
  15.     @Resource
  16.     private EmpDao empDao;
  17.  
  18. //其他方法略
  19.  
  20.     /**
  21.      * 模拟批量添加员工
  22.      */
  23.     @RequestMapping("/addEmps.do")
  24.     public String addBatch() throws ClassNotFoundException {
  25.         // 插入第一个员工
  26.         Emp e1 = new Emp();
  27.         e1.setEname("刘备");
  28.         e1.setJob("皇叔");
  29.         e1.setSal(1000.0);
  30.         e1.setEmpno(10);
  31.         empDao.save(e1);
  32.         
  33.         // 模拟异常
  34. //        Integer.valueOf("abc"); //ClassCastException
  35.         Class.forName("BadClass"); //ClassNotFoundException
  36.         
  37.         // 插入第二个员工
  38.         Emp e2 = new Emp();
  39.         e2.setEname("关羽");
  40.         e2.setJob("候");
  41.         e2.setSal(1000.0);
  42.         e2.setEmpno(10);
  43.         empDao.save(e2);
  44.         
  45.         return "redirect:findEmp.do";
  46.     }
  47.  
  48. }

执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:

图-5

可见,对于非RuntimeException异常,默认的声明式事务是处理不了的。

步骤二:注解上指定处理的异常类型

修改applicationContext.xml,在通知配置上指定异常类型,关键代码如下:

  1.     <!-- XML配置声明事务范围及类型 -->
  2.     <tx:advice id="txAdvice" transaction-manager="txManager">
  3.         <tx:attributes>
  4.             <tx:method name="find*" read-only="true" />
  5.             <tx:method name="add*" propagation="REQUIRED"
  6.                 rollback-for="java.lang. ClassNotFoundException"/>
  7.             <tx:method name="update*" propagation="REQUIRED" />
  8.             <tx:method name="delete*" propagation="REQUIRED" />
  9.         </tx:attributes>
  10.     </tx:advice>
  11.     <aop:config proxy-target-class="true">
  12.         <aop:advisor advice-ref="txAdvice"
  13.             pointcut="within(com.tarena.controller..*)" />
  14.     </aop:config>

步骤三:测试

手动删除员工表中的刘备,执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:

图-6

可见,在注解上指定了要处理的异常类型后,它就可以处理非RuntimeException了。

3.4 完整代码

本案例的完整代码如下所示:

applicationContext.xml完整代码如下:

4 RESTful应用案例

4.1 问题

使用RESTful实现员工模块的增删改查功能。

4.2 方案

在Spring+MyBatis框架基础上实现员工模块的增删改查功能,然后再使用RESTful来重构请求URL。

4.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:实现员工模块增删改查功能

复制项目SpringUnit01,创建新项目SpringRestful,在新项目中完成员工的增删改查功能。

EmpDao代码如下:

  1. package com.tarena.dao;
  2.  
  3. import java.util.List;
  4. import com.tarena.annotation.MyBatisRepository;
  5. import com.tarena.entity.Emp;
  6.  
  7. /**
  8. * 员工表的DAO组件
  9. */
  10. @MyBatisRepository
  11. public interface EmpDao {
  12.  
  13.     List<Emp> findAll();
  14.     
  15.     void save(Emp emp);
  16.     
  17.     Emp findById(int id);
  18.     
  19.     void update(Emp emp);
  20.     
  21.     void delete(int id);
  22.  
  23. }

EmpMapper.xml代码如下:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
  3. "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
  4.  
  5. <mapper namespace="com.tarena.dao.EmpDao">
  6.  
  7.     <!-- 查询全部的员工 -->
  8.     <select id="findAll"
  9.         resultType="com.tarena.entity.Emp">
  10.         select * from t_emp
  11.     </select>
  12.     
  13.     <!-- 保存一条员工数据 -->
  14.     <insert id="save"
  15.         parameterType="com.tarena.entity.Emp">
  16.         insert into t_emp values(
  17.             emp_seq.nextval,
  18.             #{ename,jdbcType=VARCHAR},
  19.             #{job,jdbcType=VARCHAR},
  20.             #{mgr,jdbcType=NUMERIC},
  21.             #{hiredate,jdbcType=DATE},
  22.             #{sal,jdbcType=NUMERIC},
  23.             #{comm,jdbcType=NUMERIC},
  24.             #{deptno,jdbcType=NUMERIC}
  25.         )
  26.     </insert>    
  27.     
  28.     <!-- 根据ID查询员工 -->
  29.     <select id="findById"
  30.         parameterType="java.lang.Integer"
  31.         resultType="com.tarena.entity.Emp">
  32.         select * from t_emp where empno=#{id}
  33.     </select>    
  34.     
  35.     <!-- 修改员工 -->
  36.     <update id="update" parameterType="com.tarena.entity.Emp">
  37.         update t_emp set
  38.             ename=#{ename,jdbcType=VARCHAR},
  39.             job=#{job,jdbcType=VARCHAR},
  40.             sal=#{sal,jdbcType=NUMERIC}
  41.         where empno=#{empno,jdbcType=NUMERIC}
  42.     </update>
  43.     
  44.     <!-- 删除员工 -->
  45.     <delete id="delete" parameterType="java.lang.Integer">
  46.         delete from t_emp where empno=#{id}
  47.     </delete>    
  48.     
  49. </mapper>

EmpController代码如下:

  1. package com.tarena.controller;
  2.  
  3. import java.util.List;
  4. import javax.annotation.Resource;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.ui.Model;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestParam;
  9. import com.tarena.dao.EmpDao;
  10. import com.tarena.entity.Emp;
  11.  
  12. @Controller
  13. @RequestMapping("/emp")
  14. public class EmpController {
  15.  
  16.     @Resource
  17.     private EmpDao empDao;
  18.  
  19.     @RequestMapping("/findEmp.do")
  20.     public String find(Model model) {
  21.         List<Emp> list = empDao.findAll();
  22.         model.addAttribute("emps", list);
  23.         return "emp/emp_list";
  24.     }
  25.     
  26.     /**
  27.      * 打开新增页面
  28.      */
  29.     @RequestMapping("/toAddEmp.do")
  30.     public String toAdd() {
  31.         return "emp/add_emp";
  32.     }
  33.     
  34.     /**
  35.      * 新增保存
  36.      */
  37.     @RequestMapping("/addEmp.do")
  38.     public String add(Emp emp) {
  39.         empDao.save(emp);
  40.         return "redirect:findEmp.do";
  41.     }
  42.     
  43.     /**
  44.      * 打开修改页面
  45.      */
  46.     @RequestMapping("/toUpdateEmp.do")
  47.     public String toUpdate(
  48.             @RequestParam("id") int id,
  49.             Model model) {
  50.         Emp e = empDao.findById(id);
  51.         model.addAttribute("emp", e);
  52.         return "emp/update_emp";
  53.     }
  54.     
  55.     /**
  56.      * 修改保存
  57.      */
  58.     @RequestMapping("/updateEmp.do")
  59.     public String update(Emp emp) {
  60.         empDao.update(emp);
  61.         return "redirect:findEmp.do";
  62.     }
  63.     
  64.     /**
  65.      * 删除
  66.      */
  67.     @RequestMapping("/deleteEmp.do")
  68.     public String delete(@RequestParam("id") int id) {
  69.         empDao.delete(id);
  70.         return "redirect:findEmp.do";
  71.     }
  72.  
  73. }

员工列表页面emp_list.jsp代码如下:

  1. <%@page pageEncoding="utf-8"%>
  2. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  3. <html>
  4. <head>
  5.     <script type="text/javascript" src="../js/jquery-1.11.1.js"></script>
  6.     <script type="text/javascript">
  7.         function delete_emp(id) {
  8.             var r = window.confirm("确定要删除此数据吗?");
  9.             if(r) {
  10.                 location.href = "deleteEmp.do?id="+id;
  11.             }
  12.         }
  13.     </script>
  14. </head>
  15. <body>
  16.     <div align="center">
  17.         <input type="button" value="新增" onclick="location.href='toAddEmp.do'"/>
  18.     </div>
  19.     <table width="60%" border="1" cellpadding="2" cellspacing="0" align="center">
  20.         <tr>
  21.             <th>EMPNO</th>
  22.             <th>ENAME</th>
  23.             <th>JOB</th>
  24.             <th>MGR</th>
  25.             <th>HIREDATE</th>
  26.             <th>SAL</th>
  27.             <th>COMM</th>
  28.             <th>DEPTNO</th>
  29.             <th></th>
  30.         </tr>
  31.         <c:forEach items="${emps }" var="emp">
  32.             <tr>
  33.                 <td>${emp.empno }</td>
  34.                 <td>${emp.ename }</td>
  35.                 <td>${emp.job }</td>
  36.                 <td>${emp.mgr }</td>
  37.                 <td>${emp.hiredate }</td>
  38.                 <td>${emp.sal }</td>
  39.                 <td>${emp.comm }</td>
  40.                 <td>${emp.deptno }</td>
  41.                 <td>
  42.                     <input type="button" value="修改" onclick="location.href='toUpdateEmp.do?id=${emp.empno }'"/>
  43.                     <input type="button" value="删除" onclick="delete_emp(${emp.empno });"/>
  44.                 </td>
  45.             </tr>
  46.         </c:forEach>
  47.     </table>
  48. </body>
  49. </html>

员工新增页面add_emp.jsp代码如下:

  1. <%@page pageEncoding="utf-8"%>
  2. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  3. <html>
  4. <head>
  5. </head>
  6. <body>
  7.     <form action="addEmp.do" method="post">
  8.         <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center">
  9.             <tr>
  10.                 <td>姓名:</td>
  11.                 <td><input type="text" name="ename"/></td>
  12.             </tr>
  13.             <tr>
  14.                 <td>岗位:</td>
  15.                 <td><input type="text" name="job"/></td>
  16.             </tr>
  17.             <tr>
  18.                 <td>工资:</td>
  19.                 <td><input type="text" name="sal"/></td>
  20.             </tr>
  21.             <tr>
  22.                 <td colspan="2"><input type="submit" value="保存"/></td>
  23.             </tr>
  24.         </table>
  25.     </form>
  26. </body>
  27. </html>

员工修改页面update_emp.jsp代码如下:

  1. <%@page pageEncoding="utf-8"%>
  2. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  3. <html>
  4. <head>
  5. </head>
  6. <body>
  7.     <form action="updateEmp.do" method="post">
  8.         <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center">
  9.             <tr>
  10.                 <td>EMPNO:</td>
  11.                 <td><input type="text" name="empno" value="${emp.empno }"/></td>
  12.             </tr>
  13.             <tr>
  14.                 <td>姓名:</td>
  15.                 <td><input type="text" name="ename" value="${emp.ename }"/></td>
  16.             </tr>
  17.             <tr>
  18.                 <td>岗位:</td>
  19.                 <td><input type="text" name="job" value="${emp.job }"/></td>
  20.             </tr>
  21.             <tr>
  22.                 <td>工资:</td>
  23.                 <td><input type="text" name="sal" value="${emp.sal }"/></td>
  24.             </tr>
  25.             <tr>
  26.                 <td colspan="2"><input type="submit" value="保存"/></td>
  27.             </tr>
  28.         </table>
  29.     </form>    
  30. </body>
  31. </html>

部署项目并启动tomcat,测试通过员工的增删改查功能。

步骤二:启用RESTful

修改web.xml,将*.do改为/,代码如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.5"
  3.     xmlns="http://java.sun.com/xml/ns/javaee"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  6.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  7. <display-name></display-name>    
  8. <welcome-file-list>
  9. <welcome-file>index.jsp</welcome-file>
  10. </welcome-file-list>
  11.     
  12. <!-- Spring前端控制器 -->
  13.     <servlet>
  14.         <servlet-name>SpringMVC</servlet-name>
  15.         <servlet-class>
  16.             org.springframework.web.servlet.DispatcherServlet
  17.         </servlet-class>
  18.         <init-param>
  19.             <param-name>
  20.                 contextConfigLocation
  21.             </param-name>
  22.             <param-value>
  23.                 classpath:applicationContext.xml
  24.             </param-value>
  25.         </init-param>
  26.     </servlet>
  27.     <servlet-mapping>
  28.         <servlet-name>SpringMVC</servlet-name>
  29.         <url-pattern>/</url-pattern>
  30.     </servlet-mapping>
  31.     <!-- 使用Filter解决中文乱码问题 -->
  32.     <filter>
  33.      <filter-name>encodingFilter</filter-name>
  34.      <filter-class>
  35.          org.springframework.web.filter.CharacterEncodingFilter
  36.      </filter-class>
  37.      <init-param>
  38.      <param-name>encoding</param-name>
  39.      <param-value>UTF-8</param-value>
  40.      </init-param>
  41.     </filter>
  42.     <filter-mapping>
  43.      <filter-name>encodingFilter</filter-name>
  44.      <url-pattern>/*</url-pattern>
  45.     </filter-mapping>
  46. </web-app>

修改applicationContext.xml,增加支持RESTful访问静态资源的配置,关键代码如下:

  1.     <!-- 支持RESTful访问静态资源 -->
  2.     <mvc:default-servlet-handler />

导入Spring中使用Ajax所需的3个开发包,如下图:

图-7

步骤三:使用RESTful重构Controller

修改EmpController,使用RESTful设计访问URI,代码如下:

  1. package com.tarena.controller;
  2.  
  3. import java.util.List;
  4. import javax.annotation.Resource;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.ui.Model;
  7. import org.springframework.web.bind.annotation.PathVariable;
  8. import org.springframework.web.bind.annotation.RequestBody;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import org.springframework.web.bind.annotation.ResponseBody;
  12. import com.tarena.dao.EmpDao;
  13. import com.tarena.entity.Emp;
  14.  
  15. @Controller
  16. @RequestMapping("/emp")
  17. public class EmpController {
  18.  
  19.     @Resource
  20.     private EmpDao empDao;
  21.  
  22.     @RequestMapping(value="/find",method=RequestMethod.GET)
  23.     public String find(Model model) {
  24.         List<Emp> list = empDao.findAll();
  25.         model.addAttribute("emps", list);
  26.         return "emp/emp_list";
  27.     }
  28.     
  29.     /**
  30.      * 打开新增页面
  31.      */
  32.     @RequestMapping(value="/toAdd",method=RequestMethod.GET)
  33.     public String toAdd() {
  34.         return "emp/add_emp";
  35.     }
  36.     
  37.     /**
  38.      * 新增保存
  39.      */
  40.     @RequestMapping(value="/add",method=RequestMethod.POST)
  41.     public String add(Emp emp) {
  42.         empDao.save(emp);
  43.         return "redirect:find";
  44.     }    
  45.  
  46.     /**
  47.      * 打开修改页面
  48.      */
  49.     @RequestMapping(value="/toUpdate/{id}",method=RequestMethod.GET)
  50.     public String toUpdate(
  51.             @PathVariable("id") int id,
  52.             Model model) {
  53.         Emp e = empDao.findById(id);
  54.         model.addAttribute("emp", e);
  55.         return "emp/update_emp";
  56.     }
  57.     
  58.     /**
  59.      * 修改保存
  60.      */
  61.     @RequestMapping(value="/update",method=RequestMethod.PUT)
  62.     @ResponseBody
  63.     public boolean update(@RequestBody Emp emp) {
  64.         empDao.update(emp);
  65.         return true;
  66.     }
  67.     
  68.     /**
  69.      * 删除
  70.      */
  71.     @RequestMapping(value="/{id}",method=RequestMethod.DELETE)
  72.     @ResponseBody
  73.     public boolean delete(@PathVariable("id") int id) {
  74.         empDao.delete(id);
  75.         return true;
  76.     }
  77.  
  78. }

步骤四:修改页面发请求的方式

在WebRoot/js文件夹下创建json.js,用于将表单数据转换成json对象,代码如下:

  1. // 将表单数据转换成json对象
  2. $.fn.serializeObject = function() {
  3. var o = {};
  4. var a = this.serializeArray();
  5. $.each(a, function() {
  6. if (o[this.name]) {
  7. if (!o[this.name].push) {
  8. o[this.name] = [o[this.name]];
  9. }
  10. o[this.name].push(this.value || '');
  11. } else {
  12. o[this.name] = this.value || '';
  13. }
  14. });
  15. return o;
  16. };

在emp_list.jsp中,对新增、修改按钮的URL进行修改,并将删除按钮改为RESTful的删除提交方式,代码如下:

  1. <%@page pageEncoding="utf-8"%>
  2. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  3. <html>
  4. <head>
  5.     <script type="text/javascript" src="../js/jquery-1.11.1.js"></script>
  6.     <script type="text/javascript">
  7.         function delete_emp(id) {
  8.             var r = window.confirm("确定要删除此数据吗?");
  9.             if(r) {
  10.                 //location.href = "deleteEmp.do?id="+id;
  11.                 $.ajax({
  12.         type:"DELETE",
  13.         url:"/SpringRestful/emp/"+id,
  14.         dataType:"json",
  15.         success:function(data){
  16.             location.href = "/SpringRestful/emp/find";
  17.         }
  18.      });                 
  19.             }
  20.         }
  21.     </script>
  22. </head>
  23. <body>
  24.     <div align="center">
  25.         <input type="button" value="新增" onclick="location.href='toAdd'"/>
  26.     </div>
  27.     <table width="60%" border="1" cellpadding="2" cellspacing="0" align="center">
  28.         <tr>
  29.             <th>EMPNO</th>
  30.             <th>ENAME</th>
  31.             <th>JOB</th>
  32.             <th>MGR</th>
  33.             <th>HIREDATE</th>
  34.             <th>SAL</th>
  35.             <th>COMM</th>
  36.             <th>DEPTNO</th>
  37.             <th></th>
  38.         </tr>
  39.         <c:forEach items="${emps }" var="emp">
  40.             <tr>
  41.                 <td>${emp.empno }</td>
  42.                 <td>${emp.ename }</td>
  43.                 <td>${emp.job }</td>
  44.                 <td>${emp.mgr }</td>
  45.                 <td>${emp.hiredate }</td>
  46.                 <td>${emp.sal }</td>
  47.                 <td>${emp.comm }</td>
  48.                 <td>${emp.deptno }</td>
  49.                 <td>
  50.                     <input type="button" value="修改" onclick="location.href='toUpdate/${emp.empno }'"/>
  51.                     <input type="button" value="删除" onclick="delete_emp(${emp.empno });"/>
  52.                 </td>
  53.             </tr>
  54.         </c:forEach>
  55.     </table>
  56. </body>
  57. </html>

修改add_emp.jsp表单的提交路径,代码如下:

  1. <%@page pageEncoding="utf-8"%>
  2. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  3. <html>
  4. <head>
  5. </head>
  6. <body>
  7.     <form action="add" method="post">
  8.         <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center">
  9.             <tr>
  10.                 <td>姓名:</td>
  11.                 <td><input type="text" name="ename"/></td>
  12.             </tr>
  13.             <tr>
  14.                 <td>岗位:</td>
  15.                 <td><input type="text" name="job"/></td>
  16.             </tr>
  17.             <tr>
  18.                 <td>工资:</td>
  19.                 <td><input type="text" name="sal"/></td>
  20.             </tr>
  21.             <tr>
  22.                 <td colspan="2"><input type="submit" value="保存" /></td>
  23.             </tr>
  24.         </table>
  25.     </form>
  26. </body>
  27. </html>

修改update_emp.jsp中表单提交的方式和路径,代码如下:

  1. <%@page pageEncoding="utf-8"%>
  2. <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
  3. <html>
  4. <head>
  5.     <script type="text/javascript" src="../../js/jquery-1.11.1.js"></script>
  6.     <script type="text/javascript" src="../../js/json.js"></script>
  7.     <script type="text/javascript">
  8.         function save() {
  9.     $.ajax({
  10.         type:"PUT",
  11.         url:"/SpringRestful/emp/update",
  12.         data:JSON.stringify($("#myform").serializeObject()),
  13.         dataType:"json",
  14.         contentType:"application/json",
  15.         success:function(data){
  16.             location.href = "/SpringRestful/emp/find";
  17.         }
  18.     });
  19. }         
  20.     </script>
  21. </head>
  22. <body>
  23.     <form action="updateEmp.do" method="post" id="myform">
  24.         <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center">
  25.             <tr>
  26.                 <td>EMPNO:</td>
  27.                 <td><input type="text" name="empno" value="${emp.empno }"/></td>
  28.             </tr>
  29.             <tr>
  30.                 <td>姓名:</td>
  31.                 <td><input type="text" name="ename" value="${emp.ename }"/></td>
  32.             </tr>
  33.             <tr>
  34.                 <td>岗位:</td>
  35.                 <td><input type="text" name="job" value="${emp.job }"/></td>
  36.             </tr>
  37.             <tr>
  38.                 <td>工资:</td>
  39.                 <td><input type="text" name="sal" value="${emp.sal }"/></td>
  40.             </tr>
  41.             <tr>
  42.                 <td colspan="2"><input type="button" value="保存" onclick="save();"/></td>
  43.             </tr>
  44.         </table>
  45.     </form>    
  46. </body>
  47. </html>

步骤五:测试

重新部署并启动tomcat,测试通过员工的增删改查功能。

4.4 完整代码

本案例的完整代码如下所示:

EmpDao完整代码如下:

EmpMapper.xml完整代码如下:

web.xml完整代码如下:

applicationContext.xml完整代码如下:

EmpController完整代码如下:

json.js完整代码如下:

emp_list.jsp完整代码如下:

add_emp.jsp完整代码如下:

update_emp.jsp完整代码如下: