1. 下载spring包,网址如下:
http://www.springframework.org/download.html
解压后的目录中包含了dist、lib等子目录
2. 在jbuilder2005中增加spring库,选择菜单tools-configure-libraries,在弹出的对话框中点击new按钮,输入spring库的名称:spring,点击add按钮,将dist目录中的所有jar文件增加到spring库中
3. 新建工程文件,选菜单file-new project,给工程文件取名为myproject
设置工程文件的属性,选菜单project-project properties,选择tomcat作为服务器,将spring库加入path/required libraries。因为例子中用到了log4j,将包含了log4j的库加入path/required libraries,注意到lib目录下有两个子目录log4j和jakarta-commons,它们的用法是不同的,如下面的代码片断所示:
log4j
| import org.apache.log4j.level; import org.apache.log4j.logger; public class springappcontroller implements controller { /** logger for this class and subclasses */ static logger logger = logger.getlogger(springappcontroller.class); jakarta-commons import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; public class springappcontroller implements controller { /** logger for this class and subclasses */ protected final log logger = logfactory.getlog(getclass()); |
4. 新建web模块,选菜单file-new,给web模块取名为springapp
5. 新建hello.jsp文件如下:
| <%@ page contenttype="text/html; charset=big5" %> <html> <head><title>example :: spring application</title></head> <body> <h1>hello - spring application</h1> <p>greetings.</p> </body> </html> |
6. 新建类文件springappcontroller.java如下:
| package spring; import org.springframework.web.servlet.mvc.controller; import org.springframework.web.servlet.modelandview; import javax.servlet.servletexception; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; //import org.apache.commons.logging.log; //import org.apache.commons.logging.logfactory; import org.apache.log4j.level; import org.apache.log4j.logger; public class springappcontroller implements controller { /** logger for this class and subclasses */ // protected final log logger = logfactory.getlog(getclass()); static logger logger = logger.getlogger(springappcontroller.class); public modelandview handlerequest(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { logger.info("springappcontroller - returning hello view"); return new modelandview("hello.jsp"); } } |
7. 修改web.xml文件
| <?xml version="1.0" encoding="utf-8"?> <!doctype web-app public '-//sun microsystems, inc.//dtd web application 2.3//en' 'http://java.sun.com/dtd/web-app_2_3.dtd'> <web-app> <servlet> <servlet-name>springapp</servlet-name> <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springapp</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file> index.jsp </welcome-file> </welcome-file-list> </web-app> |
8. 在web-inf目录中新建springapp-servlet.xml文件如下
| <?xml version="1.0" encoding="utf-8"?> <!doctype beans public "-//spring//dtd bean//en" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- - application context definition for "springapp" dispatcherservlet. --> <beans> <bean id="springappcontroller" class="spring.springappcontroller"/> <bean id="urlmapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping"> <property name="mappings"> <props> <prop key="/hello.htm">springappcontroller</prop> </props> </property> </bean> </beans> |
9. 在web-inf目录中新建log4j.properties文件如下:
| log4j.rootcategory=info, stdout, logfile log4j.appender.stdout=org.apache.log4j.consoleappender log4j.appender.stdout.layout=org.apache.log4j.patternlayout log4j.appender.stdout.layout.conversionpattern=%d %p [%c] - <%m>%n log4j.appender.logfile=org.apache.log4j.rollingfileappender log4j.appender.logfile.file=springapp.log log4j.appender.logfile.maxfilesize=512kb # keep three backup files log4j.appender.logfile.maxbackupindex=3 log4j.appender.logfile.layout=org.apache.log4j.patternlayout #pattern to output : date priority [category] - <message>line_separator log4j.appender.logfile.layout.conversionpattern=%d %p [%c] - <%m>%n |
10. 设置web模块springapp的属性content,加入文件log4j.properties,因为classes目录是自动产生的,这一步是为了把文件log4j.properties加到classes目录。
11. 设置run configuration,选菜单run-configurations,新建一个run configuration,type选server,launch uri设置为:/springapp/hello.htm,给它取名为hello
12. 运行,你会在messages窗口中看到如下信息:
?y??: server startup in 9253 ms
2004-11-05 15:05:00,585 info [spring.springappcontroller] - <springappcontroller - returning hello view>
2004/11/5 下午 03:05:00 org.springframework.web.servlet.view.abstractcachingviewresolver resolveviewname
?y??: cached view 'hello.jsp'
在myproject/tomcat/springapp.log文件中增加了一行如下所示:
2004-11-05 15:11:32,348 info [spring.springappcontroller] - <springappcontroller - returning hello view>
这说明你已成功建立了基本的spring应用。
jstl的支持,设置工程文件的属性,选菜单project-project properties,将jstl库加入path/required libraries。
14. 改进前面的例子,改进的文件如下:
增加“header”文件include.jsp,这是一些jsp文件的公用部分,这样可以使得开发和维护更容易。所有jsp文件放在web-inf/jsp目录下,为的是只有controller可以访问view。
springapp/war/web-inf/jsp/include.jsp
| <%@ page session="false"%> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> |
利用jstl,<c:redirect>将页面重定向到controller,这样就建立了index.jsp和应用架构的联系。
springapp/war/index.jsp
| <%@ include file="/web-inf/jsp/include.jsp" %> <%-- redirected because we can't set the welcome page to a virtual url. --%> <c:redirect url="/hello.htm"/> |
利用jstl的<c:out>标记,把从model提取的,传递给view的当前日期和时间作为输出。
springapp/war/web-inf/jsp/hello.jsp
| <%@ include file="/web-inf/jsp/include.jsp" %> <html> <head><title>hello :: spring application</title></head> <body> <h1>hello - spring application</h1> <p>greetings, it is now <c:out value="${now}"/> </p> </body> </html> |
在springappcontroller.java中增加包含了当前日期和时间的string作为model
springapp/src/springappcontroller.java
| import org.springframework.web.servlet.mvc.controller; import org.springframework.web.servlet.modelandview; import javax.servlet.servletexception; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; public class springappcontroller implements controller { /** logger for this class and subclasses */ protected final log logger = logfactory.getlog(getclass()); public modelandview handlerequest(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { string now = (new java.util.date()).tostring(); logger.info("returning hello view with " + now); return new modelandview("web-inf/jsp/hello.jsp", "now", now); } } |
15. 浏览改进后的结果http://localhost:8080/springapp,首先访问index.jsp,然后重定向到hello.htm,接著把控制交给controller,controller把日期和时间传送给view。
只能在浏览器这样测试。在jbuilder2005中设置run configuration不能访问http://localhost:8080/springapp,但可以访问http://localhost:8080/springapp/index.jsp
在上面的例子中,controller指定了view的完全路径,使得controller和view之间存在不必要的依赖。为了移出这种依赖,我们可以用类resourcebundleviewresolver 和 a simpleurlhandlermapping在属性文件中定义这种依赖,对于简单的情形,我们也可以利用internalresourceviewresolver设置前缀和后缀,下面就用第二种方法。修改文件springapp-servlet.xml包含viewresolver设置,我们还选择使用jstlview,这使得我们可以结合使用jstl和message resource bundles,因此可以支持国际化。
springapp/war/web-inf/springapp-servlet.xml
| <?xml version="1.0" encoding="utf-8"?> <!doctype beans public "-//spring//dtd bean//en" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- - application context definition for "springapp" dispatcherservlet. --> <beans> <bean id="springappcontroller" class="springappcontroller"/> <bean id="urlmapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping"> <property name="mappings"> <props> <prop key="/hello.htm">springappcontroller</prop> </props> </property> </bean> <bean id="viewresolver" class="org.springframework.web.servlet.view.internalresourceviewresolver"> <property name="viewclass"><value>org.springframework.web.servlet.view.jstlview</value></property> <property name="prefix"><value>/web-inf/jsp/</value></property> <property name="suffix"><value>.jsp</value></property> </bean> </beans> |
现在,我们就可以移出controller中view名称的前缀和后缀了。
| springapp/src/springappcontroller.java import org.springframework.web.servlet.mvc.controller; import org.springframework.web.servlet.modelandview; import javax.servlet.servletexception; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; public class springappcontroller implements controller { /** logger for this class and subclasses */ protected final log logger = logfactory.getlog(getclass()); public modelandview handlerequest(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { string now = (new java.util.date()).tostring(); logger.info("returning hello view with " + now); return new modelandview("hello", "now", now); } } |
这样修改后的例子应该仍能运行。
16. 增加商业逻辑类
为了分开web逻辑和商业逻辑,我们建立两个不同的包,web和bus
springapp/src/bus/product.java
| package bus; import java.io.serializable; public class product implements serializable { private string description; private double price; public void setdescription(string s) { description = s; } public string getdescription() { return description; } public void setprice(double d) { price = d; } public double getprice() { return price; } } |
springapp/src/bus/productmanager.java
| package bus; import java.io.serializable; import java.util.list; public class productmanager implements serializable { private list products; public void setproducts(list p) { products = p; } public list getproducts() { return products; } } |
修改springappcontroller.java
springapp/src/web/springappcontroller.java
| package web; import org.springframework.web.servlet.mvc.controller; import org.springframework.web.servlet.modelandview; import javax.servlet.servletexception; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import java.util.map; import java.util.hashmap; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; import bus.product; import bus.productmanager; public class springappcontroller implements controller { /** logger for this class and subclasses */ protected final log logger = logfactory.getlog(getclass()); private productmanager prodman; public modelandview handlerequest(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { string now = (new java.util.date()).tostring(); logger.info("returning hello view with " + now); map mymodel = new hashmap(); mymodel.put("now", now); mymodel.put("products", getproductmanager().getproducts()); return new modelandview("hello", "model", mymodel); } public void setproductmanager(productmanager pm) { prodman = pm; } public productmanager getproductmanager() { return prodman; } } |
17. 修改view以便显示商业数据,增加对message bundle的支持
springapp/war/web-inf/jsp/hello.jsp
| <%@ include file="/web-inf/jsp/include.jsp" %> <html> <head><title><fmt:message key="title"/></title></head> <body> <h1><fmt:message key="heading"/></h1> <p><fmt:message key="greeting"/> <c:out value="${model.now}"/> </p> <h3>products</h3> <c:foreach items="${model.products}" var="prod"> <c:out value="${prod.description}"/> <i>$<c:out value="${prod.price}"/></i> </c:foreach> </body> </html> |
18. 增加一些测试数据
我们现在还不打算增加代码,从数据库装载商业对象。我们只springapp-servlet.xml中增加bean和messagesource设置,提供一些测试数据和对messages resource bundle的支持。
springapp/war/web-inf/springapp-servlet.xml
| <?xml version="1.0" encoding="utf-8"?> <!doctype beans public "-//spring//dtd bean//en" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- - application context definition for "springapp" dispatcherservlet. --> <beans> <bean id="springappcontroller" class="web.springappcontroller"> <property name="productmanager"> <ref bean="prodman"/> </property> </bean> <bean id="prodman" class="bus.productmanager"> <property name="products"> <list> <ref bean="product1"/> <ref bean="product2"/> <ref bean="product3"/> </list> </property> </bean> <bean id="product1" class="bus.product"> <property name="description"><value>lamp</value></property> <property name="price"><value>5.75</value></property> </bean> <bean id="product2" class="bus.product"> <property name="description"><value>table</value></property> <property name="price"><value>75.25</value></property> </bean> <bean id="product3" class="bus.product"> <property name="description"><value>chair</value></property> <property name="price"><value>22.79</value></property> </bean> <bean id="messagesource" class="org.springframework.context.support.resourcebundlemessagesource"> <property name="basename"><value>messages</value></property> </bean> <bean id="urlmapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping"> <property name="mappings"> <props> <prop key="/hello.htm">springappcontroller</prop> </props> </property> </bean> <bean id="viewresolver" class="org.springframework.web.servlet.view.internalresourceviewresolver"> <property name="viewclass"><value>org.springframework.web.servlet.view.jstlview</value></property> <property name="prefix"><value>/web-inf/jsp/</value></property> <property name="suffix"><value>.jsp</value></property> </bean> </beans> |
19. 增加message bundle
springapp/war/web-inf/classes/messages.properties
| title=springapp heading=hello :: springapp greeting=greetings, it is now |
20. 浏览改进后的结果http://localhost:8080/springapp
实现数据库持久层
21. 设置hsql数据库,在jbuilder2005中增加hsql库,选择菜单tools-configure-libraries,在弹出的对话框中点击new按钮,输入hsql库的名称:hsql,点击add按钮,将lib/hsqldb目录下的文件hsqldb.jar增加到hsql库中。
选择菜单enterprise-enterprise setup,在弹出的对话框中选择database drivers,按add按钮增加hsql库。
选择菜单tools-database pilot,然后选择菜单files-new输入driver:org.hsqldb.jdbcdriver,url:jdbc:hsqldb:db/test, 双击hsqldb:db/test,输入username:sa,不必输入passsword。输入如下的sql语句并执行
| create table products ( id integer not null primary key, description varchar(255), price decimal(15,2) ); create index products_description on products(description); insert into products (id, description, price) values(1, 'lamp', 5.78); insert into products (id, description, price) values(2, 'table', 75.29); insert into products (id, description, price) values(3, 'chair', 22.81); |
这样就会在jbuilder_home/bin目录下创建一个目录db,存放了数据库test的数据
22. 创建jdbc dao (data access object)实现
springapp/src/db/productmanagerdao.java
| package db; import bus.product; import java.util.list; public interface productmanagerdao { public list getproductlist(); public void increaseprice(product prod, int pct); } |
springapp/src/db/productmanagerdaojdbc.java
| package db; import bus.product; import java.util.list; import java.sql.resultset; import java.sql.sqlexception; import java.sql.types; import javax.sql.datasource; import org.apache.commons.logging.log; import org.apache.commons.logging.logfactory; import org.springframework.jdbc.object.mappingsqlquery; import org.springframework.jdbc.object.sqlupdate; import org.springframework.jdbc.core.sqlparameter; public class productmanagerdaojdbc implements productmanagerdao { /** logger for this class and subclasses */ protected final log logger = logfactory.getlog(getclass()); private datasource ds; public list getproductlist() { logger.info("getting products!"); productquery pq = new productquery(ds); return pq.execute(); } public void increaseprice(product prod, int pct) { logger.info("increasing price by " + pct + "%"); sqlupdate su = new sqlupdate(ds, "update products set price = price * (100 + ?) / 100 where id = ?"); su.declareparameter(new sqlparameter("increase", types.integer)); su.declareparameter(new sqlparameter("id", types.integer)); su.compile(); object[] oa = new object[2]; oa[0] = new integer(pct); oa[1] = new integer(prod.getid()); int count = su.update(oa); logger.info("rows affected: " + count); } public void setdatasource(datasource ds) { this.ds = ds; } class productquery extends mappingsqlquery { productquery(datasource ds) { super(ds, "select id, description, price from products"); compile(); } protected object maprow(resultset rs, int rownum) throws sqlexception { product prod = new product(); prod.setid(rs.getint("id")); prod.setdescription(rs.getstring("description")); prod.setprice(new double(rs.getdouble("price"))); return prod; } } } |
springapp/src/bus/product.java
| package bus; import java.io.serializable; public class product implements serializable { private int id; private string description; private double price; public void setid(int i) { id = i; } public int getid() { return id; } public void setdescription(string s) { description = s; } public string getdescription() { return description; } public void setprice(double d) { price = d; } public double getprice() { return price; } } |
springapp/src/test/testproductmanagerdaojdbc.java
| package tests; import java.util.list; import java.util.arraylist; import junit.framework.testcase; import org.springframework.jdbc.datasource.drivermanagerdatasource; import db.productmanagerdaojdbc; import bus.product; public class testproductmanagerdaojdbc extends testcase { private productmanagerdaojdbc pmdao; public void setup() { pmdao = new productmanagerdaojdbc(); drivermanagerdatasource ds = new drivermanagerdatasource(); ds.setdriverclassname("org.hsqldb.jdbcdriver"); ds.seturl("jdbc:hsqldb:db/test"); ds.setusername("sa"); ds.setpassword(""); pmdao.setdatasource(ds); } public void testgetproductlist() { list l = pmdao.getproductlist(); product p1 = (product) l.get(0); assertequals("lamp", p1.getdescription()); product p2 = (product) l.get(1); assertequals("table", p2.getdescription()); } public void testincreaseprice() { list l1 = pmdao.getproductlist(); product p1 = (product) l1.get(0); assertequals(new double("5.78"), p1.getprice()); pmdao.increaseprice(p1, 10); list l2 = pmdao.getproductlist(); product p2 = (product) l2.get(0); assertequals(new double("6.36"), p2.getprice()); } } |
23. 修改web应用使其使用数据库持久层
springapp/src/bus/productmanager.java
| package bus; import java.io.serializable; import java.util.listiterator; import java.util.list; import db.productmanagerdao; public class productmanager implements serializable { private productmanagerdao pmd; private list products; public void setproductmanagerdao(productmanagerdao pmd) { this.pmd = pmd; } /* public void setproducts(list p) { products = p; } */ public list getproducts() { products = pmd.getproductlist(); return products; } public void increaseprice(int pct) { listiterator li = products.listiterator(); while (li.hasnext()) { product p = (product) li.next(); /* double newprice = p.getprice().doublevalue() * (100 + pct)/100; p.setprice(new double(newprice)); */ pmd.increaseprice(p, pct); } } } |
springapp/war/web-inf/springapp-servlet.xml
| <?xml version="1.0" encoding="utf-8"?> <!doctype beans public "-//spring//dtd bean//en" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- - application context definition for "springapp" dispatcherservlet. --> <beans> <!-- controller for the initial "hello" page --> <bean id="springappcontroller" class="web.springappcontroller"> <property name="productmanager"> <ref bean="prodman"/> </property> </bean> <!-- validator and form controller for the "price increase" page --> <bean id="priceincreasevalidator" class="bus.priceincreasevalidator"/> <bean id="priceincreaseform" class="web.priceincreaseformcontroller"> <property name="sessionform"><value>true</value></property> <property name="commandname"><value>priceincrease</value></property> <property name="commandclass"><value>bus.priceincrease</value></property> <property name="validator"><ref bean="priceincreasevalidator"/></property> <property name="formview"><value>priceincrease</value></property> <property name="successview"><value>hello.htm</value></property> <property name="productmanager"> <ref bean="prodman"/> </property> </bean> <bean id="datasource" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname"><value>org.hsqldb.jdbcdriver</value></property> <property name="url"> <value>jdbc:hsqldb:/home/trisberg/workspace/springapp/db/test</value> </property> <property name="username"><value>sa</value></property> <property name="password"><value></value></property> </bean> <bean id="prodmandao" class="db.productmanagerdaojdbc"> <property name="datasource"> <ref bean="datasource"/> </property> </bean> <bean id="prodman" class="bus.productmanager"> <property name="productmanagerdao"> <ref bean="prodmandao"/> </property> <!-- <property name="products"> <list> <ref bean="product1"/> <ref bean="product2"/> <ref bean="product3"/> </list> </property> --> </bean> <!-- <bean id="product1" class="bus.product"> <property name="description"><value>lamp</value></property> <property name="price"><value>5.75</value></property> </bean> <bean id="product2" class="bus.product"> <property name="description"><value>table</value></property> <property name="price"><value>75.25</value></property> </bean> <bean id="product3" class="bus.product"> <property name="description"><value>chair</value></property> <property name="price"><value>22.79</value></property> </bean> --> <bean id="messagesource" class="org.springframework.context.support.resourcebundlemessagesource"> <property name="basename"><value>messages</value></property> </bean> <bean id="urlmapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping"> <property name="mappings"> <props> <prop key="/hello.htm">springappcontroller</prop> <prop key="/priceincrease.htm">priceincreaseform</prop> </props> </property> </bean> <bean id="viewresolver" class="org.springframework.web.servlet.view.internalresourceviewresolver"> <property name="viewclass"> <value>org.springframework.web.servlet.view.jstlview</value> </property> <property name="prefix"><value>/web-inf/jsp/</value></property> <property name="suffix"><value>.jsp</value></property> </bean> </beans> |
springapp/src/tests/mockproductmanagerdaoimpl.java
| package tests; import bus.product; import java.util.list; import db.productmanagerdao; import bus.product; public class mockproductmanagerdaoimpl implements productmanagerdao { private list products; public void setproducts(list p) { products = p; } public list getproductlist() { return products; } public void increaseprice(product prod, int pct) { double newprice = prod.getprice().doublevalue() * (100 + pct)/100; prod.setprice(new double(newprice)); } } |
springapp/src/tests/web-inf/springapp-servlet.xml
| <?xml version="1.0" encoding="utf-8"?> <!doctype beans public "-//spring//dtd bean//en" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- - application context definition for "springapp" dispatcherservlet. --> <beans> <bean id="springappcontroller" class="web.springappcontroller"> <property name="productmanager"> <ref bean="prodman"/> </property> </bean> <bean id="prodmandao" class="tests.mockproductmanagerdaoimpl"> <property name="products"> <list> <ref bean="product1"/> <ref bean="product2"/> <ref bean="product3"/> </list> </property> </bean> <bean id="prodman" class="bus.productmanager"> <property name="productmanagerdao"> <ref bean="prodmandao"/> </property> <!-- <property name="products"> <list> <ref bean="product1"/> <ref bean="product2"/> <ref bean="product3"/> </list> </property> --> </bean> <bean id="product1" class="bus.product"> <property name="description"><value>lamp</value></property> <property name="price"><value>5.75</value></property> </bean> <bean id="product2" class="bus.product"> <property name="description"><value>table</value></property> <property name="price"><value>75.25</value></property> </bean> <bean id="product3" class="bus.product"> <property name="description"><value>chair</value></property> <property name="price"><value>22.79</value></property> </bean> </beans> |
springapp/src/tests/testproductmanager .java
| package tests; import java.util.list; import java.util.arraylist; import junit.framework.testcase; import db.productmanagerdao; import bus.productmanager; import bus.product; public class testproductmanager extends testcase { private productmanager pm; public void setup() { pm = new productmanager(); product p = new product(); p.setdescription("chair"); p.setprice(new double("20.50")); arraylist al = new arraylist(); al.add(p); p = new product(); p.setdescription("table"); p.setprice(new double("150.10")); al.add(p); /* pm.setproducts(al); */ mockproductmanagerdaoimpl pmdao = new mockproductmanagerdaoimpl(); pmdao.setproducts(al); pm.setproductmanagerdao(pmdao); pm.getproducts(); } public void testgetproducs() { list l = pm.getproducts(); product p1 = (product) l.get(0); assertequals("chair", p1.getdescription()); product p2 = (product) l.get(1); assertequals("table", p2.getdescription()); } public void testincreaseprice() { pm.increaseprice(10); list l = pm.getproducts(); product p = (product) l.get(0); assertequals(new double("22.55"), p.getprice()); p = (product) l.get(1); assertequals(new double("165.11"), p.getprice()); } } |
闽公网安备 35060202000074号