使用Spring注解实现声明式事务,管理Controller中各业务方法的事务。
Spring事务注解使用步骤:
实现此案例需要按照如下步骤进行。
步骤一:测试未管理事务的情况
复制项目SpringUnit05,创建新项目SpringUnit06。
在EmpController中,增加批量添加员工的方法,并模拟实现,代码如下:
package com.tarena.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import com.tarena.dao.EmpDao; import com.tarena.entity.Emp; @Controller @RequestMapping("/emp") public class EmpController { #cold_bold @Resource #cold_bold private EmpDao empDao; //其他方法略 #cold_bold /** #cold_bold * 模拟批量添加员工 #cold_bold */ #cold_bold @RequestMapping("/addEmps.do") #cold_bold public String addBatch() { #cold_bold // 插入第一个员工 #cold_bold Emp e1 = new Emp(); #cold_bold e1.setEname("刘备"); #cold_bold e1.setJob("皇叔"); #cold_bold e1.setSal(1000.0); #cold_bold e1.setEmpno(10); #cold_bold empDao.save(e1); #cold_bold #cold_bold // 模拟异常 #cold_bold Integer.valueOf("abc"); //ClassCastException #cold_bold #cold_bold // 插入第二个员工 #cold_bold Emp e2 = new Emp(); #cold_bold e2.setEname("关羽"); #cold_bold e2.setJob("候"); #cold_bold e2.setSal(1000.0); #cold_bold e2.setEmpno(10); #cold_bold empDao.save(e2); #cold_bold #cold_bold return "redirect:findEmp.do"; #cold_bold } }
在TestEmpController中,增加测试方法,测试批量添加员工,代码如下:
package com.tarena.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tarena.controller.EmpController; public class TestEmpController { //其他方法略 #cold_bold /** #cold_bold * 测试批量添加员工 #cold_bold */ #cold_bold @Test #cold_bold public void test2() throws ClassNotFoundException { #cold_bold ApplicationContext ctx = new ClassPathXmlApplicationContext( #cold_bold "applicationContext.xml"); #cold_bold EmpController ctl = ctx.getBean(EmpController.class); #cold_bold ctl.addBatch(); #cold_bold } }
没有执行该测试方法前,员工表中的数据如下图:
图-1
执行该测试方法后,员工表中的数据如下图:
图-2
可见,员工刘备添加成功。但EmpController.addBatch()方法是业务方法,体现了完整的业务逻辑,发生异常时应该整个业务失败,而不是一部分成功一部分失败,因此添加刘备成功是不符合要求的,应该引入事务管理机制来解决此问题。
步骤二:声明事务组件
在applicationContext.xml中声明事务组件,关键代码如下:
#cold_bold <!-- 声明事务管理组件 --> #cold_bold <bean id="txManager" #cold_bold class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> #cold_bold <property name="dataSource" ref="ds"/> #cold_bold </bean>
步骤三:开启事务注解扫描
在applicationContext.xml中,开启事务注解扫描,关键代码如下:
<!-- 声明事务管理组件 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"/> </bean> #cold_bold <!-- 开启事务注解扫描 --> #cold_bold <tx:annotation-driven #cold_bold transaction-manager="txManager" proxy-target-class="true"/>
步骤四:使用注解标识类/方法
在EmpController中,使用注解对该方法启用事务管理,代码如下:
package com.tarena.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import com.tarena.dao.EmpDao; import com.tarena.entity.Emp; @Controller @RequestMapping("/emp") #cold_bold@Transactional public class EmpController { @Resource private EmpDao empDao; //其他方法略 /** * 模拟批量添加员工 */ @RequestMapping("/addEmps.do") public String addBatch() { // 插入第一个员工 Emp e1 = new Emp(); e1.setEname("刘备"); e1.setJob("皇叔"); e1.setSal(1000.0); e1.setEmpno(10); empDao.save(e1); // 模拟异常 Integer.valueOf("abc"); //ClassCastException // 插入第二个员工 Emp e2 = new Emp(); e2.setEname("关羽"); e2.setJob("候"); e2.setSal(1000.0); e2.setEmpno(10); empDao.save(e2); return "redirect:findEmp.do"; } }
步骤五:测试
手动删除员工表中的刘备,执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:
图-3
可见,在引入了事务管理机制后,业务方法发生异常时,由于事务回滚,所以没有成功插入员工刘备,从而保证了业务的完整性。
本案例的完整代码如下所示:
EmpController完整代码如下:
package com.tarena.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import com.tarena.dao.EmpDao; import com.tarena.entity.Emp; @Controller @RequestMapping("/emp") @Transactional public class EmpController { @Resource private EmpDao empDao; /** * 查询员工 */ @RequestMapping("/findEmp.do") @Transactional(readOnly=true) public String find() { // 模拟查询员工数据 System.out.println("查询员工数据,发送至列表页面."); // 制造一个异常,便于测试异常通知 Integer.valueOf("abc"); return "emp/emp_list.jsp"; } /** * 模拟批量添加员工 */ @RequestMapping("/addEmps.do") public String addBatch() { // 插入第一个员工 Emp e1 = new Emp(); e1.setEname("刘备"); e1.setJob("皇叔"); e1.setSal(1000.0); e1.setEmpno(10); empDao.save(e1); // 模拟异常 Integer.valueOf("abc"); //ClassCastException // 插入第二个员工 Emp e2 = new Emp(); e2.setEname("关羽"); e2.setJob("候"); e2.setSal(1000.0); e2.setEmpno(10); empDao.save(e2); return "redirect:findEmp.do"; } }
TestEmpController完整代码如下:
package com.tarena.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tarena.controller.EmpController; public class TestEmpController { /** * 测试查询员工 */ @Test public void test1() { ApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml"); EmpController ctl = ctx.getBean(EmpController.class); ctl.find(); } /** * 测试批量添加员工 */ @Test public void test2() throws ClassNotFoundException { ApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml"); EmpController ctl = ctx.getBean(EmpController.class); ctl.addBatch(); } }
applicationContext.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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <!-- 配置数据源 --> <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/> <property name="driverClassName" value="oracle.jdbc.OracleDriver"/> <property name="username" value="lhh"/> <property name="password" value="123456"/> </bean> <!-- 配置SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="ds" /> <property name="mapperLocations" value="classpath:com/tarena/entity/*.xml"/> </bean> <!-- 配置MyBatis注解 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.tarena.dao" /> <property name="annotationClass" value="com.tarena.annotation.MyBatisRepository"/> </bean> <!-- 开启注解扫描 --> <context:component-scan base-package="com.tarena" /> <!-- 支持@RequestMapping请求和Controller映射 --> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 声明方面组件 --> <!-- <bean id="operateLogger" class="com.tarena.aspect.OperateLogger"/> --> <!-- 配置AOP --> <!-- <aop:config> <aop:aspect ref="operateLogger"> <aop:before method="log1" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> <aop:aspect ref="operateLogger"> <aop:around method="log2" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> <aop:aspect ref="operateLogger"> <aop:after-throwing method="log3" throwing="e" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> </aop:config> --> <!-- 开启AOP注解扫描 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 声明事务管理组件 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"/> </bean> <!-- 开启事务注解扫描 --> <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> </beans>
使用XML配置代替注解,实现Spring声明式事务。
XML配置声明式事务,关键代码如下:
<!-- XML配置声明事务范围及类型 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" read-only="true" /> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:advisor advice-ref="txAdvice" pointcut="within(com.tarena.controller..*)" /> </aop:config>
实现此案例需要按照如下步骤进行。
步骤一:取消事务注解
在applicationContext.xml中,去掉开启事务注解扫描的代码,使事务注解失效,关键代码如下:
#cold_bold <!-- 开启事务注解扫描 --> #cold_bold <!-- <tx:annotation-driven #cold_bold transaction-manager="txManager" proxy-target-class="true"/> -->
步骤二:使用XML配置声明式事务
在applicationContext.xml中,使用XML配置声明式事务,关键代码如下:
#cold_bold <!-- XML配置声明事务范围及类型 --> #cold_bold <tx:advice id="txAdvice" transaction-manager="txManager"> #cold_bold <tx:attributes> #cold_bold <tx:method name="find*" read-only="true" /> #cold_bold <tx:method name="add*" propagation="REQUIRED" /> #cold_bold <tx:method name="update*" propagation="REQUIRED" /> #cold_bold <tx:method name="delete*" propagation="REQUIRED" /> #cold_bold </tx:attributes> #cold_bold </tx:advice> #cold_bold <aop:config proxy-target-class="true"> #cold_bold <aop:advisor advice-ref="txAdvice" #cold_bold pointcut="within(com.tarena.controller..*)" /> #cold_bold </aop:config>
步骤三:测试
执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:
图-4
可见,XML配置的声明式事务与注解方式效果一样。
本案例的完整代码如下所示:
applicationContext.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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <!-- 配置数据源 --> <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/> <property name="driverClassName" value="oracle.jdbc.OracleDriver"/> <property name="username" value="lhh"/> <property name="password" value="123456"/> </bean> <!-- 配置SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="ds" /> <property name="mapperLocations" value="classpath:com/tarena/entity/*.xml"/> </bean> <!-- 配置MyBatis注解 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.tarena.dao" /> <property name="annotationClass" value="com.tarena.annotation.MyBatisRepository"/> </bean> <!-- 开启注解扫描 --> <context:component-scan base-package="com.tarena" /> <!-- 支持@RequestMapping请求和Controller映射 --> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 声明方面组件 --> <!-- <bean id="operateLogger" class="com.tarena.aspect.OperateLogger"/> --> <!-- 配置AOP --> <!-- <aop:config> <aop:aspect ref="operateLogger"> <aop:before method="log1" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> <aop:aspect ref="operateLogger"> <aop:around method="log2" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> <aop:aspect ref="operateLogger"> <aop:after-throwing method="log3" throwing="e" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> </aop:config> --> <!-- 开启AOP注解扫描 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 声明事务管理组件 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"/> </bean> <!-- 开启事务注解扫描 --> <!-- <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> --> <!-- XML配置声明事务范围及类型 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" read-only="true" /> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:advisor advice-ref="txAdvice" pointcut="within(com.tarena.controller..*)" /> </aop:config> </beans>
默认情况下,声明式事务只能捕获RuntimeException,并使事务回滚,请处理非RuntimeException情况下的事务回滚。
使用注解实现声明式事务时,按如下方式指定异常:
@Transactional(rollbackFor=ClassNotFoundException.class)
使用XML配置实现声明式事务时,按如下方式指定异常:
<tx:method name="update*" propagation="REQUIRED"
rollback-for="java.lang.ClassNotFoundException"/>
本案例中演示第二种方式。
实现此案例需要按照如下步骤进行。
步骤一:测试非RuntimeException异常的情况
修改EmpController.addBatch()方法,将模拟的异常换成非RuntimeException,代码如下:
package com.tarena.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import com.tarena.dao.EmpDao; import com.tarena.entity.Emp; @Controller @RequestMapping("/emp") @Transactional public class EmpController { @Resource private EmpDao empDao; //其他方法略 /** * 模拟批量添加员工 */ @RequestMapping("/addEmps.do") public String addBatch() throws ClassNotFoundException { // 插入第一个员工 Emp e1 = new Emp(); e1.setEname("刘备"); e1.setJob("皇叔"); e1.setSal(1000.0); e1.setEmpno(10); empDao.save(e1); // 模拟异常 #cold_bold// Integer.valueOf("abc"); //ClassCastException #cold_bold Class.forName("BadClass"); //ClassNotFoundException // 插入第二个员工 Emp e2 = new Emp(); e2.setEname("关羽"); e2.setJob("候"); e2.setSal(1000.0); e2.setEmpno(10); empDao.save(e2); return "redirect:findEmp.do"; } }
执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:
图-5
可见,对于非RuntimeException异常,默认的声明式事务是处理不了的。
步骤二:注解上指定处理的异常类型
修改applicationContext.xml,在通知配置上指定异常类型,关键代码如下:
<!-- XML配置声明事务范围及类型 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" read-only="true" /> #cold_bold <tx:method name="add*" propagation="REQUIRED" #cold_bold rollback-for="java.lang. ClassNotFoundException"/> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:advisor advice-ref="txAdvice" pointcut="within(com.tarena.controller..*)" /> </aop:config>
步骤三:测试
手动删除员工表中的刘备,执行测试方法TestEmpController.test2(),然后查询员工表数据如下图:
图-6
可见,在注解上指定了要处理的异常类型后,它就可以处理非RuntimeException了。
本案例的完整代码如下所示:
applicationContext.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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <!-- 配置数据源 --> <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/> <property name="driverClassName" value="oracle.jdbc.OracleDriver"/> <property name="username" value="lhh"/> <property name="password" value="123456"/> </bean> <!-- 配置SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="ds" /> <property name="mapperLocations" value="classpath:com/tarena/entity/*.xml"/> </bean> <!-- 配置MyBatis注解 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.tarena.dao" /> <property name="annotationClass" value="com.tarena.annotation.MyBatisRepository"/> </bean> <!-- 开启注解扫描 --> <context:component-scan base-package="com.tarena" /> <!-- 支持@RequestMapping请求和Controller映射 --> <mvc:annotation-driven /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 声明方面组件 --> <!-- <bean id="operateLogger" class="com.tarena.aspect.OperateLogger"/> --> <!-- 配置AOP --> <!-- <aop:config> <aop:aspect ref="operateLogger"> <aop:before method="log1" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> <aop:aspect ref="operateLogger"> <aop:around method="log2" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> <aop:aspect ref="operateLogger"> <aop:after-throwing method="log3" throwing="e" pointcut="within(com.tarena.controller..*)"/> </aop:aspect> </aop:config> --> <!-- 开启AOP注解扫描 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 声明事务管理组件 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="ds"/> </bean> <!-- 开启事务注解扫描 --> <!-- <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> --> <!-- XML配置声明事务范围及类型 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" read-only="true" /> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.ClassNotFoundException"/> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:advisor advice-ref="txAdvice" pointcut="within(com.tarena.controller..*)" /> </aop:config> </beans>
使用RESTful实现员工模块的增删改查功能。
在Spring+MyBatis框架基础上实现员工模块的增删改查功能,然后再使用RESTful来重构请求URL。
实现此案例需要按照如下步骤进行。
步骤一:实现员工模块增删改查功能
复制项目SpringUnit01,创建新项目SpringRestful,在新项目中完成员工的增删改查功能。
EmpDao代码如下:
package com.tarena.dao; import java.util.List; import com.tarena.annotation.MyBatisRepository; import com.tarena.entity.Emp; /** * 员工表的DAO组件 */ @MyBatisRepository public interface EmpDao { List<Emp> findAll(); void save(Emp emp); Emp findById(int id); void update(Emp emp); void delete(int id); }
EmpMapper.xml代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="com.tarena.dao.EmpDao"> <!-- 查询全部的员工 --> <select id="findAll" resultType="com.tarena.entity.Emp"> select * from t_emp </select> <!-- 保存一条员工数据 --> <insert id="save" parameterType="com.tarena.entity.Emp"> insert into t_emp values( emp_seq.nextval, #{ename,jdbcType=VARCHAR}, #{job,jdbcType=VARCHAR}, #{mgr,jdbcType=NUMERIC}, #{hiredate,jdbcType=DATE}, #{sal,jdbcType=NUMERIC}, #{comm,jdbcType=NUMERIC}, #{deptno,jdbcType=NUMERIC} ) </insert> <!-- 根据ID查询员工 --> <select id="findById" parameterType="java.lang.Integer" resultType="com.tarena.entity.Emp"> select * from t_emp where empno=#{id} </select> <!-- 修改员工 --> <update id="update" parameterType="com.tarena.entity.Emp"> update t_emp set ename=#{ename,jdbcType=VARCHAR}, job=#{job,jdbcType=VARCHAR}, sal=#{sal,jdbcType=NUMERIC} where empno=#{empno,jdbcType=NUMERIC} </update> <!-- 删除员工 --> <delete id="delete" parameterType="java.lang.Integer"> delete from t_emp where empno=#{id} </delete> </mapper>
EmpController代码如下:
package com.tarena.controller; import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import com.tarena.dao.EmpDao; import com.tarena.entity.Emp; @Controller @RequestMapping("/emp") public class EmpController { @Resource private EmpDao empDao; @RequestMapping("/findEmp.do") public String find(Model model) { List<Emp> list = empDao.findAll(); model.addAttribute("emps", list); return "emp/emp_list"; } /** * 打开新增页面 */ @RequestMapping("/toAddEmp.do") public String toAdd() { return "emp/add_emp"; } /** * 新增保存 */ @RequestMapping("/addEmp.do") public String add(Emp emp) { empDao.save(emp); return "redirect:findEmp.do"; } /** * 打开修改页面 */ @RequestMapping("/toUpdateEmp.do") public String toUpdate( @RequestParam("id") int id, Model model) { Emp e = empDao.findById(id); model.addAttribute("emp", e); return "emp/update_emp"; } /** * 修改保存 */ @RequestMapping("/updateEmp.do") public String update(Emp emp) { empDao.update(emp); return "redirect:findEmp.do"; } /** * 删除 */ @RequestMapping("/deleteEmp.do") public String delete(@RequestParam("id") int id) { empDao.delete(id); return "redirect:findEmp.do"; } }
员工列表页面emp_list.jsp代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <script type="text/javascript" src="../js/jquery-1.11.1.js"></script> <script type="text/javascript"> function delete_emp(id) { var r = window.confirm("确定要删除此数据吗?"); if(r) { location.href = "deleteEmp.do?id="+id; } } </script> </head> <body> <div align="center"> <input type="button" value="新增" onclick="location.href='toAddEmp.do'"/> </div> <table width="60%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <th>EMPNO</th> <th>ENAME</th> <th>JOB</th> <th>MGR</th> <th>HIREDATE</th> <th>SAL</th> <th>COMM</th> <th>DEPTNO</th> <th></th> </tr> <c:forEach items="${emps }" var="emp"> <tr> <td>${emp.empno }</td> <td>${emp.ename }</td> <td>${emp.job }</td> <td>${emp.mgr }</td> <td>${emp.hiredate }</td> <td>${emp.sal }</td> <td>${emp.comm }</td> <td>${emp.deptno }</td> <td> <input type="button" value="修改" onclick="location.href='toUpdateEmp.do?id=${emp.empno }'"/> <input type="button" value="删除" onclick="delete_emp(${emp.empno });"/> </td> </tr> </c:forEach> </table> </body> </html>
员工新增页面add_emp.jsp代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> </head> <body> <form action="addEmp.do" method="post"> <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <td>姓名:</td> <td><input type="text" name="ename"/></td> </tr> <tr> <td>岗位:</td> <td><input type="text" name="job"/></td> </tr> <tr> <td>工资:</td> <td><input type="text" name="sal"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="保存"/></td> </tr> </table> </form> </body> </html>
员工修改页面update_emp.jsp代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> </head> <body> <form action="updateEmp.do" method="post"> <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <td>EMPNO:</td> <td><input type="text" name="empno" value="${emp.empno }"/></td> </tr> <tr> <td>姓名:</td> <td><input type="text" name="ename" value="${emp.ename }"/></td> </tr> <tr> <td>岗位:</td> <td><input type="text" name="job" value="${emp.job }"/></td> </tr> <tr> <td>工资:</td> <td><input type="text" name="sal" value="${emp.sal }"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="保存"/></td> </tr> </table> </form> </body> </html>
部署项目并启动tomcat,测试通过员工的增删改查功能。
步骤二:启用RESTful
修改web.xml,将*.do改为/,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- Spring前端控制器 --> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name> contextConfigLocation </param-name> <param-value> classpath:applicationContext.xml </param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> #cold_bold <url-pattern>/</url-pattern> </servlet-mapping> <!-- 使用Filter解决中文乱码问题 --> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> #cold_bold <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
修改applicationContext.xml,增加支持RESTful访问静态资源的配置,关键代码如下:
#cold_bold <!-- 支持RESTful访问静态资源 --> #cold_bold <mvc:default-servlet-handler />
导入Spring中使用Ajax所需的3个开发包,如下图:
图-7
步骤三:使用RESTful重构Controller
修改EmpController,使用RESTful设计访问URI,代码如下:
package com.tarena.controller; import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.tarena.dao.EmpDao; import com.tarena.entity.Emp; @Controller @RequestMapping("/emp") public class EmpController { @Resource private EmpDao empDao; #cold_bold @RequestMapping(value="/find",method=RequestMethod.GET) public String find(Model model) { List<Emp> list = empDao.findAll(); model.addAttribute("emps", list); return "emp/emp_list"; } /** * 打开新增页面 */ #cold_bold @RequestMapping(value="/toAdd",method=RequestMethod.GET) public String toAdd() { return "emp/add_emp"; } /** * 新增保存 */ #cold_bold @RequestMapping(value="/add",method=RequestMethod.POST) public String add(Emp emp) { empDao.save(emp); #cold_bold return "redirect:find"; } /** * 打开修改页面 */ #cold_bold @RequestMapping(value="/toUpdate/{id}",method=RequestMethod.GET) public String toUpdate( #cold_bold @PathVariable("id") int id, Model model) { Emp e = empDao.findById(id); model.addAttribute("emp", e); return "emp/update_emp"; } /** * 修改保存 */ #cold_bold @RequestMapping(value="/update",method=RequestMethod.PUT) #cold_bold @ResponseBody #cold_bold public boolean update(@RequestBody Emp emp) { #cold_bold empDao.update(emp); #cold_bold return true; #cold_bold } /** * 删除 */ #cold_bold @RequestMapping(value="/{id}",method=RequestMethod.DELETE) #cold_bold @ResponseBody #cold_bold public boolean delete(@PathVariable("id") int id) { #cold_bold empDao.delete(id); #cold_bold return true; #cold_bold } }
步骤四:修改页面发请求的方式
在WebRoot/js文件夹下创建json.js,用于将表单数据转换成json对象,代码如下:
// 将表单数据转换成json对象 $.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); $.each(a, function() { if (o[this.name]) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); return o; };
在emp_list.jsp中,对新增、修改按钮的URL进行修改,并将删除按钮改为RESTful的删除提交方式,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <script type="text/javascript" src="../js/jquery-1.11.1.js"></script> <script type="text/javascript"> function delete_emp(id) { var r = window.confirm("确定要删除此数据吗?"); if(r) { #cold_bold //location.href = "deleteEmp.do?id="+id; #cold_bold $.ajax({ #cold_bold type:"DELETE", #cold_bold url:"/SpringRestful/emp/"+id, #cold_bold dataType:"json", #cold_bold success:function(data){ #cold_bold location.href = "/SpringRestful/emp/find"; #cold_bold } #cold_bold }); } } </script> </head> <body> <div align="center"> #cold_bold <input type="button" value="新增" onclick="location.href='toAdd'"/> </div> <table width="60%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <th>EMPNO</th> <th>ENAME</th> <th>JOB</th> <th>MGR</th> <th>HIREDATE</th> <th>SAL</th> <th>COMM</th> <th>DEPTNO</th> <th></th> </tr> <c:forEach items="${emps }" var="emp"> <tr> <td>${emp.empno }</td> <td>${emp.ename }</td> <td>${emp.job }</td> <td>${emp.mgr }</td> <td>${emp.hiredate }</td> <td>${emp.sal }</td> <td>${emp.comm }</td> <td>${emp.deptno }</td> <td> #cold_bold <input type="button" value="修改" onclick="location.href='toUpdate/${emp.empno }'"/> #cold_bold <input type="button" value="删除" onclick="delete_emp(${emp.empno });"/> </td> </tr> </c:forEach> </table> </body> </html>
修改add_emp.jsp表单的提交路径,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> </head> <body> #cold_bold <form action="add" method="post"> <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <td>姓名:</td> <td><input type="text" name="ename"/></td> </tr> <tr> <td>岗位:</td> <td><input type="text" name="job"/></td> </tr> <tr> <td>工资:</td> <td><input type="text" name="sal"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="保存" /></td> </tr> </table> </form> </body> </html>
修改update_emp.jsp中表单提交的方式和路径,代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> #cold_bold <script type="text/javascript" src="../../js/jquery-1.11.1.js"></script> #cold_bold <script type="text/javascript" src="../../js/json.js"></script> #cold_bold <script type="text/javascript"> #cold_bold function save() { #cold_bold $.ajax({ #cold_bold type:"PUT", #cold_bold url:"/SpringRestful/emp/update", #cold_bold data:JSON.stringify($("#myform").serializeObject()), #cold_bold dataType:"json", #cold_bold contentType:"application/json", #cold_bold success:function(data){ #cold_bold location.href = "/SpringRestful/emp/find"; #cold_bold } #cold_bold }); #cold_bold } #cold_bold </script> </head> <body> <form action="updateEmp.do" method="post" id="myform"> <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <td>EMPNO:</td> <td><input type="text" name="empno" value="${emp.empno }"/></td> </tr> <tr> <td>姓名:</td> <td><input type="text" name="ename" value="${emp.ename }"/></td> </tr> <tr> <td>岗位:</td> <td><input type="text" name="job" value="${emp.job }"/></td> </tr> <tr> <td>工资:</td> <td><input type="text" name="sal" value="${emp.sal }"/></td> </tr> <tr> #cold_bold <td colspan="2"><input type="button" value="保存" onclick="save();"/></td> </tr> </table> </form> </body> </html>
步骤五:测试
重新部署并启动tomcat,测试通过员工的增删改查功能。
本案例的完整代码如下所示:
EmpDao完整代码如下:
package com.tarena.dao; import java.util.List; import com.tarena.annotation.MyBatisRepository; import com.tarena.entity.Emp; /** * 员工表的DAO组件 */ @MyBatisRepository public interface EmpDao { List<Emp> findAll(); void save(Emp emp); Emp findById(int id); void update(Emp emp); void delete(int id); }
EmpMapper.xml完整代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <mapper namespace="com.tarena.dao.EmpDao"> <!-- 查询全部的员工 --> <select id="findAll" resultType="com.tarena.entity.Emp"> select * from t_emp </select> <!-- 保存一条员工数据 --> <insert id="save" parameterType="com.tarena.entity.Emp"> insert into t_emp values( emp_seq.nextval, #{ename,jdbcType=VARCHAR}, #{job,jdbcType=VARCHAR}, #{mgr,jdbcType=NUMERIC}, #{hiredate,jdbcType=DATE}, #{sal,jdbcType=NUMERIC}, #{comm,jdbcType=NUMERIC}, #{deptno,jdbcType=NUMERIC} ) </insert> <!-- 根据ID查询员工 --> <select id="findById" parameterType="java.lang.Integer" resultType="com.tarena.entity.Emp"> select * from t_emp where empno=#{id} </select> <!-- 修改员工 --> <update id="update" parameterType="com.tarena.entity.Emp"> update t_emp set ename=#{ename,jdbcType=VARCHAR}, job=#{job,jdbcType=VARCHAR}, sal=#{sal,jdbcType=NUMERIC} where empno=#{empno,jdbcType=NUMERIC} </update> <!-- 删除员工 --> <delete id="delete" parameterType="java.lang.Integer"> delete from t_emp where empno=#{id} </delete> </mapper>
web.xml完整代码如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- Spring前端控制器 --> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name> contextConfigLocation </param-name> <param-value> classpath:applicationContext.xml </param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 使用Filter解决中文乱码问题 --> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
applicationContext.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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <!-- 配置数据源 --> <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" /> <property name="driverClassName" value="oracle.jdbc.OracleDriver" /> <property name="username" value="lhh" /> <property name="password" value="123456" /> </bean> <!-- 配置SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="ds" /> <property name="mapperLocations" value="classpath:com/tarena/entity/*.xml" /> </bean> <!-- 配置MyBatis注解 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.tarena.dao" /> <property name="annotationClass" value="com.tarena.annotation.MyBatisRepository" /> </bean> <!-- 开启注解扫描 --> <context:component-scan base-package="com.tarena" /> <!-- 开启RequestMapping注解 --> <mvc:annotation-driven /> <!-- 处理请求转发 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 支持RESTful访问静态资源 --> <mvc:default-servlet-handler /> </beans>
EmpController完整代码如下:
package com.tarena.controller; import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.tarena.dao.EmpDao; import com.tarena.entity.Emp; @Controller @RequestMapping("/emp") public class EmpController { @Resource private EmpDao empDao; @RequestMapping(value="/find",method=RequestMethod.GET) public String find(Model model) { List<Emp> list = empDao.findAll(); model.addAttribute("emps", list); return "emp/emp_list"; } /** * 打开新增页面 */ @RequestMapping(value="/toAdd",method=RequestMethod.GET) public String toAdd() { return "emp/add_emp"; } /** * 新增保存 */ @RequestMapping(value="/add",method=RequestMethod.POST) public String add(Emp emp) { empDao.save(emp); return "redirect:find"; } /** * 打开修改页面 */ @RequestMapping(value="/toUpdate/{id}",method=RequestMethod.GET) public String toUpdate( @PathVariable("id") int id, Model model) { Emp e = empDao.findById(id); model.addAttribute("emp", e); return "emp/update_emp"; } /** * 修改保存 */ @RequestMapping(value="/update",method=RequestMethod.PUT) @ResponseBody public boolean update(@RequestBody Emp emp) { empDao.update(emp); return true; } /** * 删除 */ @RequestMapping(value="/{id}",method=RequestMethod.DELETE) @ResponseBody public boolean delete(@PathVariable("id") int id) { empDao.delete(id); return true; } }
json.js完整代码如下:
// 将表单数据转换成json对象 $.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); $.each(a, function() { if (o[this.name]) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); return o; };
emp_list.jsp完整代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <script type="text/javascript" src="../js/jquery-1.11.1.js"></script> <script type="text/javascript"> function delete_emp(id) { var r = window.confirm("确定要删除此数据吗?"); if(r) { //location.href = "deleteEmp.do?id="+id; $.ajax({ type:"DELETE", url:"/SpringRestful/emp/"+id, dataType:"json", success:function(data){ location.href = "/SpringRestful/emp/find"; } }); } } </script> </head> <body> <div align="center"> <input type="button" value="新增" onclick="location.href='toAdd'"/> </div> <table width="60%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <th>EMPNO</th> <th>ENAME</th> <th>JOB</th> <th>MGR</th> <th>HIREDATE</th> <th>SAL</th> <th>COMM</th> <th>DEPTNO</th> <th></th> </tr> <c:forEach items="${emps }" var="emp"> <tr> <td>${emp.empno }</td> <td>${emp.ename }</td> <td>${emp.job }</td> <td>${emp.mgr }</td> <td>${emp.hiredate }</td> <td>${emp.sal }</td> <td>${emp.comm }</td> <td>${emp.deptno }</td> <td> <input type="button" value="修改" onclick="location.href='toUpdate/${emp.empno }'"/> <input type="button" value="删除" onclick="delete_emp(${emp.empno });"/> </td> </tr> </c:forEach> </table> </body> </html>
add_emp.jsp完整代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> </head> <body> <form action="add" method="post"> <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <td>姓名:</td> <td><input type="text" name="ename"/></td> </tr> <tr> <td>岗位:</td> <td><input type="text" name="job"/></td> </tr> <tr> <td>工资:</td> <td><input type="text" name="sal"/></td> </tr> <tr> <td colspan="2"><input type="submit" value="保存" /></td> </tr> </table> </form> </body> </html>
update_emp.jsp完整代码如下:
<%@page pageEncoding="utf-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <script type="text/javascript" src="../../js/jquery-1.11.1.js"></script> <script type="text/javascript" src="../../js/json.js"></script> <script type="text/javascript"> function save() { $.ajax({ type:"PUT", url:"/SpringRestful/emp/update", data:JSON.stringify($("#myform").serializeObject()), dataType:"json", contentType:"application/json", success:function(data){ location.href = "/SpringRestful/emp/find"; } }); } </script> </head> <body> <form action="updateEmp.do" method="post" id="myform"> <table width="40%" border="1" cellpadding="2" cellspacing="0" align="center"> <tr> <td>EMPNO:</td> <td><input type="text" name="empno" value="${emp.empno }"/></td> </tr> <tr> <td>姓名:</td> <td><input type="text" name="ename" value="${emp.ename }"/></td> </tr> <tr> <td>岗位:</td> <td><input type="text" name="job" value="${emp.job }"/></td> </tr> <tr> <td>工资:</td> <td><input type="text" name="sal" value="${emp.sal }"/></td> </tr> <tr> <td colspan="2"><input type="button" value="保存" onclick="save();"/></td> </tr> </table> </form> </body> </html>