本文将在Eclipse开发环境下,采用Spring MVC + Spring + MyBatis + Maven + Log4J 框架搭建一个Java web 项目。
1. 环境准备:
1.1 创建数据库:
本文使用的数据库为MySQL ,首先创建一个test数据库,创建goods表,SQL如下:
CREATE TABLE `goods` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`goodsname` VARCHAR(20) NOT NULL,
`goodsprice` DECIMAL(10,0) NOT NULL,
`goodscosting` DECIMAL(10,0) NOT NULL,
`releasedate` VARCHAR(20) NOT NULL,
`goodscount` INT(11) NOT NULL,
`goodsdetail` VARCHAR(500) NOT NULL,
`goodsphoto` VARCHAR(50) NOT NULL,
`goodstype` VARCHAR(50) NOT NULL,
`isdelete` INT(11) NOT NULL DEFAULT '0',
KEY `id` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
1.2 新建工程:
本项目采用maven工具进行项目管理,在Eclipse中创建maven web 项目。最终项目结构及模块功能如下所示:
1.3 配置pom.xml
创建项目后,修改主工程模块的pom.xml文件,添加本项目依赖库,主要有MyBatis,Spring3.0,MySQL,Tomcat,Maven等;具体如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ganji</groupId>
<artifactId>SpringMyBatisDemo</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>SpringMyBatisDemo Maven Webapp</name>
<url>http://maven.apache.org</url> <properties>
<!-- spring版本号 -->
<spring.version>3.2.4.RELEASE</spring.version>
<!-- mybatis版本号 -->
<mybatis.version>3.2.4</mybatis.version>
<!-- log4j日志文件管理包版本 -->
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.9</log4j.version>
<!-- servlet安装包版本 -->
<servlet.version>3.0.1</servlet.version>
</properties> <dependencies> <!-- javax servlet 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
</dependency> <!-- spring核心包 -->
<!-- spring frame start -->
<!-- 添加string-core包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加spring-web包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加spring-oxm包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加spring-tx包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加spring-jdbc包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加spring-webmvc包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加spring-aop包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加AspectJ包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1</version>
</dependency> <!-- 添加 spring-context-support包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加spring-test包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring frame end --> <!-- hibernate start-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.2.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
<!-- hibernate end--> <!-- mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency> <!-- mybatis/spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency> <!-- mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.29</version>
</dependency> <!-- 添加druid连接池包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.12</version>
</dependency> <!-- Junit单元测试包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency> <!-- json数据 -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency> <!-- 日志文件管理包 -->
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end --> <!-- JSTL 标签库依赖包 -->
<!-- JSTL Start -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jstl-impl</artifactId>
<version>1.2</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- JSTL End -->
</dependencies> <repositories> <!-- 配置 maven 远程仓库 -->
<repository>
<id>nexus</id>
<name>nexus</name>
<url>http://mvn.corp.ganji.com:8081/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<!-- 远程仓库配置结束 --> <!-- 配置 tomcat-maven-plugin 确保MAVEN能够下载到该插件 -->
<repository>
<id>people.apache.snapshots</id>
<url>
http://repository.apache.org/content/groups/snapshots-group/
</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories> <pluginRepositories> <pluginRepository>
<id>nexus</id>
<name>nexus</name>
<url>http://mvn.corp.ganji.com:8081/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository> <pluginRepository>
<name>oss.sonatype.org</name>
<id>oss.sonatype.org</id>
<url>http://oss.sonatype.org/content/groups/public</url>
</pluginRepository> <pluginRepository>
<id>apache.snapshots</id>
<name>Apache Snapshots</name>
<url>
http://repository.apache.org/content/groups/snapshots-group/
</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<!-- 配置 tomcat-maven-plugin 结束 --> <build>
<finalName>SpringMyBatisDemo</finalName>
<!-- 配置tomcat 服务器 --> <!-- directory缺省情况下指向target -->
<!--<directory>${basedir}/target</directory> -->
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<url>http://localhost:8080/manager/text</url>
<!-- server、username、password对应maven的setting下的配置 -->
<server>tomcat</server>
<username>admin</username>
<password>admin</password>
<path>/${project.build.finalName}</path>
<!-- war文件路径缺省情况下指向target -->
<!--<warFile>${basedir}/target/${project.build.finalName}.war</warFile> -->
</configuration>
</plugin>
</plugins> <pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.mybatis.generator
</groupId>
<artifactId>
mybatis-generator-maven-plugin
</artifactId>
<versionRange>
[1.3.2,)
</versionRange>
<goals>
<goal>generate</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build> </project>
2. 持久层设计
本项目的持久层采用MyBatis框架实现。在项目的src/main/resources文件夹下创建一个名为applicationContext.xml的文件,该文件为spring的核心配置文件。
配置文件基本结构如下所示:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
... ...
</beans>
Spring整合MyBatis
在applicationContext.xml中添加如下代码
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
<!-- MyBatis配置 -->
<!-- 创建SqlSessionFactory,同时指定数据源 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:/mapper/*Mapper.xml" />
</bean>
<!-- 指定Mapper映射文件路径 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.shopping.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
<!--配置SqlSessionTemplate对象-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean> <!-- 启动context注解 -->
<context:annotation-config /> <!-- 定义扫描根路径,不使用默认的扫描方式 -->
<context:component-scan base-package="com.shopping" use-default-filters="false">
<!-- 扫描符合@Service的类 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />
<!-- 扫描符合@Repository的类 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />
<!-- 扫描符合@Controller的类 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<!-- 扫描符合@Component的类 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component" />
</context:component-scan>
2.1 创建领域模型对象Goods
该对象可以看做是数据库表的对象翻译,每个字段对应数据库中的一个属性。
package com.shopping.domain; /**
* @ClassName: Goods
* @Description:商品model 对应数据库商品表
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:19:26
*/
public class Goods { /**
* @Fields id : 商品表主键
*/
private int id; /**
* @Fields goodsname : 商品名称
*/
private String goodsname; /**
* @Fields goodsprice : 商品价格
*/
private double goodsprice; /**
* @Fields goodscosting : 商品成本
*/
private double goodscosting; /**
* @Fields releaseDate : 发布日期
*/
private String releaseDate; /**
* @Fields goodscount : 商品数量
*/
private int goodscount; /**
* @Fields goodsdetail : 商品明细
*/
private String goodsdetail; /**
* @Fields goodsphoto : 商品图片
*/
private String goodsphoto; /**
* @Fields goodsType : 商品类型
*/
private String goodsType; /**
* @Fields isDelete : 是否删除
*/
private boolean isDelete;
... ...//省略getXxx和SetXxx方法
}
2.2 创建数据访问层dao及daoImpl
@Resource 注解表明该属性值通过Spring注入
@Repository 注解将一个类声明为bean
代码如下:
package com.shopping.dao; import java.util.List;
import com.shopping.domain.Goods; /**
* @ClassName: GoodsDao
* @Description: GoodsDao层接口 , 定义对数据库中Goods表的各种操作
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:32:01
*/
public interface GoodsDao { /**
* @Title: Add
* @Description: 添加商品
* @param goods : 新增商品
* @return : 添加结果 1: 成功 0: 失败
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:38:51
*/
public boolean Add(Goods goods); /**
* @Title: Update
* @Description: 更新商品
* @param goods : 修改后的商品信息
* @return : 更新结果 1: 成功 0: 失败
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:39:07
*/
public boolean Update(Goods goods); /**
* @Title: DeleteById
* @Description: 通过商品ID来删除商品
* @param goodsId : 商品ID
* @return : 删除结果 1: 成功 0: 失败
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:39:10
*/
public boolean DeleteById(int goodsId); /**
* @Title: Query
* @Description: 查询商品
* @param goods : 查询条件,若没有 可以为空
* @return : 查询结果 null or List
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:39:12
*/
public List<Goods> Query(Goods goods); /**
* @Title: queryById
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param id
* @return
* @author: zhangzhifei
* @date: 2015年8月23日 下午4:16:57
*/
public Goods QueryById(int id);
}
package com.shopping.dao.impl; import java.util.List; import javax.annotation.Resource; import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository; import com.shopping.dao.GoodsDao;
import com.shopping.domain.Goods; /**
* @ClassName: GoodsDaoImpl
* @Description: GoodsDao接口的实现,定义对数据库中Goods表的具体操作
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:47:04
*/
@Repository
public class GoodsDaoImpl implements GoodsDao{ /**
* @Fields sqlSessionTemplate : Spring sqlSessionTemplate对象
*/
@Resource(name="sqlSession")
private SqlSessionTemplate sqlSessionTemplate; public SqlSessionTemplate getSqlSessionTemplate() {
return sqlSessionTemplate;
} public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
} /**
* <p>Title: Add</p>
* <p>Description: </p>
* @param goods
* @return
* @see com.shopping.dao.GoodsDao#Add(com.shopping.domain.Goods)
*/
public boolean Add(Goods goods) {
return this.sqlSessionTemplate.insert("Add",goods) > 0 ? true : false ;
} /**
* <p>Title: Update</p>
* <p>Description: </p>
* @param goods
* @return
* @see com.shopping.dao.GoodsDao#Update(com.shopping.domain.Goods)
*/
public boolean Update(Goods goods) {
return this.sqlSessionTemplate.update("Update", goods) > 0 ? true : false ;
} /**
* <p>Title: DeleteById</p>
* <p>Description: </p>
* @param goodsId
* @return
* @see com.shopping.dao.GoodsDao#DeleteById(int)
*/
public boolean DeleteById(int goodsId) {
return this.sqlSessionTemplate.delete("DeleteById", goodsId) > 0 ? true : false ;
} /**
* <p>Title: Query</p>
* <p>Description: </p>
* @param goods
* @return
* @see com.shopping.dao.GoodsDao#Query(com.shopping.domain.Goods)
*/
public List<Goods> Query(Goods goods) {
return this.sqlSessionTemplate.selectList("Query", goods);
} /**
* <p>Title: queryById</p>
* <p>Description: </p>
* @param id
* @return
* @see com.shopping.dao.GoodsDao#queryById(int)
*/
@Override
public Goods QueryById(int id) {
return this.sqlSessionTemplate.selectOne("QueryById", id);
} }
2.3 创建数据库Mapper文件GoodsDaoMapper.xml 该文件放置对数据表的各种操作SQL语句
id: SQL语句的名字,sqlsession通过该名字提取对应SQL语句
parameterType: 该语句参数值的类型
keyColumn: 主键
resultType: SQL语句返回值类型。
<?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="com.shopping.dao.GoodsDao"> <insert id="Add" parameterType="com.shopping.domain.Goods"
useGeneratedKeys="true" keyColumn="id">
insert into Goods( goodsname, goodsprice, goodscosting, releasedate,
goodscount, goodsdetail, goodsphoto, goodstype, isdelete)
values(#{goodsname}, #{goodsprice}, #{goodscosting}, #{releaseDate},
#{goodscount},#{goodsdetail}, #{goodsphoto}, #{goodsType}, 0)
</insert> <delete id="DeleteById" parameterType="int">
update goods set isdelete = 1 where id = #{id}
</delete> <update id="Update" parameterType="com.shopping.domain.Goods">
update goods set goodsname=#{goodsname},
goodsprice=#{goodsprice}, goodscosting=#{goodscosting},
releasedate=#{releaseDate}, goodscount=#{goodscount},
goodsdetail=#{goodsdetail}, goodsphoto=#{goodsphoto},
goodstype=#{goodsType}, isdelete=#{isDelete}
where id=#{id}
</update> <!-- 条件查询,查询多条记录即返回结果是一个集合的时候,resultType不是集合类型,而是集合所包含的类型 -->
<select id="Query" parameterType="com.shopping.domain.Goods"
resultType="com.shopping.domain.Goods">
select id, goodsname, goodsprice, goodscosting, releasedate,
goodscount, goodsdetail, goodsphoto, goodstype, isdelete
from goods
where isdelete = 0
<if test="goodsname != null">
and goodsname = #{goodsname}
</if>
<if test="goodsType != null">
and goodstype = #{goodsType}
</if>
</select> <select id="QueryById" parameterType="int" resultType="com.shopping.domain.Goods">
select id, goodsname, goodsprice, goodscosting, releasedate,
goodscount, goodsdetail, goodsphoto, goodstype, isdelete
from goods
where isdelete = 0 and id = #{id}
</select> </mapper>
3. 业务层设计
本项目业务层只有一个业务类,该类负责调用持久层的UserDao对象,主要完成数据的增删改查及日志记录等操作
3.1 通过Spring装配Service
修改applicationContext.xml文件,添加如下代码:
<!--开启事务的Annotation支持 -->
<tx:annotation-driven transaction-manager="transactionManager"/> <!--配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <!-- 启动对@AspectJ注解的支持 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
3.2 通过Spring装配Log4J
使用spring中的Log4jConfigListener管理log4J。配置如下:
在web.xml中添加如下内容:
<!-- 日志记录 -->
<context-param>
<!-- 日志配置文件路径 -->
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:conf/log4j.properties</param-value>
</context-param> <context-param>
<!-- 日志页面的刷新间隔 -->
<param-name>log4jRefreshInterval</param-name>
<param-value>6000</param-value>
</context-param> <listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
在src/main/resources下新建log4j.properties文件
### set log levels ###
#log4j.rootLogger = debug , stdout , D , E
log4j.rootLogger = debug , stdout , D ### output to the console ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = ${springmvc.root}/WEB-INF/logs/log.log
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
#log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
log4j.appender.stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n ### Output to the log file ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ${springmvc.root}/WEB-INF/logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = WARN
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n ### Save exception information to separate file ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ${springmvc.root}/WEB-INF/logs/error.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = ERROR
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
3.3 创建业务层Service及ServiceImpl
@Service 将一个类声明为业务bean
@Transactional 将一个类中的所有方法或某个方法声明为事务
代码如下:
package com.shopping.service; import java.util.List; import com.shopping.domain.Goods; /**
* @ClassName: GoodsService
* @Description:GoodsService层接口
* @author: zhangzhifei
* @date: 2015年8月20日 上午11:35:05
*/
public interface GoodsService { /**
* @Title: Add
* @Description: 添加商品
* @param goods : 新增商品
* @return : 添加结果 1: 成功 0: 失败
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:38:51
*/
public boolean Add(Goods goods); /**
* @Title: Update
* @Description: 更新商品
* @param goods : 修改后的商品信息
* @return : 更新结果 1: 成功 0: 失败
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:39:07
*/
public boolean Update(Goods goods); /**
* @Title: DeleteById
* @Description: 通过商品ID来删除商品
* @param goodsId : 商品ID
* @return : 删除结果 1: 成功 0: 失败
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:39:10
*/
public boolean DeleteById(int goodsId); /**
* @Title: Query
* @Description: 查询商品
* @param goods : 查询条件,若没有 可以为空
* @return : 查询结果 null or List
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:39:12
*/
public List<Goods> Query(Goods goods); /**
* @Title: queryById
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param id
* @return
* @author: zhangzhifei
* @date: 2015年8月23日 下午4:17:32
*/
public Goods QueryById(int id);
}
package com.shopping.service.impl; import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.shopping.dao.GoodsDao;
import com.shopping.domain.Goods;
import com.shopping.service.GoodsService; /**
* @ClassName: GoodsServiceImpl
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: zhangzhifei
* @date: 2015年8月20日 上午11:37:30
*/
@Transactional
@Service("goodsService")
public class GoodsServiceImpl implements GoodsService{ /**
* @Fields goodsDao : 通过spring注入
*/
@Resource
private GoodsDao goodsDao; /**
* @return goodsDao
*/
public GoodsDao getGoodsDao() {
return goodsDao;
} /**
* @param goodsDao 要设置的 goodsDao
*/
public void setGoodsDao(GoodsDao goodsDao) {
this.goodsDao = goodsDao;
} /**
* <p>Title: Add</p>
* <p>Description: </p>
* @param goods
* @return
* @see com.shopping.service.GoodsService#Add(com.shopping.domain.Goods)
*/
public boolean Add(Goods goods) { boolean a= this.getGoodsDao().Add(goods);
//int b = 3/0;
return a;
} /**
* <p>Title: Update</p>
* <p>Description: </p>
* @param goods
* @return
* @see com.shopping.service.GoodsService#Update(com.shopping.domain.Goods)
*/
public boolean Update(Goods goods) {
return this.getGoodsDao().Update(goods);
} /**
* <p>Title: DeleteById</p>
* <p>Description: </p>
* @param goodsId
* @return
* @see com.shopping.service.GoodsService#DeleteById(int)
*/
public boolean DeleteById(int goodsId) {
return this.getGoodsDao().DeleteById(goodsId);
} /**
* <p>Title: Query</p>
* <p>Description: </p>
* @param goods
* @return
* @see com.shopping.service.GoodsService#Query(com.shopping.domain.Goods)
*/
public List<Goods> Query(Goods goods) {
return this.getGoodsDao().Query(goods);
} /**
* <p>Title: QueryById</p>
* <p>Description: </p>
* @param id
* @return
* @see com.shopping.service.GoodsService#QueryById(int)
*/
@Override
public Goods QueryById(int id) {
return this.getGoodsDao().QueryById(id); }
}
3.4 创建日志记录类LogAspect
@Component 将一个类声明为组件bean
@Aspect 将一个类声明为AOP切面
@Pointcut 声明一个切点
@before 声明前置通知
@After 声明后置通知
@Around 声明环绕通知
@AfterThrowing 声明一个通知,抛出异常并方法结束后执行
package com.shopping.log; import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component; /**
* @ClassName: AopLog
* @Description: AOP日志类
* @author: zhangzhifei
* @date: 2015年8月22日 下午6:47:16
*/
@Component
@Aspect
public class LogAspect { /**
* @Fields logger : Logger变量 记录日志
*/
Logger logger = Logger.getLogger(LogAspect.class); /**
* @Fields strLog : 日志信息
*/
String strLog = null ; /**
* @Title: pointcut
* @Description: 定义切入点 执行impl下的所有方法时 都调用
* @author: zhangzhifei
* @date: 2015年8月22日 下午6:57:39
*/
@Pointcut("execution (* com.shopping.service.impl.*.*(..))")
public void pointcut() { } /**
* @Title: before
* @Description: 前置通知:在某连接点之前执行的通知,但这个通知不能阻止连接点前的执行
* @param jp : 连接点:程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者抛出的异常行为
* @author: zhangzhifei
* @date: 2015年8月22日 下午8:38:08
*/
@Before("pointcut()")
public void before() {
strLog = "log Begining method: " ;
logger.error(strLog);
} /**
* @Title: after
* @Description: 后置通知: 连接点执行后调用
* @param jp : 连接点:程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者抛出的异常行为
* @author: zhangzhifei
* @date: 2015年8月22日 下午6:59:10
*/
@After("pointcut()")
public void after() {
strLog ="doAfter:log Ending method: " ;
logger.error(strLog);
} /**
* @Title: around
* @Description: 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行
* @param point : 当前进程中的连接点
* @return
* @throws Throwable
* @author: zhangzhifei
* @date: 2015年8月22日 下午6:59:32
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long time = System.currentTimeMillis();
Object object = point.proceed();
time = System.currentTimeMillis() - time;
System.out.println("process time: " + time + " ms");
return object;
} /**
* @Title: afterThrowing
* @Description: 抛出异常后通知 : 在方法抛出异常退出时执行的通知。
* @param ex : 异常信息
* @param jp : 连接点:程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者抛出的异常行为
* @author: zhangzhifei
* @date: 2015年8月22日 下午6:59:55
*/
@AfterThrowing(pointcut = "pointcut()", throwing = "ex")
public void afterThrowing(Exception ex) {
strLog ="doAfter:log Ending method: " + "Exception" + ex;
logger.error(strLog);
}
}
4. 表示层设计
4.1 配置Spring MVC框架
本项目将所有web请求全部提交给Spring MVC框架处理,在web.xml中添加如下内容:
<!-- 读取spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:conf/applicationContext.xml;</param-value>
</context-param> <!-- 设计路径变量值 -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>springmvc.root</param-value>
</context-param> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <!-- springMVC核心配置 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:conf/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Spring中的字符集过滤器可以很方便的为我们解决项目中出现的中文乱码问题,使用时需要在web.xml文件中配置一下该过滤器,设置两个重要的参数(encoding和forceEncoding),在web.xml中添加如下内容:
<!-- Spring字符集过滤器 -->
<filter>
<filter-name>SpringEncodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SpringEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在applicationContext.xml文件中添加如下内容:
<!-- 避免IE在ajax请求时,返回json出现下载 -->
<bean id="jacksonMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean> <!-- 访问静态资源 -->
<mvc:resources mapping="/resources/**" location="/WEB-INF/" /> <!-- 有些请求是不需要经过controller层的处理的,可以这么来配置 -->
<mvc:view-controller path="/" view-name="index"/> <!-- 对模型视图添加前后缀 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp">
</bean>
4.2 配置Spring MVC 校验框架
Spring只提供了数据校验接口,但没提供实现,本项目采用Hibernate框架提供的HibernateValidator来进行数据验证,在applicationContext.xml中添加如下内容:
<!-- 为Spring配置校验器 -->
<mvc:annotation-driven validator="validator" /> <!-- 数据类型转换 -->
<bean id="conversion-service" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" /> <!-- 添加校验信息资源文件的声明 -->
<bean id="validatemessageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:conf/validatemessages"/>
<property name="useCodeAsDefaultMessage" value="true" />
<property name="fileEncodings" value="utf-8"/>
<property name="cacheSeconds" value="10"/>
</bean> <!-- 通过验证器引用指定的资源文件 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<!--不设置则默认为classpath下的 ValidationMessages.properties -->
<property name="validationMessageSource" ref="validatemessageSource"/>
</bean>
4.3 新建视图层model
该model主要与页面表单对应,类中为字段添加了约束,代码如下:
具体约束规则,这里不介绍。
package com.shopping.viewmodel; import javax.validation.constraints.Digits;
import javax.validation.constraints.Size; import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.constraints.Range; /**
* @ClassName: Goods
* @Description:商品model 对应数据库商品表
* @author: zhangzhifei
* @date: 2015年8月20日 上午10:19:26
*/
public class VMGoods { /**
* @Fields id : 商品表主键
*/
private int id; /**
* @Fields goodsname : 商品名称
*/
@NotEmpty(message="{goodsname.not.empty}")
private String goodsname; /**
* @Fields goodsprice : 商品价格
*/
@Range(min=0, max=1000, message="{goodsprice.not.inrange}")
private double goodsprice; /**
* @Fields goodscosting : 商品成本
*/
@Range(min=0, max=1000, message="{goodscosting.not.inrange}")
private double goodscosting; /**
* @Fields releaseDate : 发布日期
*/
@NotEmpty(message="{releaseDate.not.empty}")
private String releaseDate; /**
* @Fields goodscount : 商品数量
*/
@Digits(integer=15, fraction=0, message="{goodscount.not.indigits}")
private int goodscount; /**
* @Fields goodsdetail : 商品明细
*/
@Size(min=1, max=1000, message="{goodsdetail.not.insize}")
private String goodsdetail; /**
* @Fields goodsphoto : 商品图片
*/
@NotEmpty(message="{goodsphoto.not.empty}")
private String goodsphoto; /**
* @Fields goodsType : 商品类型
*/
@Size(min=1, max=1000, message="{goodsType.not.insize}")
private String goodsType; /**
* @Fields isDelete : 是否删除
*/
private boolean isDelete;
... ... }
4.4 配置出错信息
将出错信息直接写在类里边不利于国际化,所以本项目另外建了一个国际化资源文件,用于存储校验信息
在conf文件夹下新建validatemessages.properties文件,添加如下内容:
goodsname.not.empty=\u5546\u54C1\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
goodsprice.not.inrange=\u5546\u54C1\u4EF7\u683C\u4E0D\u5728\u8303\u56F4\u5185
goodscosting.not.inrange=\u5546\u54C1\u6210\u672C\u4E0D\u5728\u8303\u56F4\u5185
releaseDate.not.empty=\u65E5\u671F\u4E0D\u80FD\u4E3A\u7A7A
goodscount.not.indigits=\u5546\u54C1\u6570\u91CF\u4E0D\u80FD\u4E3A\u5C0F\u6570
goodsdetail.not.insize=\u5546\u54C1\u8BE6\u60C5\u8D85\u51FA\u8303\u56F4
goodsphoto.not.empty=\u5546\u54C1\u56FE\u7247\u4E0D\u80FD\u4E3A\u7A7A
goodsType.not.insize=\u5546\u54C1\u7C7B\u522B\u957F\u5EA6\u592A\u957F
4.5 新建Controller对象
该对象用于处理各种请求:
@Controller 将一个对象声明为controller bean
@RequestMapping 映射请求路径
@Resource 声明该属性值由Spring注入
@RequestParam 将请求数据与参数绑定
@Valid 声明校验
@ModelAttribute 绑定请求对象
package com.shopping.controller; import java.util.List; import javax.annotation.Resource;
import javax.validation.Valid; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import com.shopping.Convert.Converter;
import com.shopping.domain.Goods;
import com.shopping.service.GoodsService;
import com.shopping.viewmodel.VMGoods; /**
* @ClassName: GoodsController
* @Description:TODO(这里用一句话描述这个类的作用)
* @author: zhangzhifei
* @date: 2015年8月20日 下午12:01:11
*/
@Controller
@RequestMapping("/goods")
public class GoodsController { /**
* @Fields goodsService : TODO(用一句话描述这个变量表示什么)
*/
@Resource(name="goodsService")
public GoodsService goodsService; @RequestMapping("/AddGoods")
public String AddGoods(ModelMap modelMap) {
modelMap.addAttribute("goods", new VMGoods());
return "AddGoods";
} /**
* @Title: SearchGoods
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param goodsname
* @param goodsType
* @return
* @author: zhangzhifei
* @date: 2015年8月20日 下午5:00:35
*/
@RequestMapping("/search")
public String SearchGoods(@RequestParam(value="goodsname")String goodsname,
@RequestParam(value="goodsType")String goodsType,
ModelMap modelMap){
List<Goods> goodslist = goodsService.Query(new Goods());
modelMap.addAttribute("goodslist",goodslist);
return "SearchResult";
} /**
* @Title: Add
* @Description: 处理添加货物请求
* @param goods
* @param bindingResult
* @return
* @author: zhangzhifei
* @date: 2015年8月20日 下午5:00:26
*/
@RequestMapping("/add")
public String Add(@Valid @ModelAttribute("goods")VMGoods vmgoods ,
BindingResult error, ModelMap model){
if(error.hasErrors()){
return "AddGoods";
}
else{
Goods goods = Converter.VMGoodsToGoods(vmgoods);
if(goodsService.Add(goods) == true){
model.addAttribute("result", 1);
}
else{
model.addAttribute("result", 0);
}
return "AddGoods";
}
} /**
* @Title: Delete
* @Description: 删除商品
* @param id
* @param modelMap
* @return
* @author: zhangzhifei
* @date: 2015年8月23日 下午4:09:24
*/
@RequestMapping("/delete")
public String Delete(@RequestParam(value="id")int id,ModelMap modelMap){
if(goodsService.DeleteById(id) == true){
modelMap.addAttribute("result", 1);
}
else{
modelMap.addAttribute("result", 0);
} List<Goods> goodslist = goodsService.Query(new Goods());
modelMap.addAttribute("goodslist",goodslist);
return "SearchResult";
} /**
* @Title: Update
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param id
* @param modelMap
* @return
* @author: zhangzhifei
* @date: 2015年8月23日 下午4:22:49
*/
@RequestMapping("/update")
public String Update(int id, ModelMap modelMap){
Goods goods = new Goods();
goods = goodsService.QueryById(id);
modelMap.addAttribute("goods",goods);
return "UpdateGoods";
} /**
* @Title: UpdateGoods
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param goods
* @param modelMap
* @return
* @author: zhangzhifei
* @date: 2015年8月23日 下午4:22:58
*/
@RequestMapping("/UpdateGoods")
public String UpdateGoods(Goods goods1, ModelMap modelMap){
goodsService.Update(goods1);
List<Goods> goodslist = goodsService.Query(new Goods());
modelMap.addAttribute("goodslist",goodslist);
return "SearchResult";
}
}
4.6 新建页面视图
AddGoods.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 prefix="sf" uri="http://www.springframework.org/tags/form" %>
<%@ page isELIgnored="false"%>
<!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>
<c:if test="${result == 0}">
<c:out value="添加成功"></c:out>
</c:if>
<sf:form action="${pageContext.request.contextPath}/goods/add" method="post" modelAttribute="goods">
商品名称: <sf:input type="text" path="goodsname" autocomplete="off"></sf:input>
<sf:errors path="goodsname"></sf:errors><br/>
商品价格:
<sf:input type="text" path="goodsprice" autocomplete="off"></sf:input>
<sf:errors path="goodsprice"></sf:errors><br /> 商品成本:
<sf:input type="text" path="goodscosting" autocomplete="off"></sf:input>
<sf:errors path="goodscosting"></sf:errors><br /> 数量:
<sf:input type="text" path="goodscount" autocomplete="off"></sf:input>
<sf:errors path="goodscount"></sf:errors><br /> 发布日期:
<sf:input type="text" path="releaseDate" autocomplete="off"></sf:input>
<sf:errors path="releaseDate"></sf:errors><br /> 商品图片:
<sf:input type="text" path="goodsphoto" autocomplete="off"></sf:input>
<sf:errors path="goodsphoto"></sf:errors><br /> 商品类别:
<sf:input type="text" path="goodsType" autocomplete="off"></sf:input>
<sf:errors path="goodsType"></sf:errors><br />
详情:
<sf:textarea path="goodsdetail" value="" cols="80" rows="5"></sf:textarea>
<sf:errors path="goodsdetail"></sf:errors><br /> <input type="submit" value="提交" />
</sf:form>
</body>
</html>
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
<%@ page isELIgnored="false"%>
<!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>Test Spring MVC And Mybatis</title>
</head>
<body> <form action="${pageContext.request.contextPath}/goods/search"
method="post">
商品名称:<input type="text" name="goodsname" />
商品种类:<input type="text" name="goodsType" />
<input type="submit" value="搜索">
<input type="button"
onclick="javascript:location.href='${pageContext.request.contextPath}/goods/AddGoods'" value="添加商品">
</form> </body>
</html>
SearchResult.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page isELIgnored="false"%>
<!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>Test Spring MVC And Mybatis</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/goods/search"
method="post">
商品名称:<input type="text" name="goodsname" /> 商品种类:<input type="text"
name="goodsType" />
<input type="submit" value="搜索">
</form>
<table>
<tr>
<th>商品名称</th>
<th>商品种类</th>
<th>商品价格</th>
<th>商品成本</th>
<th>数量</th>
<th>发布日期</th>
<th>商品图片</th>
<th>详情</th>
<th>操作</th>
</tr>
<c:if test="${goodslist == null}">
<tr> <td colspan="9"><c:out value="货物未找到!!!"/></td></tr>
</c:if>
<c:if test="${goodslist != null}">
<c:forEach var = "goods" items="${goodslist}">
<tr>
<td><c:out value="${goods.goodsname}"/></td>
<td><c:out value="${goods.goodsType}"/></td>
<td><c:out value="${goods.goodsprice}"/></td>
<td><c:out value="${goods.goodscosting}"/></td>
<td><c:out value="${goods.goodscount}"/></td>
<td><c:out value="${goods.releaseDate}"/></td>
<td><c:out value="${goods.goodsphoto}"/></td>
<td><c:out value="${goods.goodsdetail}"/></td> <td>
<input type="button" value="修改" onclick="javascript:location.href='${pageContext.request.contextPath}/goods/update?id=${goods.id}'">
<input type="button" value="删除" onclick="javascript:location.href='${pageContext.request.contextPath}/goods/delete?id=${goods.id}'">
</td>
</tr>
</c:forEach>
</c:if>
</table>
</body>
</html>
UpdateGoods.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page isELIgnored="false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登陆</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/goods/UpdateGoods" method="post">
<input type="hidden" name="id" value="${goods.id}">
商品名称:<input type="text" value="${goods.goodsname}" name="goodsname"><br/>
商品价格:<input type="text" value="${goods.goodsprice}" name="goodsprice"><br/>
商品成本:<input type="text" value="${goods.goodscosting}" name="goodscosting"><br/>
数量:<input type="text" value="${goods.goodscount}" name="goodscount"><br/>
发布日期:<input type="text" value="${goods.releaseDate}" name="releaseDate"><br/>
商品图片:<input type="text" value="${goods.goodsphoto}" name="goodsphoto"><br/>
商品类别:<input type="text" value="${goods.goodsType}"name="goodsType"><br/>
详情:<textarea name="goodsdetail" value="${goods.goodsdetail}" cols="80"rows="5"></textarea><br/>
<input type="submit" value="提交"/>
</form>
</body>
5. 运行工程