(程序源代码:http://download.youkuaiyun.com/detail/wq359135103/5592043)
摘 要
SSH 为 struts+spring+hibernate的一个集成框架,是目前较流行的一种Web应用程序开源框架。集成SSH框架的系统从职责上分为四层:表示层、业务逻辑层、数据持久层和域模块层,以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。其中使用Struts作为系统的整体基础架构,负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做管理,管理struts和hibernate。这种新的开发模式让我们的开发更加方便、快捷、思路清晰,同时还便于以后的维护,实现的软件的高内聚,低耦合。
关键词:Struts,hibernate,spring,SSH框架
目 录
1 前 言
SSH 为 struts+spring+hibernate的一个集成框架,是目前较流行的一种Web应用程序开源框架。SSH框架的系统从职责上分为四层:表示层、业务逻辑层、数据持久层和域模块层,以帮助开发人员在短期内搭建结构清晰、可复用性好、维护方便的Web应用程序。其中使用Struts作为系统的整体基础架构,负责MVC的分离,在Struts框架的模型部分,控制业务跳转,利用Hibernate框架对持久层提供支持,Spring做管理,管理struts和hibernate。具体做法是:用面向对象的分析方法根据需求提出一些模型,将这些模型实现为基本的Java对象,然后编写基本的DAO接口,并给出Hibernate的DAO实现,采用Hibernate架构实现的DAO类来实现Java类与数据库之间的转换和访问,最后由Spring做管理,管理struts和hibernate。
系统的基本业务流程是: 在表示层中,首先通过JSP页面实现交互界面,负责传送请求(Request)和接收响应(Response),然后Struts根据配置文件(struts-config.xml)将ActionServlet接收到的Request委派给相应的Action处理。在业务层中,管理服务组件的Spring IoC容器负责向Action提供业务模型(Model)组件和该组件的协作对象数据处理(DAO)组件完成业务逻辑,并提供事务处理、缓冲池等容器组件以提升系统性能和保证数据的完整性。而在持久层中,则依赖于Hibernate的对象化映射和数据库交互,处理DAO组件请求的数据,并返回处理结果。
采用上述开发模型,不仅实现了视图、控制器与模型的彻底分离,而且还实现了业务逻辑层与持久层的分离。这样无论前端如何变化,模型层只需很少的改动,并且数据库的变化也不会对前端有所影响,大大提高了系统的可复用性。而且由于不同层之间耦合度小,有利于团队成员并行工作,大大提高了开发效率。
2 Struts框架
2.1 Struts简介
Struts 是Apache软件基金会(ASF)赞助的一个开源项目。它最初是Jakarta项目中的一个子项目,并在2004年3月成为ASF的顶级项目。它通过采用JavaServlet/JSP技术,实现了基于Java EEWeb应用的MVC设计模式的应用框架,是MVC经典设计模式中的一个经典产品。
2.2 Struts框架的搭建
登录http://struts.apache.org/download 下载Struts2的jar包,解压打开lib文件夹将如图2.1所示的jar包导入Eclipse项目下的lib包中,Struts框架即搭建成功。
图2.1 Struts的jar包
2.3 struts.xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.custom.i18n.resources" value="mess"></constant>
<constant name="struts.devMode" value="true"/>
<constant name="struts.i18n.encoding" value="utf-8"></constant>
<package name="jzy" extends="struts-default" namespace="/">
<action name="addGoods" method="addGoods" class="addGoodsAction">
<result name="error">/error.jsp</result>
<result name="success" type="chain">listGoods</result>
</action>
<action name="listGoods" method="listGoods" class="addGoodsAction">
<result name="error">/error.jsp</result>
<result name="goodsList">/goodsList.jsp</result>
</action>
<action name="delGoods" method="delGoods" class="addGoodsAction">
<result name="error">/error.jsp</result>
<result name="success" type="chain">listGoods</result>
</action>
<action name="updateGoods" method="updateGoods" class="addGoodsAction">
<result name="error">/error.jsp</result>
<result name="success" type="chain">listGoods</result>
<result name="updateGoods">/editGoods.jsp</result>
</action>
<action name="*">
<result>/{1}.jsp</result>
</action>
</package>
</struts>
3 Hibernate框架
3.1 hibernate简介
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
3.2 hibernate框架搭建
登录http://www.hibernate.org/download下载hibernate的jar包,解压文件将required的文件下的所有jar文件复制到Eclipse项目下的lib文件夹下,hibernate框架即配置成功。jar文件如图3.1所示。
3.1 hibernate的jar包
3.2.1 Goods.hbm.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated 2010-11-9 18:15:04 by Hibernate Tools 3.3.0.GA -->
<hibernate-mapping>
<class name="cn.jzy.ssh.domain.Goods" table="goods">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="name" type="java.lang.String">
<column name="name" />
</property>
<property name="price" type="java.lang.Float">
<column name="price" />
</property>
<property name="inventory" type="java.lang.Integer">
<column name="inventory" />
</property>
<property name="status" type="java.lang.String">
<column name="status" />
</property>
<property name="imgUrl" type="java.lang.String">
<column name="imgUrl" />
</property>
<property name="description" type="java.lang.String">
<column name="description" />
</property>
<property name="categoryId" type="java.lang.Integer">
<column name="categoryId" />
</property>
</class>
</hibernate-mapping>
3.2.2 对象/关系映射
package cn.jzy.ssh.domain;
public class Goods {
private int id;
private String name;
private float price;
private int inventory;
private String status;
private String description;
private String imgUrl;
private int categoryId;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getInventory() {
return inventory;
}
public void setInventory(int inventory) {
this.inventory = inventory;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
public int getCategoryId() {
return categoryId;
}
public void setCategoryId(int categoryId) {
this.categoryId = categoryId;
}
}
4 Spring框架
4.1 Spring 简介
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
4.2 Spring框架搭建
登录http://www.springsource.org/download/community下载Spring包,解压文件将dist文件下的jar包全部导入Eclipse项目下的lib文件下,jar文件如图4.1所示。
图4.1 Spring的jar包
5 SSH框架整合
5.1 Spring与Struts整合
Spring与Struts整合首先将struts2-spring-plugin-2.2.1.jar复制到Eclipse项目的lib文件夹下。其次struts.xml文件中action的class路径需在applicationContext.xml文件中进行映射,而不是决定的路径了。
在web.xml文件中配置Spring监听器,代码如下:
<listener>
<listener-class>org.springframework.web.context.ContextLoad erListener</listener-class>
</listener>
5.2 Spring 与Hibernate整合
Spring与Hibernate整合需要增加配置文件,在WEB-INF文件下增加applicationContext.xml用于配置Spring与Hibernate的整合配置文件。而其它的Goods.hbm.xml配置不变。applicationContext.xml配置如下:
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Spring配置文件的Schema信息 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 定义数据源Bean,使用C3P0数据源实现 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- 指定连接数据库的驱动 -->
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<!-- 指定连接数据库的URL -->
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/onlineshop?useUnicode=true&characterEncoding=utf-8" />
<!-- 指定连接数据库的用户名 -->
<property name="user" value="root" />
<!-- 指定连接数据库的密码 -->
<property name="password" value="123456" />
<!-- 指定连接数据库连接池的最大连接数 -->
<property name="maxPoolSize" value="40" />
<!-- 指定连接数据库连接池的最小连接数 -->
<property name="minPoolSize" value="1" />
<!-- 指定连接数据库连接池的初始化连接数 -->
<property name="initialPoolSize" value="1" />
<!-- 指定连接数据库连接池的连接的最大空闲时间 -->
<property name="maxIdleTime" value="20" />
</bean>
<!-- 定义Hibernate的SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!-- 依赖注入数据源,注入正是上面定义的dataSource -->
<property name="dataSource" ref="dataSource" />
<!-- mappingResouces属性用来列出全部映射文件 -->
<property name="mappingResources">
<list>
<!-- 以下用来列出Hibernate映射文件 -->
<value>cn/jzy/ssh/domain/Goods.hbm.xml</value>
</list>
</property>
<!-- 定义Hibernate的SessionFactory的属性 -->
<property name="hibernateProperties">
<!-- 配置Hibernate属性 -->
<value>
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.format_sql=true;
</value>
</property>
</bean>
<bean id="GoodsDao" class="cn.jzy.ssh.dao.GoodsDaoHibernate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="GoodsService" class="cn.jzy.ssh.service.GoodsServiceImpl">
<property name="GoodsDao" ref="GoodsDao"></property>
</bean>
<bean id="addGoodsAction" class="cn.jzy.ssh.action.GoodsAction" scope="prototype">
<property name="GoodsService" ref="GoodsService"></property>
</bean>
<bean id="myService" class="cn.jzy.ssh.service.MyServiceImpl"></bean>
<bean id="loginAction" class="cn.jzy.ssh.action.LoginAction"
scope="prototype">
<property name="ms" ref="myService"></property>
</bean>
<!-- 配置Hibernate的局部事务管理器,使用HibernateTransactionManager类 -->
<!-- 该类实现PlatformTransactionManager接口,是针对Hibernate的特定实现-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- 配置HibernateTransactionManager时需要依注入SessionFactory的引用 -->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置事务增强处理,指定事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 用于配置详细的事务语义 -->
<tx:attributes>
<!-- 所有以'get'开头的方法是read-only的 -->
<tx:method name="get*" read-only="true"/>
<!-- 其他方法使用默认的事务设置 -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 配置一个切入点 -->
<aop:pointcut id="leePointcut"
expression="bean(GoodsService)"/>
<!-- 指定在leePointcut切入点应用txAdvice事务增强处理 -->
<aop:advisor advice-ref="txAdvice"
pointcut-ref="leePointcut"/>
</aop:config>
</beans>
5.3 SSH框架测试
根据以上配置新建一个SSHDemo项目实现对一个商品表的增、删、查、该。项目源程序见附录A。测试运行结果如下:
(1)对goods表插入一件商品,插入界面如图5.1所示。
图5.1 goods表插入
(2)查询插入数据的结果如图5.2所示。
图5.2 goods表查询
(3)更新刚才插入的商品数据,更新界面如图5.3所示,结果如图5.4所示。
图5.3goods表更新界面
图 5.4 goods表更新结果
(4)删除插入的数据,结果如图5.4 所示
图5.5 goods表删除结果
6 总 结
在这次SSH框架的搭建中,我还是积累了很多一些自己不知道的知识,具体有如下几点:Struts中Action的方法不能有参数,否则在配置struts.xml文件中的Action调用此方法是会报无此方法的异常;Spring的Hibernate第三版和第四版有很大的变化,第四版的Spring不再支持HibernateTemplate()方法,在这次分别搭建Spring和Hibernate框架搭建中,我先用的是第四版的Hibernate与Spring,由于SSH框架才开始学,在整合中只会用HibernateTemplate()方法操作数据库,因此在整合是都换成了第三版进行整合。通过这次课程SSH框架的课程设计知道了自己在学习SSH框架中还有不足,而学习是个积累的过程。要想学好这样的框架就必须先了解Struts,Spring,Hibernate各个的运行机制流程。在熟悉各个框架的基础上在进行整合才能达到好的效果。 由于现在能力不够所以做的还不够好,上面的例子自己照着流程也做了一下,可是由于对框架的了解并不是十分的透彻,以及各个版本的融合问题,例子中还有些问题。但是整个开发搭建的流程自己走了一遍,也对SSH有了更多的一些了解。
参 考 文 献
[1]朱福喜.《Java语言程序设计》(第二版).科学出版社
[2]陈国君等.《Java程序设计基础》(第二版).清华大学出版社
[3] Deitel.《Java大学基础教程》(第六版).电子工业出版社
[4] MaryCampione.《Java语言导学》(第四版).机械工业出版社
[5] Y.Daniel Liang.《Java语言程序设计基础篇》(第六版). 机械工业出版社
[6] Kathy Sierra.《Head First Java》(第二版).东南大学出版社
[ 7] 李刚.《轻量级JavaEE企业应用实战》(第三版).电子工业出版社
[8] 王建国《Struts 2 框架应用开发教程》清华大学出版社
[10] 耿祥义等《Java面向对象程序设计》.清华大学出版社
[11] Bruce Eckel《Java编程思想》(第四版). 机械工业出版社
附录A:SSHDemo项目源程序
1.DAO层源代码
(1)GoodsDao:
package cn.jzy.ssh.dao;
import java.util.List;
import cn.jzy.ssh.domain.Goods;
public interface GoodsDao {
Goods get(Integer id);
Integer save(Goods goods);
void update(Goods goods);
void delete(Integer id);
void delete(Goods goods);
List<Goods> findByName(String name);
public List<Goods> findAllGoods();
}
(2)GoodsDaoHibernate
package cn.jzy.ssh.dao;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import cn.jzy.ssh.domain.Goods;
public class GoodsDaoHibernate extends HibernateDaoSupport implements GoodsDao {
@Override
public Goods get(Integer id) {
return getHibernateTemplate().get(Goods.class, id);
}
@Override
public Integer save(Goods goods) {
return (Integer)getHibernateTemplate().save(goods);
}
@Override
public void update(Goods goods) {
getHibernateTemplate().update(goods);
}
@Override
public void delete(Integer id) {
getHibernateTemplate().delete(get(id));
}
@Override
public void delete(Goods goods) {
getHibernateTemplate().delete(goods);
}
@SuppressWarnings("unchecked")
@Override
public List<Goods> findByName(String name) {
return (List<Goods>)getHibernateTemplate().find("from goods g where g.name like ?",name);
}
@SuppressWarnings("unchecked")
@Override
public List<Goods> findAllGoods() {
return (List<Goods>)getHibernateTemplate().find("from cn.jzy.ssh.domain.Goods as goods");
}
}
2 .Service层源代码
(1)GoodsService
package cn.jzy.ssh.service;
import java.util.List;
import cn.jzy.ssh.domain.Goods;
public interface GoodsService {
boolean addGoods(Goods goods);
public List<Goods> listGoods();
public void deleteGoods(int id);
public Goods getGoodsByID(int id);
public void updateGoods(Goods goods);
}
(2)GoodsServiceImpl
package cn.jzy.ssh.service;
import java.util.List;
import cn.jzy.ssh.dao.GoodsDao;
import cn.jzy.ssh.domain.Goods;
public class GoodsServiceImpl implements GoodsService{
private GoodsDao goodsDao;
public void setGoodsDao(GoodsDao goodsDao){
this.goodsDao=goodsDao;
}
@Override
public boolean addGoods(Goods goods) {
int result=goodsDao.save(goods);
if(result>0){
return true;
}
return false;
}
@Override
public List<Goods> listGoods() {
return goodsDao.findAllGoods();
}
@Override
public void deleteGoods(int id) {
goodsDao.delete(id);
}
@Override
public Goods getGoodsByID(int id) {
return goodsDao.get(id);
}
@Override
public void updateGoods(Goods goods) {
goodsDao.update(goods);
}
}
3. GoodsAction 源代码
package cn.jzy.ssh.action;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.Action;
import cn.jzy.ssh.domain.Goods;
import cn.jzy.ssh.service.GoodsService;
public class GoodsAction implements Action,ServletRequestAware{
private Goods goods;
private String tip;
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private GoodsService goodsService;
protected HttpServletRequest request;
public Goods getGoods() {
return goods;
}
public void setGoods(Goods goods) {
this.goods = goods;
}
public String getTip() {
return tip;
}
public void setTip(String tip) {
this.tip = tip;
}
public void setGoodsService(GoodsService goodsService) {
this.goodsService = goodsService;
}
public String addGoods() throws Exception{
if(goodsService.addGoods(goods)){
setTip("添加商品成功!");
return SUCCESS;
}else{
return ERROR;
}
}
public String listGoods() throws Exception{
List<Goods> goods=goodsService.listGoods();
/*for(Goods g:goods){
System.out.println(g.toString());
}*/
request.setAttribute("goodsList", goods);
return "goodsList";
}
public String delGoods() throws Exception{
if(id!=0){
goodsService.deleteGoods(id);
return SUCCESS;
}
return ERROR;
}
public String updateGoods() throws Exception{
int select=Integer.parseInt(request.getParameter("select"));
if(select==1){
if(id!=0){
Goods goods=goodsService.getGoodsByID(id);
request.setAttribute("goods", goods);
return "updateGoods";
}
}
if(select==2){
goodsService.updateGoods(goods);
return SUCCESS;
}
return ERROR;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request=request;
}
@Override
public String execute() throws Exception {
return null;
}
}
4. Jsp源代码
(1)addGoods.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>
<link href="css/bootstrap.css" rel="stylesheet" media="screen">
<link href="css/myshop.css" rel="stylesheet" media="screen">
</head>
<body>
<div class="container">
<div class="row">
<s:include value="top.jsp"></s:include>
<div class="span3"></div>
<div class="span9">
<s:form action="/addGoods" class="form-horizontal">
<s:textfield name="goods.name" label="商品名"></s:textfield>
<s:textfield name="goods.price" label="价格"></s:textfield>
<s:textfield name="goods.inventory" label="库存"></s:textfield>
<s:textfield name="goods.status" label="状态"></s:textfield>
<s:textfield name="goods.imgUrl" label="图片位置"></s:textfield>
<s:textfield name="goods.description" label="描述"></s:textfield>
<s:textfield name="goods.categoryId" label="分类ID"></s:textfield>
<table>
<tr>
<td colspan="2">
<button type="submit" class="btn btn-success">添加</button>
<button type="reset" class="btn btn-success">重置</button>
</td>
</tr>
</table>
</s:form>
</div>
</div>
</div>
<script src="js/jquery-1.9.1.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>
(2)goodsList.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!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>
<link href="css/bootstrap.css" rel="stylesheet" media="screen">
<link href="css/myshop.css" rel="stylesheet" media="screen">
</head>
<body>
<div class="container">
<div class="row">
<s:include value="top.jsp"></s:include>
<table class="table table-hover table-bordered">
<tr>
<td>ID</td>
<td>商品名称</td>
<td>单价</td>
<td>库存</td>
<td>状态</td>
<td>图片地址</td>
<td>描述</td>
<td>分类ID</td>
<td width="50px">操作</td>
</tr>
<s:iterator value="#request.goodsList">
<tr>
<td><s:property value="id" /></td>
<td><s:property value="name" /></td>
<td><s:property value="price" /></td>
<td><s:property value="inventory" /></td>
<td><s:property value="status" /></td>
<td><s:property value="imgUrl" /></td>
<td><s:property value="description" /></td>
<td><s:property value="categoryId" /></td>
<td><a href="delGoods?id=<s:property value='id'/>">删除</a>
<a href="updateGoods?id=<s:property value='id'/>&select=1">编辑</a>
</tr>
</s:iterator>
</table>
</div>
</div>
<script src="js/jquery-1.9.1.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>
(3)editGoods.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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>
<link href="css/bootstrap.css" rel="stylesheet" media="screen">
<link href="css/myshop.css" rel="stylesheet" media="screen">
</head>
<body>
<div class="container">
<div class="row">
<s:include value="top.jsp"></s:include>
<s:form action="/updateGoods?select=2" class="form-horizontal">
<table class="table table-hover table-bordered">
<tr>
<td>ID</td>
<td>${goods.id }</td>
<td><input type="text" readonly="readonly" name="goods.id" value="${goods.id}" /></td>
</tr>
<tr>
<td>商品名</td>
<td>${goods.name }</td>
<td><input type="text" name="goods.name" value="${goods.name}" /></td>
</tr>
<tr>
<td>单价</td>
<td>${goods.price }</td>
<td><input type="text" name="goods.price" value="${goods.price}" /></td>
</tr>
<tr>
<td>库存</td>
<td>${goods.inventory }</td>
<td><input type="text" name="goods.inventory" value="${goods.inventory}" /></td>
</tr>
<tr>
<td>状态</td>
<td>${goods.status }</td>
<td><input type="text" name="goods.status" value="${goods.status}" /></td>
</tr>
<tr>
<td>图片位置</td>
<td>${goods.imgUrl }</td>
<td><input type="text" name="goods.imgUrl" value="${goods.imgUrl}" /></td>
</tr>
<tr>
<td>描述</td>
<td>${goods.description }</td>
<td><input type="text" name="goods.description" value="${goods.description}" /></td>
</tr>
<tr>
<td>分类ID</td>
<td>${goods.categoryId }</td>
<td><input type="text" name="goods.categoryId" value="${goods.categoryId}" /></td>
</tr>
</table>
<button type="submit" class="btn btn-info">更新</button>
<button type="reset" class="btn btn-info">重置</button>
</s:form>
</div>
</div>
<script src="js/jquery-1.9.1.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>