一寸光阴一寸金
AXIS学习笔记
前天头告诉我用SOAP WEB服务开发一个客户程序,用来与企业内部的ERP进行交互。晚上赶快找相关的资料猛看,总算对SOAP有了一定的认识。干程序员这行真不容易,好象得不停地学习新东西,一不小心就被淘汰:(不过学习也是个很有意思的事情。好了,废话少说,让我们开始吧。
一、软件环境
1、axis-1_2 (从apache网站下载最新axis-bin-1_2.zip解压即可)
2、Tomcat5.0
3、JDK5.0
二、相关配置
1、在你的%TOMCAT_HOME%\common\lib下需要加入三个包 activation.jar、mail.jar、tools.jar
2、环境变量设置
AXIS_HOME 即axis-bin-1_2.zip解压的目录(我的是在F:\soap\axis-1_2)
AXIS_LIB 即 %AXIS_HOME%\lib
AXISCLASSPATH 即 %AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery-0.2.jar;%AXIS_LIB%\commons-logging-1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar;也就是把%AXIS_LIB%下所用JAR文件都导入
三、实验一下
在%AXIS_HOME%\webapps下找到axis文件夹,将其整个拷贝到%TOMCAT_HOME%\webapps下,启动
Tomcat,打开浏览器访问http://localhost:8080/axis/,出现以下页面说明你配置成功了。很简单吧:)
四、发布我们的第一个程序
第一个程序简单的返回HELLO WORLD!
HelloWorld.java
public class HelloWorld {
public String sayHello()
{
return "HELLO WORLD!";
}
}
我们的第一种发布方式:
将HelloWorld.java拷贝到%TOMCAT_HOME%\webapps\axis下,然后将其改名为HelloWorld.jws,这样AXIS就自然将其发布了。现在写个客户端程序访问一下:
TestClient.java
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.rpc.ParameterMode;
public class TestClient
{
public static void main(String [] args) throws Exception {
String endpoint = "http://localhost:" +"8080"+ "/axis/HelloWorld.jws";//指明服务所在位置
Service service = new Service(); //创建一个Service实例,注意是必须的!
Call call = (Call) service.createCall();//创建Call实例,也是必须的!
call.setTargetEndpointAddress( new java.net.URL(endpoint) );//为Call设置服务的位置
call.setOperationName( "sayHello" );//注意方法名与HelloWorld.java中一样!!
String res = (String) call.invoke( new Object[] {} );//返回String,没有传入参数
System.out.println( res );
}
}
我的测试是在jbuilder2005中,注意项目中要导入其自带的AXIS包(当然应该把其中JAR文件替换一下),可以看到程序返回了 "HELLO WORLD!"
可以看到在AXIS里发布服务其实是一件很容易的事,这是因为这个服务很简单的原因:)下面我们介绍第二种发布方式,这是常用的。
我们的第二种发布方式:
1、将HelloWorld.java编译成HelloWorld.class,放到%TOMCAT_HOME%\webapps\axis\WEB-INF\classes
下
2、在%TOMCAT_HOME%\webapps\axis\WEB-INF下新建deploy.wsdd文件,即SOAP服务发布描述文件
deploy.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="" target="_blank">http://xml.apache.org/axis/wsdd/providers/java">
<service name="HelloWorld" provider="java:RPC">
<parameter name="className" value="HelloWorld"/>
<parameter name="allowedMethods" value="sayHello"/>
</service>
</deployment>
在DOS下转换目录到%TOMCAT_HOME%\webapps\axis\WEB-INF,命令:
java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.wsdd
你会发现目录下多了一个server-config.wsdd文件,这就是AXIS的配置文件,以后所有的服务发布描述都会在里面找到。(当然,你可以直接修改它,不用再写deploy.wsdd)然后打开浏览器http://localhost:8080/axis/servlet/AxisServlet,你就会看到你的服务已发布
同样用客户端程序访问一下:(注意和上边的差别!!)
HelloClient.java
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
public class HelloClient
{
public static void main(String [] args) throws Exception {
String endpoint = "http://localhost:" +"8080"+ "/axis/services/HelloWorld";//注意!差别仅仅在这里!!
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName("sayHello" );
String res = (String) call.invoke( new Object[] {} );
System.out.println( res );
}
}
好了,相信你对AXIS已有了大致的了解。接下来将会涉及到传参数、JAVABEAN对象,及AXIS的安全问题,下次再说吧:)也欢迎和我,一个快乐的JAVA程序员,联系:)ronghao100@hotmail.com
++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(二)使用Handler来增强Web服务的功能
Handler的基本概念
J2EE Web 服务中的Handler技术特点非常像Servlet技术中的Filter。我们知道,在Servlet中,当一个HTTP到达服务端时,往往要经过多个Filter对请求进行过滤,然后才到达提供服务的Servlet,这些Filter的功能往往是对请求进行统一编码,对用户进行认证,把用户的访问写入系统日志等。相应的,Web服务中的Handler通常也提供一下的功能:
对客户端进行认证、授权;
把用户的访问写入系统日志;
对请求的SOAP消息进行加密,解密;
为Web Services对象做缓存。
SOAP消息Handler能够访问代表RPC请求或者响应的SOAP消息。在JAX-RPC技术中,SOAP消息Handler可以部署在服务端,也可以在客户端使用。
下面我们来看一个典型的SOAP消息Handler处理顺序:
某个在线支付服务需要防止非授权的用户访问或者撰改服务端和客户端传输的信息,从而使用消息摘要(Message Digest)的方法对请求和响应的SOAP消息进行加密。当客户端发送SOAP消⑹保?突Ф说?andler把请求消息中的某些敏感的信息(如信用卡密码)进行加密,然后把加密后的SOAP消息传输到服务端;服务端的SOAP消息Handler截取客户端的请求,把请求的SOAP 消息进行解密,然后把解密后的SOAP消息派发到目标的Web服务端点。
Apache axis是我们当前开发Web服务的较好的选择,使用axisWeb服务开发工具,可以使用Handler来对服务端的请求和响应进行处理。典型的情况下,请求传递如图1所示。
图1 SOAP消息的传递顺序
在图中,轴心点(pivot point)是Apache与提供程序功能相当的部分,通过它来和目标的Web服务进行交互,它通常称为Provider。axis中常用的Provider有Java:RPC,java:MSG,java:EJB。一个Web服务可以部署一个或者多个Handler。
Apache axis中的Handler体系结构和JAX-RPC 1.0(JSR101)中的体系结构稍有不同,需要声明的是,本文的代码在axis中开发,故需要在axis环境下运行。
在axis环境下,SOAP消息Handler必须实现org.apache.axis.Handler接口(在JAX-RPC 1.0规范中,SOAP消息Handler必须实现javax.xml.rpc.handler.Handler接口),org.apache.axis.Handler接口的部分代码如下:
例程1 org.apache.axis.Handle的部分代码
public interface Handler extends Serializable {
public void init();
public void cleanup();
public void invoke(MessageContext msgContext) throws AxisFault ;
public void onFault(MessageContext msgContext);
public void setOption(String name, Object value);
public Object getOption(String name);
public void setName(String name);
public String getName();
public Element getDeploymentData(Document doc);
public void generateWSDL(MessageContext msgContext) throws AxisFault;
…
}
为了提供开发的方便,在编写Handler时,只要继承org.apache.axis.handlers. BasicHandler即可,BasicHandler是Handler的一个模板,我们看它的部分代码:
例程2 BasicHandler的部分代码
public abstract class BasicHandler implements Handler {
protected static Log log =
LogFactory.getLog(BasicHandler.class.getName());
protected Hashtable options;
protected String name;
//这个方法必须在Handler中实现。
public abstract void invoke(MessageContext msgContext) throws AxisFault;
public void setOption(String name, Object value) {
if ( options == null ) initHashtable();
options.put( name, value );
}
…
}
BasicHandler中的(MessageContext msgContext)方法是Handler实现类必须实现的方法,它通过MessageContext来获得请求或者响应的SOAPMessage对象,然后对SOAPMessage进行处理。
在介绍Handler的开发之前,我们先来看一下目标Web服务的端点实现类的代码,如例程3所示。
例程3 目标Web服务的端点实现类
package com.hellking.webservice;
public class HandleredService
{
//一个简单的Web服务
public String publicMethod(String name)
{
return "Hello!"+name;
}
}
//另一个Web服务端点:
package com.hellking.webservice;
public class OrderService
{
//web服务方法:获得客户端的订单信息,并且对订单信息进行对应的处理,
通常情况是把订单的信息写入数据库,然后可客户端返回确认信息。
public String orderProduct(String name,String address,String item,int quantity,Card card)
{
String cardId=card.getCardId();
String cardType=card.getCardType();
String password=card.getPassword();
String rderInfo="name="+name+",address="+address+",item="+item+",quantity="+quantity+"
,cardId="+cardId+",cardType="+cardType+",password="+password;
System.out.println("这里是客户端发送来的信息:");
System.out.println(orderInfo);
return orderInfo;
}
}
下面我们分不同情况讨论Handler的使用实例。
使用Handler为系统做日志
Handler为系统做日志是一种比较常见而且简单的使用方式。和Servlet中的Filter一样,我们可以使用Handler来把用户的访问写入系统日志。下面我们来看日志Handler的具体代码,如例程4所示。
例程4 LogHandler的代码
package com.hellking.webservice;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Date;
import org.apache.axis.AxisFault;
import org.apache.axis.Handler;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
public class LogHandler extends BasicHandler {
/**invoke,每一个handler都必须实现的方法。
*/
public void invoke(MessageContext msgContext) throws AxisFault
{
//每当web服务被调用,都记录到log中。
try {
Handler handler = msgContext.getService();
String filename = (String)getOption("filename");
if ((filename == null) || (filename.equals("")))
throw new AxisFault("Server.NoLogFile",
"No log file configured for the LogHandler!",
null, null);
FileOutputStream fos = new FileOutputStream(filename, true);
PrintWriter writer = new PrintWriter(fos);
Integer counter = (Integer)handler.getOption("accesses");
if (counter == null)
counter = new Integer(0);
counter = new Integer(counter.intValue() + 1);
Date date = new Date();
msgContext.getMessage().writeTo(System.out);
String result = "在"+date + ": Web 服务 " +
msgContext.getTargetService() +
" 被调用,现在已经共调用了 " + counter + " 次.";
handler.setOption("accesses", counter);
writer.println(result);
writer.close();
} catch (Exception e) {
throw AxisFault.makeFault(e);
}
}
}
前面我们说过,Handler实现类必须实现invoke方法,invoke方法是Handler处理其业务的入口点。LogHandler的主要功能是把客户端访问的Web服务的名称和访问时间、访问的次数记录到一个日志文件中。
下面部署这个前面开发的Web服务对像,然后为Web服务指定Handler。编辑Axis_Home/WEB-INF/ server-config.wsdd文件,在其中加入以下的内容:
<service name="HandleredService" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="com.hellking.webservice.HandleredService"/>
<parameter name="allowedRoles" value="chen"/>
<beanMapping languageSpecificType="java:com.hellking.webservice.Card"
qname="card:card" xmlns:card="card"/>
<requestFlow>
<handler name="logging" type="java:com.hellking.webservice.LogHandler">
<parameter name="filename" value="c:\\MyService.log"/>
</handler>
</requestFlow>
</service>
…
</globalConfiguration>
…
<handler name="logging" type="java:com.hellking.webservice.LogHandler">
<parameter name="filename" value="c:\\MyService.log"/>
</handler>
…
<service name="HandleredService" provider="java:RPC">
…
<requestFlow>
<handler type="logging"/>
…<!--在这里可以指定多个Handler-->
</requestFlow>
</service>
http://127.0.0.1:8080/handler/services/HandleredService?wsdl&method=publicMethod&name=chen
注意:这个URL需要根据具体情况改变。
在Sun Jul 06 22:42:03 CST 2003: Web 服务 HandleredService 被调用,现在已经共调用了 1 次.
在Sun Jul 06 22:42:06 CST 2003: Web 服务 HandleredService 被调用,现在已经共调用了 2 次.
在Sun Jul 06 22:42:13 CST 2003: Web 服务 HandleredService 被调用,现在已经共调用了 3 次.
使用Handler对用户的访问认证
使用Handler为用户访问认证也是它的典型使用,通过它,可以减少在Web服务端代码中认证的麻烦,同时可以在部署描述符中灵活改变用户的访问权限。
对用户认证的Handler代码如下:
例程5 认证的Handler
package com.hellking.webservice;
import….
//此handler的目的是对用户认证,只有认证的用户才能访问目标服务。
public class AuthenticationHandler extends BasicHandler
{
/**invoke,每一个handler都必须实现的方法。
*/
public void invoke(MessageContext msgContext)throws AxisFault
{
SecurityProvider provider = (SecurityProvider)msgContext.getProperty("securityProvider");
if(provider==null)
{
provider= new SimpleSecurityProvider();
msgContext.setProperty("securityProvider", provider);
}
if(provider!=null)
{
String userId=msgContext.getUsername();
String password=msgContext.getPassword();
//对用户进行认证,如果authUser==null,表示没有通过认证,
抛出Server.Unauthenticated异常。
org.apache.axis.security.AuthenticatedUser authUser
= provider.authenticate(msgContext);
if(authUser==null)
throw new AxisFault("Server.Unauthenticated",
Messages.getMessage("cantAuth01", userId), null,null);
//用户通过认证,把用户的设置成认证了的用户。
msgContext.setProperty("authenticatedUser", authUser);
}
}
}
在AuthenticationHandler代码里,它从MessageContext中获得用户信息,然后进行认证,如果认证成功,那么就使用msgContext.setProperty("authenticatedUser", authUser)方法把用户设置成认证了的用户,如果认证不成功,那么就抛出Server.Unauthenticated异常。
部署这个Handler,同样,在server-config里加入以下的内容:
<handler name="authen" type="java:com.hellking.webservice.AuthenticationHandler"/>
…
<service name="HandleredService" provider="java:RPC">
<parameter name="allowedRoles" value="chen"/>
…
</service>
WEB-INF/users.lst文件中加入以下用户:
hellking hellking
chen chen
http://127.0.0.1:8080/handler/services/HandleredService?wsdl&method=publicMethod&name=chen
将会提示输入用户名和密码,如图2所示。
图2 访问web服务时的验证
如果客户端是应用程序,那么可以这样在客户端设置用户名和密码:
例程6 在客户端设置用户名和密码
http://127.0.0.1:808
String endpointURL = "http://127.0.0.1:8080/handler/services/HandleredService?wsdl";
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpointURL) );
call.setOperationName( new
QName("HandleredService", "orderProduct") );//设置操作的名称。
//由于需要认证,故需要设置调用的用户名和密码。
call.getMessageContext().setUsername("chen");
call.getMessageContext().setPassword("chen");
使用Handler对用户的访问授权
对于已经认证了的用户,有时在他们操作某个特定的服务时,还需要进行授权,只有授权的用户才能继续进行操作。我们看对用户进行授权的Handler的代码。
例程7 对用户进行授权的代码
package com.hellking.webservice;
import…
//此handler的目的是对认证的用户授权,只有授权的用户才能访问目标服务。
public class AuthorizationHandler extends BasicHandler
{
/**invoke,每一个handler都必须实现的方法。
*/
public void invoke(MessageContext msgContext)
throws AxisFault
{
AuthenticatedUser user = (AuthenticatedUser)msgContext.getProperty("authenticatedUser");
if(user == null)
throw new AxisFault("Server.NoUser", Messages.getMessage("needUser00"), null, null);
String userId = user.getName();
Handler serviceHandler = msgContext.getService();
if(serviceHandler == null)
throw new AxisFault(Messages.getMessage("needService00"));
String serviceName = serviceHandler.getName();
String allowedRoles = (String)serviceHandler.getOption("allowedRoles");
if(allowedRoles == null)
{
return;
}
SecurityProvider provider = (SecurityProvider)msgContext.getProperty("securityProvider");
if(provider == null)
throw new AxisFault(Messages.getMessage("noSecurity00"));
for(StringTokenizer st = new StringTokenizer(allowedRoles, ","); st.hasMoreTokens();)
{
String thisRole = st.nextToken();
if(provider.userMatches(user, thisRole))
{
return;//访问授权通过。
}
}
//没有通过授权,不能访问目标服务,抛出Server.Unauthorized异常。
throw new AxisFault("Server.Unauthorized",
Messages.getMessage("cantAuth02", userId, serviceName), null, null);
}
}
在service-config.wsdd文件中,我们为Web服务指定了以下的用户:
<parameter name="allowedRoles" value="chen,hellking"/>
provider.userMatches(user, thisRole)将匹配允许访问Web服务的用户,如果匹配成功,那么授权通过,如果没有授权成功,那么抛出Server.Unauthorized异常。
使用Handler对SOAP消息进行加密、解密
由于SOAP消息在HTTP协议中传输,而HTTP协议的安全度是比较低的,怎么保证信息安全到达对方而不泄漏或中途被撰改,将是Web服务必须解决的问题。围绕Web服务的安全,有很多相关的技术,比如WS-Security,WS-Trace等,另外,还有以下相关技术:
XML Digital Signature(XML数字签名)
XML Encryption (XML加密)
XKMS (XML Key Management Specification)
XACML (eXtensible Access Control Markup Language)
SAML (Secure Assertion Markup Language)
ebXML Message Service Security
Identity Management & Liberty Project
不管使用什么技术,要使信息安全到达对方,必须把它进行加密,然后在对方收到信息后解密。为了提供开发的方便,可以使用Handler技术,在客户端发送信息前,使用客户端的Handler对SOAP消息中的关键信息进行加密;在服务端接收到消息后,有相应的Handler把消息进行解密,然后才把SOAP消息派发到目标服务。
下面我们来看一个具体的例子。加入使用SOAP消息发送订单的信息,订单的信息如下:
例程8 要发送的订单SOAP消息
<soap-env:Envelope xmlns:soap-env="" target="_blank">http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header/>
<soapenv:Body>
<ns1:orderProduct soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encod
ing/" xmlns:ns1="HandleredService">
<arg0 xsi:type="xsd:string">hellking</arg0>
<arg1 xsi:type="xsd:string">beijing</arg1>
<arg2 xsi:type="xsd:string">music-100</arg2>
<arg3 xsi:type="xsd:int">10</arg3>
<arg4 href="#id0"/>
</ns1:orderProduct>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmls
oap.org/soap/encoding/" xsi:type="ns2:card" xmlns:soapenc="http://schemas.xmlsoa
p.org/soap/encoding/" xmlns:ns2="card">
<cardId xsi:type="xsd:string">234230572</cardId>
<cardType xsi:type="xsd:string">visa</cardType>
<password xsi:type="xsd:string">234kdsjf</password>
</multiRef>
</soapenv:Body>
</soap-env:Envelope>
上面的黑体字是传输的敏感信息,故需要加密。我们可以使用Message Digest之类的方法进行加密。加密之后的信息结构如下:
例程9 把SOAP消息某些部分加密
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope …
<soapenv:Body>
<ns1:orderProduct …>
…
<arg4 href="#id0"/>
</ns1:orderProduct>
<multiRef …>
<ns3:EncryptedData xmlns:ns3="" target="_blank">http://www.w3.org/2000/11/temp-xmlenc">
<ns3:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ns3:DigestValue>rO0ABXQAkyA8Y2FyZ…….
</ns3:DigestValue>
</ns3:EncryptedData>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>
图3是使用Handler对SOAP消息进行加密、解密后,SOAP消息在传递过程中结构的改变。
图3 SOAP消息的加密和解密
从上图可以看出,通过使用加密、解密的Handler,可以确保消息的安全传递。进一步说,如果把这种Handler做成通用的组件,那么就可以灵活地部署到不同的服务端和客户端。
客户端的Handler的功能是把SOAP消息使用一定的规则加密,假如使用Message Digest加密方式,那么可以这样对敏感的信息加密:
例程10 对SOAP消息的敏感部分加密
SOAPElement ele= soapBodyElement.addChildElement(envelope.createName
("EncryptedData","","http://www.w3.org/2000/11/temp-xmlenc"));
ele.addChildElement("DigestMethod").addAttribute(envelope.createName
("Algorithm"),"http://www.w3.org/2000/09/xmldsig#sha1");
byte[] digest=new byte[100];
ByteArrayOutputStream out=new ByteArrayOutputStream (100);
MessageDigest md = MessageDigest.getInstance("SHA");
ObjectOutputStream oos = new ObjectOutputStream(out);
//要加密的信息
String data = " <cardId xsi:type='xsd:string'>234230572
</cardId><cardType xsi:type='xsd:string'>visa</cardType>
<password xsi:type='xsd:string'>234kdsjf</password>";
byte buf[] = data.getBytes();
md.update(buf);
oos.writeObject(data);
oos.writeObject(md.digest());
digest=out.toByteArray();
out.close();
ele.addChildElement("DigestValue").addTextNode(new
sun.misc.BASE64Encoder().encode(digest));//对加密的信息编码
在客户端发送出SOAP消息时,客户端的Handler拦截发送的SOAP消息,然后对它们进行加密,最后把加密的信息传送到服务端。
服务端接收到加密的信息后,解密的Handler会把对应的加密信息解密。服务端Handler代码如例程11所示。
例程11 服务端解密Handler
package com.hellking.webservice;
import…
//此handler的目的是把加密的SOAP消息解密成目标服务可以使用的SOAP消息。
public class MessageDigestHandler extends BasicHandler
{
/**invoke,每一个handler都必须实现的方法。
*/
public void invoke(MessageContext msgContext)throws AxisFault
{
try
{
//从messageContext例取得SOAPMessage对象。
SOAPMessage msg=msgContext.getMessage();
SOAPEnvelope env=msg.getSOAPPart().getEnvelope();
Iterator it=env.getBody().getChildElements();
SOAPElement multi=null;
while(it.hasNext())
{
multi=(SOAPElement)it.next();//multi是soapbody的最后一个child。
}
String value="";//value表示加密后的值。
SOAPElement digestValue=null;
Iterator it2=multi.getChildElements();
while(it2.hasNext())
{
SOAPElement temp=(SOAPElement)it2.next();
Iterator it3=temp.getChildElements(env.createName("DigestValue",
"ns3","http://www.w3.org/2000/11/temp-xmlenc"));
if(it3.hasNext())
value=((SOAPElement)it3.next()).getValue();//获得加密的值
}
//把加密的SOAPMessage解密成目标服务可以调用的SOAP消息。
SOAPMessage msg2=convertMessage(msg,this.decrypte(value));
msgContext.setMessage(msg2);
}
catch(Exception e)
{
e.printStackTrace();
}
}
//这个方法是把加密的数据进行解密,返回明文。
public String decrypte(String value)
{
String data=null;
try
{
ByteArrayInputStream fis = new
ByteArrayInputStream(new sun.misc.BASE64Decoder().decodeBuffer(value));
ObjectInputStream ois = new ObjectInputStream(fis);
Object o = ois.readObject();
if (!(o instanceof String)) {
System.out.println("Unexpected data in string");
System.exit(-1);
}
data = (String) o;
System.out.println("解密后的值:" + data);
o = ois.readObject();
if (!(o instanceof byte[])) {
System.out.println("Unexpected data in string");
System.exit(-1);
}
byte origDigest[] = (byte []) o;
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(data.getBytes());
}
…
return data;
}
//把解密后的信息重新组装成服务端能够使用的SOAP消息。
public SOAPMessage convertMessage(SOAPMessage msg,String data)
{
….
}
}
可以看出,服务端解密的Handler和客户端加密的Handler的操作是相反的过程。
总结
通过以上的讨论,相信大家已经掌握了Handler的基本使用技巧。可以看出,通过使用Handler,可以给Web服务提供一些额外的功能。在实际的开发中,我们可以开发出一些通用的Handler,然后通过不同的搭配方式把它们部署到不同的Web服务中。
+++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(三)(建立安全的AXIS服务上)
ronghao100 原创
在前面的文章中,我们实现了最简单的AXIS服务。现在我们一起来讨论一下Web服务的安全问题。
根据应用的对安全要求的级别不同,可以采用不同的方式来实现安全性,以下是目前最常用的一些实现方式(从低到高排列):
1、J2EE Web应用默认的访问控制(数据是明文的);
2、使用axis的Handler进行访问控制(数据是明文的);
3、使用Servlet过滤器(Filter)进行访问控制(数据是明文的);
4、使用SSL/HTTPS协议来传输(加密的数据传输协议);
5、使用WS-Security规范对信息进行加密与身份认证(数据被加密传输)。
我们仅讨论第2、4、5种实现方式。在此之前我们先来了解一下AXIS自带的一个工具SOAPMonitor。
一、SOAPMonitor的使用
打开http://localhost:8080/axis/进入AXIS的主页面,你会看见:
SOAPMonitor-[disabled by default for security reasons] ,默认状态下其是不可用的,现在我们就来激活它。
1、到目录%TOMCAT_HOME%\webapps\axis下,你会找到SOAPMonitorApplet.java,在命令行中编译它:
javac -classpath %AXIS_HOME%\lib\axis.jar SOAPMonitorApplet.java
编译完之后你会看见目录下多了很多CLASS文件,它们的名字是SOAPMonitorApplet*.class
2、在目录%TOMCAT_HOME%\webapps\axis\WEB-INF下打开server-config.wsdd文件,将下面的两部分代码直
接加入其中相应的位置
第一部分:
<handler name="soapmonitor" type="java:org.apache.axis.handlers.SOAPMonitorHandler">
<parameter name="wsdlURL" value="/axis/SOAPMonitorService-impl.wsdl"/>
<parameter name="namespace" value="" target="_blank">http://tempuri.org/wsdl/2001/12/SOAPMonitorService-impl.wsdl"/>
<parameter name="serviceName" value="SOAPMonitorService"/>
<parameter name="portName" value="Demo"/>
</handler>
第二部分:
<service name="SOAPMonitorService" provider="java:RPC">
<parameter name="allowedMethods" value="publishMessage"/>
<parameter name="className" value="org.apache.axis.monitor.SOAPMonitorService"/>
<parameter name="scope" value="Application"/>
</service>
3、选择你要监控的服务
以上次的HelloWorld服务为例,在server-config.wsdd中你会找到这段代码
<service name="HelloWorld" provider="java:RPC">
<parameter name="allowedMethods" value="sayHello"/>
<parameter name="className" value="HelloWorld"/>
</service>
在这段代码中加入以下的代码:
<requestFlow>
<handler type="soapmonitor"/>
</requestFlow>
<responseFlow>
<handler type="soapmonitor"/>
</responseFlow>
最后的样子是:
<service name="HelloWorld" provider="java:RPC">
<requestFlow>
<handler type="soapmonitor"/>
</requestFlow>
<responseFlow>
<handler type="soapmonitor"/>
</responseFlow>
<parameter name="allowedMethods" value="sayHello"/>
<parameter name="className" value="HelloWorld"/>
</service>
这样HelloWorld服务就被监控了
4、启动Tomcat,打开http://localhost:8080/axis/SOAPMonitor,你就会看到Applet界面,在
jbuilder2005中运行我们上次写的客户端程序 TestClient.java。OK!你会在Applet界面看
见客户端与服务器端互发的XML内容,注意这里是明文!
二、使用axis的Handler进行访问控制(对安全要求不高时推荐)
axis为Web服务的访问控制提供了相关的配置描述符,并且提供了一个访问控制的简单 Handler。默认情况下,你只要在配置描述符中添加用户,然后在Web服务器的部署描述符中自动允许的角色即可。
1、在axis的配置文件users.lst(位于WEB-INF目录下)中添加一个用户,如"ronghao1111",表示
用户名为ronghao,密码为1111。
2、把例HelloWorld的Web服务重新部署(新加的部分已标出)
<service name="HelloWorld" provider="java:RPC">
<requestFlow>
<handler type="soapmonitor"/>
<handler type="Authenticate"/> //新加的AXIS自带的Handler
</requestFlow>
<responseFlow>
<handler type="soapmonitor"/>
</responseFlow>
<parameter name="allowedMethods" value="sayHello"/>
<parameter name="allowedRoles" value="ronghao"/> //注意,这里是新加的部分!
<parameter name="className" value="HelloWorld"/>
</service>
在这个部署描述符中,指定HelloWorld服务只能被ronghao访问
3、修改客户端程序 TestClient.java,增加访问用户名、密码(新加的部分已标出)
TestClient.java
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.rpc.ParameterMode;
public class TestClient
{
public static void main(String [] args) throws Exception {
String endpoint = "http://localhost:" +"8080"+ "/axis/HelloWorld";
Service service = new Service();
Call call = (Call) service.createCall();
call.getMessageContext().setUsername("ronghao");// 用户名。
call.getMessageContext().setPassword("1111");// 密码
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName( "sayHello" );
String res = (String) call.invoke( new Object[] {} );
System.out.println( res );
}
}
执行TestClient,能够顺利访问Web服务;如果修改用户名或者密码,那么就不能访问 。同样,
你在http://localhost:8080/axis/SOAPMonitor中看到的请求和响应的XML是明文!
三、使用SSL/HTTPS协议来传输
Web服务也可以使用SSL作为传输协议。虽然JAX-RPC并没有强制规定是否使用SSL协议,但在tomcat
下使用HTTPS协议。
1、使用JDK自带的工具创建密匙库和信任库。
1)通过使用以下的命令来创建服务器端的密匙库:
keytool -genkey -alias Server -keystore server.keystore -keyalg RSA
输入keystore密码: changeit
您的名字与姓氏是什么?
[Unknown]: Server
您的组织单位名称是什么?
[Unknown]: ec
您的组织名称是什么?
[Unknown]: ec
您所在的城市或区域名称是什么?
[Unknown]: beijing
您所在的州或省份名称是什么?
[Unknown]: beijing
该单位的两字母国家代码是什么
[Unknown]: CN
CN=Server, OU=ec, O=ec, L=beijing, ST=beijing, C=CN 正确吗?
[否]: y
输入<Server>的主密码
(如果和 keystore 密码相同,按回车):
以上命令执行完成后,将获得一个名为server.keystore的密匙库。
2)生成客户端的信任库。首先输出RSA证书:
keytool -export -alias Server -file test_axis.cer -storepass changeit -keystore server.keystore
然后把RSA证书输入到一个新的信任库文件中。这个信任库被客户端使用,被用来验证服务器端的身份。
keytool -import -file test_axis.cer -storepass changeit -keystore client.truststore -alias serverkey -noprompt
以上命令执行完成后,将获得一个名为client.truststore的信任库。
3)同理生成客户端的密匙库client.keystore和服务器端的信任库server.truststore.方便起见给出.bat文件
gen-cer-store.bat内容如下:
set SERVER_DN="CN=Server, OU=ec, O=ec, L=BEIJINGC, S=BEIJING, C=CN"
set CLIENT_DN="CN=Client, OU=ec, O=ec, L=BEIJING, S=BEIJING, C=CN"
set KS_PASS=-storepass changeit
set KEYINFO=-keyalg RSA
keytool -genkey -alias Server -dname %SERVER_DN% %KS_PASS% -keystore server.keystore %KEYINFO% -keypass changeit
keytool -export -alias Server -file test_axis.cer %KS_PASS% -keystore server.keystore
keytool -import -file test_axis.cer %KS_PASS% -keystore client.truststore -alias serverkey -noprompt
keytool -genkey -alias Client -dname %CLIENT_DN% %KS_PASS% -keystore client.keystore %KEYINFO% -keypass changeit
keytool -export -alias Client -file test_axis.cer %KS_PASS% -keystore client.keystore
keytool -import -file test_axis.cer %KS_PASS% -keystore server.truststore -alias clientkey -noprompt
好的,现在我们就有了四个文件:server.keystore,server.truststore,client.keystore,client.truststore
2、更改Tomcat的配置文件(server.xml),增加以下部署描述符:(其实里面有,只是被注释掉了)
<Connector port="8440"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="true" keystoreFile="f:\server.keystore" keystorePass="changeit"
truststoreFile="f:\server.truststore" truststorePass="changeit"
sslProtocol="TLS" />
3、把HelloWorld重新部署一次,在server-config.wsdd中修改如下部署代码。(还原了而已)
<service name="HelloWorld" provider="java:RPC">
<requestFlow>
<handler type="soapmonitor"/>
</requestFlow>
<responseFlow>
<handler type="soapmonitor"/>
</responseFlow>
<parameter name="allowedMethods" value="sayHello"/>
<parameter name="className" value="HelloWorld"/>
</service>
4、修改客户端程序 TestClient.java(修改的部分已标出)
public class TestClient
{
public static void main(String [] args) throws Exception {
String endpoint = "https://localhost:" +"8440"+ "/axis/HelloWorld";//注意区别在这里!https!
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress( new java.net.URL(endpoint) );
call.setOperationName( "sayHello" );
String res = (String) call.invoke( new Object[] {} );
System.out.println( res );
}
}
5、最后使用命令来执行客户端程序
java -cp %AXISCLASSPATH%
-Djavax.net.ssl.keyStore=client.keystore
-Djavax.net.ssl.keyStorePassword=changeit
-Djavax.net.ssl.trustStore=client.truststore
TestClient
+++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(四)(建立安全的AXIS服务下)
ronghao100 原创
四、使用WS-Security规范对信息进行加密与身份认证
我们打算用Handler结合WSSecurity实现Web服务安全(Handler的有关内容请参阅AXIS学习笔记(二))
设想流程:用WSClientRequestHandler.java位于客户端对客户端发出的XML文档进行加密
WSServerRequestHandler.java位于服务器端对客户端发出的加密后的XML文档进行解密
WSServerResponseHandler.java位于服务器端对服务器端返回的XML文档进行加密
WSClientResponseHandler.java位于客户端对服务器端返回的XML文档进行解密
1、使用ISNetworks安全提供者,ISNetworks实现了RSA加密、解密算法。
当然,你也可以使用其它的安全提供者,并且可以使用不同的加密算法。
ISNetworks相关包ISNetworksProvider.jar。拷贝到%TOMCAT_HOME% \webapps\axis\WEB-INF\lib
2、Trust Services Integration Kit提供了一个WS-Security实现。你可以从http://www.xmltrustcenter.org获得相关库文件,分别是ws-security.jar和tsik.jar。ws-security.jar中包含一个WSSecurity类,我们使用它来对XML进行数字签名和验证,加密与解密。同样拷贝到%TOMCAT_HOME%\webapps\axis\WEB-INF\lib
3、创建密匙库和信任库。(见上文,一模一样!)
4、框架结构
WSClientHandler.java //基类,包含了一些公用方法
WSClientRequestHandler.java //继承于WSClientHandler.java,调用WSHelper.java对客户端发出的XML文档进行加密
WSClientResponseHandler.java //继承于WSClientHandler.java,调用WSHelper.java对服务器端返回的XML文档进行解密
WSServerHandler.java //基类,包含了一些公用方法
WSServerRequestHandler.java //继承于WSServerHandler.java,调用WSHelper.java对客户端发出的加密后的XML文档进行解密
WSServerResponseHandler.java//继承于WSServerHandler.java,调用WSHelper.java对服务器端返回的XML文档进行加密
WSHelper.java //核心类,对SOAP消息签名、加密、解密、身份验证
MessageConverter.java //帮助类,Document、SOAP消息互相转换
5、具体分析(在此强烈建议看一下tsik.jar的API)
WSHelper.java
public class WSHelper {
static String PROVIDER="ISNetworks";//JSSE安全提供者。
//添加JSSE安全提供者,你也可以使用其它安全提供者。只要支持DESede算法。这是程序里动态加载还可以在JDK中静态加载
static
{
java.security.Security.addProvider(new com.isnetworks.provider.jce.ISNetworksProvider());
}
/**
*对XML文档进行数字签名。
*/
public static void sign(Document doc, String keystore, String storetype,
String storepass, String alias, String keypass) throws Exception {
FileInputStream fileInputStream = new FileInputStream(keystore);
java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
keyStore.load(fileInputStream, storepass.toCharArray());
PrivateKey key = (PrivateKey)keyStore.getKey(alias, keypass.toCharArray());
X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
SigningKey sk = SigningKeyFactory.makeSigningKey(key);
KeyInfo ki = new KeyInfo();
ki.setCertificate(cert);
WSSecurity wSSecurity = new WSSecurity();//ws-security.jar中包含的WSSecurity类
wSSecurity.sign(doc, sk, ki);//签名。
}
/**
*对XML文档进行身份验证。
*/
public static boolean verify(Document doc, String keystore, String storetype,
String storepass) throws Exception {
FileInputStream fileInputStream = new FileInputStream(keystore);
java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
keyStore.load(fileInputStream, storepass.toCharArray());
TrustVerifier verifier = new X509TrustVerifier(keyStore);
WSSecurity wSSecurity = new WSSecurity();
MessageValidity[] resa = wSSecurity.verify(doc, verifier, null,null);
if (resa.length > 0)
return resa[0].isValid();
return false;
}
/**
*对XML文档进行加密。必须有JSSE提供者才能加密。
*/
public static void encrypt(Document doc, String keystore, String storetype,
String storepass, String alias) throws Exception {
try
{
FileInputStream fileInputStream = new FileInputStream(keystore);
java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
keyStore.load(fileInputStream, storepass.toCharArray());
X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
PublicKey pubk = cert.getPublicKey();
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede",PROVIDER);
keyGenerator.init(168, new SecureRandom());
SecretKey key = keyGenerator.generateKey();
KeyInfo ki = new KeyInfo();
ki.setCertificate(cert);
WSSecurity wSSecurity = new WSSecurity();
//加密。
wSSecurity.encrypt(doc, key, AlgorithmType.TRIPLEDES, pubk, AlgorithmType.RSA1_5, ki);
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
*对文档进行解密。
*/
public static void decrypt(Document doc, String keystore, String storetype,
String storepass, String alias, String keypass) throws Exception {
FileInputStream fileInputStream = new FileInputStream(keystore);
java.security.KeyStore keyStore = java.security.KeyStore.getInstance(storetype);
keyStore.load(fileInputStream, storepass.toCharArray());
PrivateKey prvk2 = (PrivateKey)keyStore.getKey(alias, keypass.toCharArray());
WSSecurity wSSecurity = new WSSecurity();
//解密。
wSSecurity.decrypt(doc, prvk2, null);
WsUtils.removeEncryptedKey(doc);//从 WS-Security Header中删除 EncryptedKey 元素
}
public static void removeWSSElements(Document doc) throws Exception {
WsUtils.removeWSSElements(doc);// 删除WSS相关的元素。
}
}
WSClientHandler.java
//继承自org.apache.axis.handlers.BasicHandler即AXIS内在的
public class WSClientHandler extends BasicHandler{
protected String keyStoreFile ;
protected String keyStoreType ="JKS";//默认
protected String keyStorePassword ;
protected String keyAlias ;
protected String keyEntryPassword ;
protected String trustStoreFile ;
protected String trustStoreType = "JKS";//默认
protected String trustStorePassword ;
protected String certAlias ;
public void setInitialization(String keyStoreFile,String keyStoreType,String keyStorePassword,
String keyAlias,String keyEntryPassword,String trustStoreFile,
String trustStoreType,String trustStorePassword,String certAlias){
this.keyStoreFile=keyStoreFile;
this.keyStoreType=keyStoreType;
this.keyStorePassword=keyStorePassword;
this.keyAlias=keyAlias;
this.keyEntryPassword=keyEntryPassword;
this.trustStoreFile=trustStoreFile;
this.trustStoreType=trustStoreType;
this.trustStorePassword=trustStorePassword;
this.certAlias=certAlias;
}
public void setInitialization(String keyStoreFile,String keyStorePassword,
String keyAlias,String keyEntryPassword,String trustStoreFile,
String trustStorePassword,String certAlias){
this.keyStoreFile=keyStoreFile;
this.keyStorePassword=keyStorePassword;
this.keyAlias=keyAlias;
this.keyEntryPassword=keyEntryPassword;
this.trustStoreFile=trustStoreFile;
this.trustStorePassword=trustStorePassword;
this.certAlias=certAlias;
}
public void invoke(MessageContext messageContext) throws AxisFault {//在这个方法里对XML文档进行处理
//do nothing now!
}
public void onFault(MessageContext msgContext) {
System.out.println("处理错误,这里忽略!");
}
}
WSClientRequestHandler.java
public class WSClientRequestHandler extends WSClientHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
try {
SOAPMessage soapMessage = messageContext.getMessage();
Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage); //soapMessage转换为Document
WSHelper.sign(doc, keyStoreFile, keyStoreType,keyStorePassword, keyAlias, keyEntryPassword); //数字签名
WSHelper.encrypt(doc, trustStoreFile, trustStoreType, trustStorePassword, certAlias); //加密
soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc);
//处理后的Document再转换回soapMessage
messageContext.setMessage(soapMessage);
} catch (Exception e){
System.err.println("在处理响应时发生以下错误: " + e);
e.printStackTrace(); }
}
}
WSClientResponseHandler.java
public class WSClientResponseHandler extends WSClientHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
try {
SOAPMessage soapMessage = messageContext.getCurrentMessage();
Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage);
WSHelper.decrypt(doc, keyStoreFile, keyStoreType,
keyStorePassword, keyAlias, keyEntryPassword);//解密
WSHelper.verify(doc, trustStoreFile, trustStoreType, trustStorePassword);//验证
WSHelper.removeWSSElements(doc);
soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc);
messageContext.setMessage(soapMessage);
} catch (Exception e){
e.printStackTrace();
System.err.println("在处理响应时发生以下错误: " + e);
}
}
}
WSServerHandler.java
public class WSServerHandler extends BasicHandler{
protected String keyStoreFile ;
protected String keyStoreType ="JKS";//默认
protected String keyStorePassword ;
protected String keyAlias ;
protected String keyEntryPassword ;
protected String trustStoreFile ;
protected String trustStoreType = "JKS";//默认
protected String trustStorePassword ;
protected String certAlias ;
public void invoke(MessageContext messageContext) throws AxisFault {
//do nothing now!
}
public void onFault(MessageContext msgContext) {
System.out.println("处理错误,这里忽略!");
}
public void init() { //初始化,从配置文件server-config.wsdd中读取属性
keyStoreFile = (String)getOption("keyStoreFile");
if(( keyStoreFile== null) )
System.err.println("Please keyStoreFile configured for the Handler!");
trustStoreFile = (String)getOption("trustStoreFile");
if(( trustStoreFile== null) )
System.err.println("Please trustStoreFile configured for the Handler!");
keyStorePassword = (String)getOption("keyStorePassword");
if(( keyStorePassword== null) )
System.err.println("Please keyStorePassword configured for the Handler!");
keyAlias = (String)getOption("keyAlias");
if(( keyAlias== null) )
System.err.println("Please keyAlias configured for the Handler!");
keyEntryPassword = (String)getOption("keyEntryPassword");
if(( keyEntryPassword== null) )
System.err.println("Please keyEntryPassword configured for the Handler!");
trustStorePassword = (String)getOption("trustStorePassword");
if(( trustStorePassword== null) )
System.err.println("Please trustStorePassword configured for the Handler!");
certAlias = (String)getOption("certAlias");
if ((certAlias==null))
System.err.println("Please certAlias configured for the Handler!");
if ((getOption("keyStoreType")) != null)
keyStoreType = (String)getOption("keyStoreType");
if ((getOption("trustStoreType")) != null)
trustStoreType = (String)getOption("trustStoreType");
}
}
WSServerRequestHandler.java
public class WSServerRequestHandler extends WSServerHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
try {
SOAPMessage msg = messageContext.getCurrentMessage();
Document doc = MessageConverter.convertSoapMessageToDocument(msg);
System.out.println("接收的原始消息:");
msg.writeTo(System.out);
WSHelper.decrypt(doc, keyStoreFile, keyStoreType,
keyStorePassword, keyAlias, keyEntryPassword);//解密
WSHelper.verify(doc, trustStoreFile, trustStoreType, trustStorePassword);//验证
WSHelper.removeWSSElements(doc);
msg = MessageConverter.convertDocumentToSOAPMessage(doc);
System.out.println("怀原后的原始消息:");
msg.writeTo(System.out);
messageContext.setMessage(msg);
} catch (Exception e){
e.printStackTrace();
System.err.println("在处理响应时发生以下错误: " + e);
}
}
}
WSServerResponseHandler.java
public class WSServerResponseHandler extends WSServerHandler{
public void invoke(MessageContext messageContext) throws AxisFault {
try {
SOAPMessage soapMessage = messageContext.getMessage();
System.out.println("返回的原始消息:");
soapMessage.writeTo(System.out);
Document doc = MessageConverter.convertSoapMessageToDocument(soapMessage);
WSHelper.sign(doc, keyStoreFile, keyStoreType,
keyStorePassword, keyAlias, keyEntryPassword);//数字签名
WSHelper.encrypt(doc, trustStoreFile, trustStoreType,//加密
trustStorePassword, certAlias);
soapMessage = MessageConverter.convertDocumentToSOAPMessage(doc);
System.out.println("返回的加密后的消息:");
soapMessage.writeTo(System.out);
messageContext.setMessage(soapMessage);
} catch (Exception e){
System.err.println("在处理响应时发生以下错误: " + e);
e.printStackTrace();
}
}
}
6、应用
为方便使用,把上述文件打包为ws-axis.jar,放入%TOMCAT_HOME%\webapps\axis\WEB-INF\lib
1)把HelloWorld重新部署一次,在server-config.wsdd中修改如下部署代码。
<service name="HelloWorld" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="HelloWorld"/>
<requestFlow>
<handler type="soapmonitor"/>
<handler type="java:com.ronghao.WSAxis.WSServerRequestHandler">
<parameter name="keyStoreFile" value="f:\server.keystore"/>
<parameter name="trustStoreFile" value="f:\server.truststore"/>
<parameter name="keyStorePassword" value="changeit"/>
<parameter name="keyAlias" value="Server"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="certAlias" value="clientkey"/>
</handler>
</requestFlow>
<responseFlow>
<handler type="soapmonitor"/>
<handler type="java:com.ronghao.WSAxis.WSServerResponseHandler">
<parameter name="keyStoreFile" value="f:\server.keystore"/>
<parameter name="trustStoreFile" value="f:\server.truststore"/>
<parameter name="keyStorePassword" value="changeit"/>
<parameter name="keyAlias" value="Server"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="certAlias" value="clientkey"/>
</handler>
</responseFlow>
</service>
2)修改客户端程序 TestClient.java(修改的部分已标出,记着导入ws-axis.jar)
import javax.xml.namespace.QName;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import com.ronghao.WSAxis.*;
public class WSSClient1
{
public static void main(String [] args)
{
try {
//服务端的url,需要根据情况更改。
String endpointURL = "http://localhost:8080/axis/services/HelloWorld";
Service svc = new Service();
WSClientHandler handler=new WSClientRequestHandler();
//注意新加的HANDLER
handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
WSClientHandler handlee=new WSClientResponseHandler();
//注意新加的HANDLER
handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
Call call =(Call)svc.createCall();
call.setClientHandlers(handler,handlee);//添加Handler
call.setTargetEndpointAddress(new java.net.URL(endpointURL));
call.setOperationName(new QName("sayHello"));
String result = (String) call.invoke( new Object [] {});
System.out.println("the result"+result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行的时候http://localhost:8080/axis/SOAPMonitor中看到的请求的XML就已加密!
总结
这里对代码的解释是不够的,很多概念没有提到。建议你最好看tsik.jar和AXIS的API深入了解。另外对ws-axis.jar的加解密实现打算运用apache的wss4j,相关网址http://ws.apache.org/ws-fx/wss4j/。不过这个东西也应该够用了暂时。所有的源文件在附件中附件:soapTest.zip(279K)
++++++++++++++++++++++++++++++++++++++
AXIS学习笔记(五)( 在AXIS服务间传递JavaBean及其安全解决)
ronghao100 原创
在AXIS服务间传递JavaBean及其安全解决
这是AXIS学习笔记的最后一篇。在前面我们讨论了最简单的HelloWorld服务,客户端并没有向服务器端
传递参数,现在我们来传传JavaBean。当然,也可以传递你自己定义的JAVA类,但那样你必须自己创建
专门的XML序列化器和反序列化器;而对JavaBean,AXIS提供了现成的序列化器。(有人说:懒惰是程序员最大的美德,我喜欢,所以我就传传JavaBean)
一、服务器端
1、CLASS类两个Order.class,OrderTest.class,位于%TOMCAT_HOME%\webapps\axis\WEB-INF\classes下
这两个类都直接给出源码,不再说明
Order.java
public class Order {
private String id;
private String name;
public void setId(String id){
this.id=id;
}
public String getId(){
return id;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
OrderTest.java
public class OrderTest {
public Order returnOrder(Order order){
Order newOrder=new Order();
if(order.getId().equals("1"))
newOrder.setName("ronghao");
else newOrder.setName("haorong");
return newOrder;
}
}
2、修改服务器端配置文件server-config.wsdd
在server-config.wsdd中相应位置添加以下代码
<service name="Order" provider="java:RPC">
<parameter name="allowedMethods" value="returnOrder"/>
<parameter name="className" value="OrderTest"/>
<beanMapping languageSpecificType="java:Order" qname="ns1:Order"
xmlns:ns1="urn:BeanService"/>
</service>
可以看到和前面的发布服务代码相比仅多了一行代码
<beanMapping languageSpecificType="java:Order" qname="ns1:Order"
xmlns:ns1="urn:BeanService"/>
languageSpecificType属性指定JavaBean类文件位置,例如:
languageSpecificType="java:com.ronghao.axis.Order"
qname属性指定JavaBean类的名字
其他是固定的。
二、客户端
客户端类文件一个OrderClient.class,代码如下(变化的部分加注释):
public class OrderClient
{
public static void main(String args[])
throws Exception
{
String endpoint = "http://localhost:8080/axis/services/Order"; //服务所在位置
Order order=new Order(); //JavaBean
order.setId("1");
Service service = new Service();
Call call = (Call)service.createCall();
//注册JavaBean,注意和server-config.wsdd中的配置代码比较
QName qn = new QName("urn:BeanService", "Order");
call.registerTypeMapping(Order.class, qn, new BeanSerializerFactory(Order.class, qn),
new BeanDeserializerFactory(Order.class, qn));
String name="no!";
try
{
call.setTargetEndpointAddress(new URL(endpoint));
//调用的服务器端方法
call.setOperationName(new QName("Order", "returnOrder"));
//设定传入的参数,这里qn即Order.class
call.addParameter("arg1", qn, ParameterMode.IN);
//设定返回的参数是Order.class
call.setReturnType(qn, Order.class);
Order result = (Order)call.invoke(new Object[] {
order
});
if(result != null)
name = result.getName();
}
catch(Exception e)
{
System.err.println(e);
}
System.out.println(name);
}
}
OK!运行一下,就可以看到返回了"ronghao"。
和上一篇文章一样,我们不容许在网络中传递XML是明文,于是需要加密和验证。这里我们继续采用上次所讲的框架。(已打包成ws-axis.jar)
一、修改服务器端配置文件server-config.wsdd(和上一文章一模一样!不再罗嗦)
在server-config.wsdd中相应位置添加以下代码
<requestFlow>
<handler type="soapmonitor"/>
<handler type="java:com.ronghao.WSAxis.WSServerRequestHandler">
<parameter name="keyStoreFile" value="f:\server.keystore"/>
<parameter name="trustStoreFile" value="f:\server.truststore"/>
<parameter name="keyStorePassword" value="changeit"/>
<parameter name="keyAlias" value="Server"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="certAlias" value="clientkey"/>
</handler>
</requestFlow>
<responseFlow>
<handler type="soapmonitor"/>
<handler type="java:com.ronghao.WSAxis.WSServerResponseHandler">
<parameter name="keyStoreFile" value="f:\server.keystore"/>
<parameter name="trustStoreFile" value="f:\server.truststore"/>
<parameter name="keyStorePassword" value="changeit"/>
<parameter name="keyAlias" value="Server"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="certAlias" value="clientkey"/>
</handler>
</responseFlow>
二、客户端(区别就在这里,注意!!)
首先在这里要说一下,客户端代码编写困扰了我很长一段时间(整整一天),因为它并不象我想象的那么简单,当然解决起来还是挺简单的:)问题的解决经历了三个阶段
第一阶段:
在这个阶段我想当然的在OrderClient.class中加入了如下代码:
WSClientHandler handler=new WSClientRequestHandler();//注意新加的HANDLER
handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
WSClientHandler handlee=new WSClientResponseHandler();//注意新加的HANDLER
handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
call.setClientHandlers(handler,handlee);//添加Handler
这个方法也是我在上一文章里介绍的,结果抛出以下异常:
faultString: org.xml.sax.SAXException: Deserializing parameter
'newProfileReturn': could not find deserializer for type
{urn:BeanService Order}SerializableProfile
也就是说不能正常解析XML文件,于是理所当然的郁闷了,觉得代码中肯定漏设了CALL的一个属性,于是查看AXIS的源代码,没有结果!转机出现在下面一行代码,在不断的抛出异常中我修改了代码
将call.setClientHandlers(handler,handlee);改为
call.setClientHandlers(null,null);
结果程序还是抛出同样的异常,于是意识到这可能是AXIS的一个BUG,为证明这一点,我将下面的Handler初始化代码删除
WSClientHandler handler=new WSClientRequestHandler();//注意新加的HANDLER
handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
WSClientHandler handlee=new WSClientResponseHandler();//注意新加的HANDLER
handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
结果还是抛出同样的异常,果然是BUG!得到这个结论后去了apache AXIS主页,在问题列表中见到了完全一样问题的提交,但没有解答(晕!)
最后得到了结论:call的setClientHandlers()方法只有当call处理简单的数据类型,如String,int等等才能正常使用!
(当然,如果你对这个问题有不同的见解,欢迎和我联系。或许我错了,但程序不运行是真的:))
第二阶段:
开始在google上找问题的解决方法,这也是我的习惯:)。找了一个类似问题的讨论,地址如下:
http://marc.theaimsgroup.com/?l=axis-user&m=111259980822735&w=2
他们的解决方法是Handler继承于javax.xml.rpc.handler.Handler,然后在程序里动态注册而在我的ws-axis.jar里Handler继承于org.apache.axis.handlers.BasicHandler。当然,
javax.xml.rpc.handler.Handler是org.apache.axis.handlers.BasicHandler的老爸,但在程序里老爸和儿子之间却不能很好的兼容,这也许就是所谓的代沟??无奈中重新写了Handler,但在运行中却抛出异常,提示message在被invoke的时候已被更改。我靠,Handler的作用就是来更改message的啊!这是什么世道!
我知道很多程序采用的就是这种方法,但我好象怎么修改都抛出上述异常。
第三阶段
既然在程序里动态注册Handler行不通,于是决定写个单独的配置文件来注册Handler。如果这种方法不幸失败就返回第二阶段。好马为什么不吃回头草??
1、ws-axis.jar中修改WSClientHandler.class,修改后如下,我想你一看就明白为何修改
public class WSClientHandler extends BasicHandler{
protected String keyStoreFile ;
protected String keyStoreType ="JKS";
protected String keyStorePassword ;
protected String keyAlias ;
protected String keyEntryPassword ;
protected String trustStoreFile ;
protected String trustStoreType = "JKS";
protected String trustStorePassword ;
protected String certAlias ;
public void init() {
keyStoreFile = (String)getOption("keyStoreFile");
if(( keyStoreFile== null) )
System.err.println("Please keyStoreFile configured for the Handler!");
trustStoreFile = (String)getOption("trustStoreFile");
if(( trustStoreFile== null) )
System.err.println("Please trustStoreFile configured for the Handler!");
keyStorePassword = (String)getOption("keyStorePassword");
if(( keyStorePassword== null) )
System.err.println("Please keyStorePassword configured for the Handler!");
keyAlias = (String)getOption("keyAlias");
if(( keyAlias== null) )
System.err.println("Please keyAlias configured for the Handler!");
keyEntryPassword = (String)getOption("keyEntryPassword");
if(( keyEntryPassword== null) )
System.err.println("Please keyEntryPassword configured for the Handler!");
trustStorePassword = (String)getOption("trustStorePassword");
if(( trustStorePassword== null) )
System.err.println("Please trustStorePassword configured for the Handler!");
certAlias = (String)getOption("certAlias");
if ((certAlias==null))
System.err.println("Please certAlias configured for the Handler!");
if ((getOption("keyStoreType")) != null)
keyStoreType = (String)getOption("keyStoreType");
if ((getOption("trustStoreType")) != null)
trustStoreType = (String)getOption("trustStoreType");
}
public void invoke(MessageContext messageContext) throws AxisFault {
//do nothing now!
}
public void onFault(MessageContext msgContext) {
System.out.println("处理错误,这里忽略!");
}
}
2、写客户端的配置代码client-config.wsdd,如下:
<?xml version="1.0" encoding="UTF-8"?>
<deployment name="defaultClientConfig"
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="" target="_blank">http://xml.apache.org/axis/wsdd/providers/java">
<transport name="http"
pivot="java:org.apache.axis.transport.http.HTTPSender"/>
<transport name="local"
pivot="java:org.apache.axis.transport.local.LocalSender"/>
<transport name="java"
pivot="java:org.apache.axis.transport.java.JavaSender"/>
<globalConfiguration>
<requestFlow>
<handler type="java:com.ronghao.WSAxis.WSClientRequestHandler">
<parameter name="keyStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.keystore"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="certAlias" value="serverkey"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="trustStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.truststore"/>
<parameter name="keyAlias" value="Client"/>
<parameter name="keyStorePassword" value="changeit"/>
</handler>
</requestFlow>
<responseFlow>
<handler type="java:com.ronghao.WSAxis.WSClientResponseHandler">
<parameter name="keyStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.keystore"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="certAlias" value="serverkey"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="trustStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.truststore"/>
<parameter name="keyAlias" value="Client"/>
<parameter name="keyStorePassword" value="changeit"/>
</handler>
</responseFlow>
</globalConfiguration>
</deployment>
同样不再解释,不明白可以参考我的上一篇文章
3、修改OrderClient.class
在OrderClient.class中加入了如下代码:
EngineConfiguration conf =
new FileProvider("F:\\Tomcat\\webapps\\axis\\WEB-INF\\client-config.wsdd");//位置
Service service = new Service(conf);
当然记得导入
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
运行一下,返回"ronghao",靠,搞定!
注意:这次我把OrderClient.class的调用放到了一个JSP文件中而不是jbuilder中,因为有client-config.wsdd,所以你必须有完整的WEB程序发布到TOMCAT中,否则会报找不到
相应文件。
- 作者: Jo Ja Yong 2006年08月29日, 星期二 17:30 回复(6) | 引用(0) 加入博采
软件项目成功的20个经验
1、定义项目成功的标准
在项目的开始,要保证风险承担者对于他们如何判断项目是否成功有统一的认识。经常,满足一个预定义的进度安排是唯一明显的成功因素,但是肯定还有其他的因素存在,比如:增加市场占有率,获得指定的销售量或销售额,取得特定用户满意程度,淘汰一个高维护需求的遗留系统,取得一个特定的事务处理量并保证正确性。项目计划目标定义,包括进度,成本和质量(PP)
2、识别项目的驱动、约束和自由程度
每个项目都需要平衡它的功能性,人员,预算,进度和质量同标。我们把以上五个项目方面中的每一个方面,要么定义成一个约束,你必须在这个约束中进行操作,要么定义成与项目成功对应的驱动,或者定义成通向成功的自由程度,你可以在一个规定的范围内调整。相关的详细信息,请参照我的《创建一种软件工程文化》(Creating a software Engineering Culture)(Dorset House,1996)中的第一章。项目的假设和约束(PP)
3、定义产品发布标准
在项目早期,要决定用什么标准来确定产品是否准备好发布了。你可以把发布标准基于:还存在有多少个高优先级的缺陷、性能度量、特定功能完全可操作、或其他方面表明项目已经达到了它的目的。不管你选择了什么标准,都应该是可实现的、可测量的、文档化的,并且与你的客户指的“质量”一致。项目的具体验收标准(PP)
4、沟通承诺
尽管有承诺不可能事件的压力,从不作一个你知道你不能保证的承诺。和客户和管理人员沟通哪些可以实际取得时,要有好的信誉。你的任何以前项目的数据会帮助你作说服的论据,虽然这对于不讲道理的人来说没有任何可真正的防御作用。沟通计划,关键依赖和承诺(PP)
5、写一个计划
有些人认为,花时间写计划还不如花时间写代码,但是我不这么认为。困难的部分不是写计划,困难的部分是作这个计划——思考,沟通,权衡,交流,提问并且倾听。你用来分析解决问题需要花费的时间,会减少项目以后会带给你的意外。项目计划(PP)
6、把任务分解成英寸大小的小圆石
英寸大小的小圆石是缩小了的里程碑。把大任务分解成多个小任务,帮助你更加精确的估计它们,暴露出在其他情况下你可能没有想到的工作活动,并且保证更加精确、细密的状态跟踪。工作结构分解WBS (PP)
7、为通用的大任务开发计划工作表
如果你的组经常承担某种特定的通用任务,如实现一个新的对象类,你需要为这些任务开发一个活动检查列表和计划工作表。每个检查列表应该包括这个大任务可能需要的所有步骤。这些检查列表和工作表将帮助小组成民确定和评估与他/她必须处理的大任务的每个实例相关的工作量。项目进度计划 (PP)
8、计划中.在质且控制活动后应证百赐改工作
几乎所有的质量控制活动.如测试和技术评审.都会发现缺陷或其他提高的可能。你的项目进度或工作细分结构,应该把每次质量控制活动后的修改,作为一个单独的任务包括进去。如果你事实上不用作任何的修改,很好,你已经走在了本任务的计划前面。但是不要去指望它。项目质量计划,质量保证计划 (PPQA)
9、为过程改进安排时间
你的小组成员已经淹没在他们当前的项目中,但是如果你想把你的组提升到一个更高的软件工程能力水平,你就必须投资一些时间在过程改进上。从你的项目进度中留出一些时间,因为软件项目活动应该包括做能够帮助你下一个项日更加成功的过程改进。不要把你项目成员可以利用的时间100%的投入到项目任务中,然后惊讶于为什么他们在主动提高方面没有任何进展。
10、管理项目的风险
如果你不去识别和控制风险.那么它们会控制你。在项目计划时花一些时间集体讨论可能的风险因素,评估它们的潜在危害,并且决定你如何减轻或预防它们。要一个软件风险管理的简要的指南,参见我的文章“Know Your Enemy:Software Risk Management”(Oct.1998)。风险管理(RSKM)
11、根据工作计划而不是日历来作估计
人们通常以日历时间作估计,但是我倾向于估计与任务相关联的工作计划(以人时为单位)的数量,然后把工作计划转换为日历时间的估计。这个转换基于每天我有多少有效的小时花费在项目任务上,我可能碰到的任何打断或突发调整请求,会议,和所有其他会让时间消失的地方。
12、不要为人员安排超过他们80的时间
跟踪你的组员每周实际花费在项目指定工作的平均小时数;实在会让人吃惊。与我们被要求做的许多活动相关的任务切换的开销,显著地降低了我们的工作效率。不要只是因为有人在一顶特定工作上每周花费10小时,就去假设他或她可以马上做4个这种任务,如果他或她能够处理完3个任务,你就很幸运了。项目成员角色和分工,角色责任矩阵
13、将培训时间放到计划中
确定你的组员每年在培训上花费多少时间,并把它从组员工作在指定项目任务上的可用时间中减去。你可能在平均值中早已经减去了休假时间、生病时间和其他的时间,对于培训时间也要同样的处理。培训计划 (PP,OT)
14、记录你的估算和你是如何达到估算的
当你准备估算作的工作时,把它们记录下来,并且记录你是如何完成每个任务的。理解创建估算所用的假设和方法,能够使它们在必要的时候更容易防护和调整,而且它将帮助你改善你的估算过程。估算和度量 (PP,MA)
15、记录估算并且使用估算工具
有很多商业工具可以帮助你估算整个项目。根据它们真实项目经验的巨大数据库,这些工具可以给你一个可能的进度和人员分配安排选择。它们同样能够帮助你避免进人“不可能区域”,即产品大小,小组大小和进度安排组合起来没有已知项目成功的情况。Software Producitivity Centre(www.spc.ca)公司的Estimate Pro是可以一试的好工具。估算和度量 (PP,MA)
16、遵守学习曲线
如果你在项目中第一次尝试新的过程,工具或技术,你必须认可付出短期内生产力降低的代价。不要期望在新软件工程方法的第一次尝试中就获得惊人的效益,在进度安排中考虑不可避免的学习曲线。项目计划中的方法,工具和技术 (PP)
17、考虑意外缓冲
事情不会象作项目计划的一样准确的进行,所以你的预算和进度安排应该在主要阶段后面包括一些意外的缓冲,以适应无法预料的事件。不幸的是,你的管理者或客户可能把这些缓冲作为填料,而不是明智的承认事实确实如此。指明一些以前项目不愉快的意外,来说明你的深谋远虑。
18、记录实际增况与估算情况
如果你不记录花费在每项任务上的实际工作时间,并和你的估算作比较,你将永远不能提高你的估算能力。你的估算将永远是猜测。度量分析 (MA)
19、只有当任务100%完成时.才认为该任务完成
使用英寸大小的小圆石的一个好处是,你可以区分每个小任务要么完成了,要么没有完成,这比估计一个大任务在某个时候完成了多少百分比要实在的多。不要让人们只入不舍他们任务的完成状态;使用明确的标准来判断一个步骤是否真正的完成了。增量和迭代,每日构造,持续集成
20、公开、公正地跟踪项目状态
创建一个良好的风气,让项目成员对准确地报告项目的状态感到安全。努力让项目在准确的、基于数据的事实基础上运行,而不是从因为害怕报告坏消息而产生的令人误解的乐观主义。使用项目状态信息在必要的时候进行纠正操作,并且在条件允许时进行表扬。
这些提示不能保证你的成功,但是它将帮助你在你的项目上获得一个坚实的把手,并且保证你做了所有你可以做的事来让项日在这个疯狂的世界上成功。项目跟踪和控制 (PMC)
- 作者: Jo Ja Yong 2006年07月10日, 星期一 10:34 回复(1) | 引用(0) 加入博采
对国内房地产市场不要太乐观
- 作者: Jo Ja Yong 2006年03月22日, 星期三 09:32 回复(0) | 引用(0) 加入博采
MyEclipse+struts+Hibernate配置开发
说明:
这个手册只是为初学者制作的环境配置和快速开发的一些基本方法,为的是广大爱好者能快速上手,少走我走过的弯路,里面没有任何关于java模式和其他相关的说明。本人水平有限,也没有能力去讨论关于模式设计和开发细节的一些内容。
建议:
如果你还不清楚struts和hibernate的一些基本原理,希望能先去了解一下这方面的相关内容。
推荐:
Hibernate中文手册》作者认为要学Hibernate看这个就足够了,里面几乎包括了所有的细节,不过可能不太适合快速入门。
地址:http://www.hibernate.org/hib_docs/v3/reference/zh- cn/html_single/
关于struts的资料就很多了,这里推荐一个可以下载一些入门教程的网站。
地址:http://www.wnetw.com/jclub/index.jsp
强烈建议入门的朋友先了解一下基本的原理!否则本文可能对你没有任何帮助。
相关工具下载:(注意版本)
mysql5.0 http://www.mysql.org
eclipse 3.1.1 http://www.eclipse.org
myeclipse4.0.3 http://www.myeclipseide.com
tomcat5.5
安装:
关于tomcat和mysql的安装就不多说了,需要注意的是最好保证你的 jdk是1.5的版本,并配置好你的环境变量,不然可能会遇到一些问题。
把eclipse解开,再去安装刚下载的myeclipse,在安装的时候需要把路径指定到刚才解开的eclipse上,由于myeclipse是个收费软件,所以需要注册。不过一般按照Chinese的习惯,去google一个注册码就可以了:}
开发环境部署:
好了,现在保证你的mysql和tomcat服务能够正常启动,myeclipse能够正常打开(如果不能,可以去找一下相关的说明或者给作者留言)。下面我们就要开始真正的开始部署一个传说中的tomcat+struts+hibernate+mysql结构的工程了!(faint!前言就写的我好累)
首先,在myeclipse里新建一个工程。在左边的Package Exporler面版里点右键选择new->project…
在跳出菜单里选择MyEclipse->J2EE Projects->Web Project。
点击next后进入如下画面:
工程名为:test
结束后点击Finish。
好了,如果成功的话你就会在 Package Exporler里看到一个新的test工程!现在我们先配置一下数据库方面的东西。首先在你的mysql 里建立一个数据库webases,再在里面新建一个表admin,里面三个字段分别为id,name,password其中id为自动取值的主键(mysql具体的操作可以自己找资料,不是本文涉及范围)。
再回到myeclipse ,选中window->Open Perspective->Other…
可以看到现在跳出一个名为Select Perspective的菜单,在里面选中MyEclipse Databases Exporler,可以看到现在到了下面的页面。
按以上图示输入相关字段后点击Finish便建立了一个数据库连接,在新出现的JDBC for Mysql上点右键,选择Open connection…,确认用户名和密码正确后点OK,如果一切顺利的话你会看到下面的画面:
这说明你已经和数据库建立了正确的连接。现在我们再回到window->Open Perspective- >Other…里的MyEclipse,也就是我们刚进来的时候看到的画面。
右键点击你刚建立的工程 test并选择MyEclipse->Add struts Capabilities…在跳出的菜单里按照如下输入并确定:
好了,现在你已经为你的工程增加了struts,接下来和上面一样在右键工程后选择MyEclipse- >Add Hibernate Capabilities…一路确定下来为你的工程添加Hibernate。(为方便起见我们在选择路径时把HibernateSessionFactory.java放在了src/com下面,其实最好建立个单独的目录如 src/com/hibernate)
为了更好的演示我们不建立通常的登陆页面而是建立个注册页面。选择 src目录下的hibernate.cfg.xml文件。照如下填写并保存。这样hibernate就为你建立了数据库的连接池。
下面我们再选择WebRoot/WEB-INF/struts-config.xml文件,在画面中点击右键选择new- >Form, Action and JSP。如下填写
再选择JSP选项,如下
最后选择Finish。
再新建一个一个success.jsp的页面,
在刚才struts- config.xml文件里右键选择addAdmin选择Properties,在菜单里选择Forwords,再点add,如下图填写
最后你的struts-config.xml就是下面这个样子:
下面我们转到hibernate。换到刚才我们建立数据库的页面,选择你的admin的表点右键选择Create Hibernate Mapping。选择好打包路径后选择Finish。如图:
在你刚才选择的路径下(我为方便是src/com/yourcompanyname/)下新建立的文件 AdminDAOFactory.java文件并输入以下内容:
package com.yourcompanyname;
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hibernate.SessionFactory;
public class AdminDAOFactory {
Session session;
Transaction tx;
public void add(Admin admin) throws HibernateException {
/**
* Creation Date: 11-17-2005
* TODO Add a new admin user.
* @param An object of Admin
* @return void
* @author Coder Guo
*/
try {
session = SessionFactory.currentSession();
tx = session.beginTransaction();
//Add a new admin
session.save(admin);
tx.commit ();
}catch(HibernateException e){
throw e;
}finally{
if (tx!=null) {
tx.rollback();
}
SessionFactory.closeSession();
}
}
}
再打开com.yourcompany.struts.action下的AddAdminAction.java添加(其中如果有错误选中好按ctrl+shift+o自动添加包)
public class AddAdminAction extends Action {
// --------------------------------------------------------- Instance Variables
// --------------------------------------------------------- Methods
/**
* Method execute
* @param mapping
* @param form
* @param request
* @param response
* @return ActionForward
* @author Coder Guo
*/
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
AddAdminForm addAdminForm = (AddAdminForm) form;
// TODO Add a new admin
Admin admin = new Admin();
admin.setName(addAdminForm.getName ());
admin.setPassword(addAdminForm.getPassword ());
AdminDAOFactory adminDAO = new AdminDAOFactory ();
adminDAO.add(admin);
return mapping.findForward("success");
}
}
再打开com.yourcompanyname.struts.form下的AddAdminForm.java,修改(如果有错误按照上面说的方法导入包)
public ActionErrors validate(
ActionMapping mapping,
HttpServletRequest request) {
// TODO Auto-generated method stub
ActionErrors errors = new ActionErrors();
Session session = SessionFactory.currentSession();
Transaction tx = session.beginTransaction ();
Query query = session.createQuery("select admin from Admin as admin where admin.name = '" + this.name + "'");
Iterator it = query.iterate ();
if (it.hasNext()){
errors.add ("addAdmin.err.name",new ActionMessage("form.addAdmin.err.name"));
}
tx.commit();
SessionFactory.closeSession ();
return errors;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
// TODO Auto-generated method stub
this.name=null;
this.password=null;
}
再打开com\yourcompanyname\struts下的ApplicationResource.properties在这里面添加错误信息:
Form.addAdmin.err.name=err
最后,(汗,好累啊-_-!)打开addAdmin.jsp修改成如下:
<%@ page contentType="text/html; charset=utf-8"%>
<%@ page language="java"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<script language = "javascript">
<!--
function check(){
if (loginForm.userName.value == "" || loginForm.password.value == ""){
alert("请输入完整的信息!");
loginForm.userName.focus();
return false;
}
}
//-->
</script>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html:html>
<head>
<html:base />
<title>login.jsp</title>
<link href="css/webcss.css" rel="stylesheet" type="text/css">
<meta http-equiv="pragma" content="no- cache">
<meta http-equiv="cache-control" content="no- cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http- equiv="description" content="This is my page">
</head>
<body>
<center>
<p> </p>
<p> </p>
<table width="300" border="0" cellpadding="0" cellspacing="0">
<html:form action="/addAdmin" focus="name" method="GET">
<tr align="center" valign="middle">
<td colspan="2" class="typt_normal">新增管理员</td>
</tr>
<tr>
<td width="100" align="center" valign="middle" class="typt_normal">名称: </td>
<td width="200" align="left"><html:text property="name" styleClass="text_s"/><html:errors property="addAdmin.err.name"/></td>
</tr>
<tr>
<td width="100" align="center" valign="middle" class="typt_normal">密码: </td>
<td width="200" align="left"><html:password property="password" styleClass="text_s"/></td>
</tr>
<tr>
<td colspan="2" align="center" valign="middle"><html:submit value="提交" onclick="return check ();"/><html:reset value="重置"></html:reset></td>
</tr>
</html:form>
</table>
</center>
</body>
</html:html>
其中可以看到如何在struts的标签中使用javascript的方法。
配置好myeclipse于tomcat的连接。在window->Preferences做如下设定:
在项目文件点右键->“myeclipse”->“Add and remove project deployment”,如下图:
好了,我们的配置工作基本结束了,在myeclipse上开启tomcat服务
现在打开浏览器,输入
http://127.0.0.1:8080/test/addAdmin.jsp就可以看到你的jsp页面了
- 作者: Jo Ja Yong 2006年03月2日, 星期四 16:34 回复(2) | 引用(0) 加入博采
多收了三五斗(楼市版)
- 作者: Jo Ja Yong 2006年03月2日, 星期四 09:13 回复(0) | 引用(0) 加入博采
超级搞笑的33个冷笑话
| 超级搞笑的33个冷笑话!!! 1.烤肉时最不希望发生的事:1.肉跟你装熟;2.木炭耍冷;3.蛤蚧搞自闭;4.烤肉架搞分裂;5.火种没种;6.肉跟架子搞小团体;7.香肠肉跟你耍黑道;8.黑轮爆胎;9.葱跟你装蒜;10.玉米跟你来硬的! 2.你说:我爱你521 +又说:每一天365 --------------------------- 结果呢= 886 3.表演系排小品。 男生:"本来咱俩这事儿好好的,都是让你妈给逼的。"女生:"是你妈逼的!"男生:"你妈逼的!"女生:"你妈逼的!!"男生:"去你妈的,不排了,不排了,这叫什么台词儿啊?!!" 4.某对男女在校外租房。暑假MM去外地实习了,GG还在房里住着。MM实习归来,见房间里脏兮兮的,显然几星期都没打扫过,于是就勤快地来了个大扫除。晚上GG回来了,问:"桌上的灰怎么不见了?上面还记着电话号码呢……" 5.第一题:黄花岗起义时,开第一枪的人是谁? (a)黄兴(b)宋教仁(c)孙文(d)罗福星第二题:黄花岗起义时,开第二枪的人是谁? (a)黄兴(b)宋教仁(c)孙文(d)罗福星第三题:黄花岗起义时,开第三枪的人是谁? (a)黄兴(b)宋教仁(c)孙文(d)罗福星这三题的答案都是(a)因为教育出版社的教材里有一句话:"黄兴朝向空中鸣了三枪揭开了黄花岗起义的序幕!" 6.科大有个学生,马上大四毕业了,依然没有工作,没有女友。于是,他去算命。 "你啊,将一直穷困潦倒,直到四十岁……"学生听了眼睛一亮,心想有转机,于是问:"然后呢?""然后你就习惯这样的生活了……" 7.美国《西雅图时报》很负责任地写下"超级女声"的英文全称:Mongolian Cow Sour Sour Yogurt Super Girl!(蒙古的牛∷崴崮蹋崛镸ongolian Cow Sour Sour Yogurt =蒙牛酸酸乳)该报网站第一个回帖者留言:记者大哥,请问你四级过了没有? 8.我这一生只被电影感动过三次: 第一次,是我很小的时候看《妈妈再爱我一次》,我深深地被感动了;第二次,看《大话西游》,我深深地被孙悟空和紫霞的爱情故事感动了;第三次,看《十面埋伏》,当我看到章子怡那顽强的生命力时,我第三次被深深的感动了! 9.构建和谐社会的四大要素:一.在自然界不要跟天斗;二.在国际上不要跟美国斗;三.在中国不要跟GC党斗;四.在家里不要跟老婆斗。 10.中国的"新三座大山":教育改革产业化,医疗体制商业化,房地产业商品化! 近期改革热点结论:教改把家里二老逼疯,医改提前给你送终,房改把百姓腰包掏空! 11.中国人民为: 国家大剧院骄傲——到30亿的国家大剧院看戏是每个国人的梦想! 为CCTV新大楼骄傲——50亿的新大楼让多少国人看电视时心潮澎湃! 为上海磁悬浮骄傲——中国人用600亿解决30公里的交通问题多么令世人骄傲! 为中共纪检委骄傲——让5000多贪官带走400多亿美金到国外! 12.手机欠费,遂拨1860咨询如何缴费,答复:对不起,您的电话已停机,详情请垂询1860。 13.人大代表去化验科,护士指着前方一牌说:"非本科人员不得入内!"那人大怒,骂道:"我就化验个尿,还TMD要本科文凭!!!" 14.四川猪瘟时,某乡电视台的宣传口号——宰杀病猪等于自杀! 15.艺术节我们要跳一个巨可怕的集体舞——需有急速摔倒、高抬腿等暴烈难度的动作。结果没练几天大家就都受不了,有的浑身是青,有的肌肉拉伤……我右腿就伤得非常严重,根本不听使唤!今天到三楼上课,天啊,我简直就是把右腿直着一阶一阶的往上提送。最可气的是——正走着,只听后面两个女孩低声嘀咕道:"还是大城市的学校比较正规些,这要是在我们老家,小儿麻痹的根本不能上学!!" 16.问:国际米兰球迷看到自己球队夺得意甲联赛、意大利杯、欧洲冠军杯、丰田杯冠军后干什么? 答:关上PS2后上床睡觉! 17.大学生总喜欢新鲜刺激的事物。譬如打牌,输的要喊"我是猪"或是抱电线杆子喊"我的病有救了"之类的壮举。你看人家汕大多有创意——宿舍打牌,谁输了谁要在半夜十二点独自上后山抄十个墓碑的碑文回来!最要命的是第二天早上大家一起上山找墓碑校对!!? 18.看一个人的心术,要看他的眼神。 看一个人的身价,要看他的对手。 看一个人的底牌.要看他身边的好友。 看一个人是否快乐,要看他清晨梦醒时的一刹那表情。 看一个人的胸襟,要看他如何面对失败及被人出卖。 两个人的关系(男女),要看发生"意外"时,另一方的紧张程度…… 19.大家问我男人应当追求什么?我回答:金钱和美女。于是,大家开始鄙视我……大家又问我男人应当追求什么?我说:事业和爱情!于是,大家开始崇拜我…… 20.饿狼觅食,听见有家人在训孩子:"再哭就把你扔出去喂狼!"可是,孩子哭了一夜……第二天早晨,狼长叹一声:"哎……人类说话不算数!" 21女:这学期我选了一门叫"应用心理学"的课耶! 男:真的啊?那快来帮我分析一下我的心理吧~女:那还不行~男:为什么? 女:因为我下学期才会选"变态心理学"这门课! 22、小时候,把"English"读成"硬给利息"的同学现在当了行长;读"因果联系"的现在成了哲学家;读"硬改历史"的现在成了领导……我读"阴沟里洗",结果今天成了卖菜的! 23、高中时家里买了电脑,找了个本电脑入门书学了学,知道了exe文件是executable的缩写,bmp文件是bitmap的缩写,bat文件是batch的缩写。后来,一个同学来我家的时候往电脑里拷了几个文件,从那以后的相当长的一段时间里,我都认为jpg文件是"japanese girl"的缩写…… 24、一早起床用高露洁致癌牙膏刷牙,给儿子冲一瓶碘超标的雀巢奶粉,然后自己喝杯过期的光明牛奶,吃几个超标面粉做的馒头,夹点臭水池里面腌的榨菜。准备坐公交吧,坐车人真多,手机没放好,不小心被一个小新疆"借"过去了。中午跟同事一起到肯德基吃顿苏丹红炸鸡,下午给老婆打电话,约她到新开的菜馆吃地沟油炒的菜,其中有一盘避孕药催大的香辣鳝鱼丝,一个牛肉毒粉丝,两个四川资阳猪肉大包子,老板上了一杯重金属超标100倍的碧螺春茶,再喝点含甲醛的啤酒。晚上,保姆打电话说因为矿难在井里出不来,叮嘱我别忘了做掺入白蜡油大米的米饭,别忘了做个敌敌畏泡过的金华火腿小菜,别忘了给小孩冲阜阳产的奶粉,别忘了给大人冲几杯还是金华那里产的糖精水拌银耳燕窝……如果能从矿井平安里出来,一定给全家带温州产的优质纸皮鞋,最后再提一下,千万别忘了买西安的福利彩票! 嘿,这小日子过的,那叫一个幸福! 25、某学生在水木某版面发了一篇《清华大学保持*员先进性教育活动近期安排》,该版面的版主回复:请贵党成员不要污染版面,否则删文,封ID,谢谢合作!(超冷!) 26、一日深夜,偶辗转反侧,夜不能寐,遂发短信给友寝一姐妹:"郁闷中,陪偶聊会吧。"不一会,姐妹回信:"好吧,想聊什幺?话题由你定!"偶想了想,乐着回复道:"那偶们就聊沉重点的话题吧,比如说——你的体重!"一阵沉默过后,姐妹回短信,上面写道:"这也太沉重了吧,那我们还是聊点肤浅的吧,比如说——你的智商!!!" 27、金钱不能买到一切,但是可以买到我;暴力不能解决一切,但是可以解决你~:) 28、想当年,我拳打南山敬老院,脚踢北海幼儿园,一米以下全部放倒,我在太平间里一跺脚,"不服的给我站起来!"没有一个敢喘气的~~ 29、我虽然拥护你说话的权利,但我誓死不赞成你的观点。 30、医学院GG: 学医苦,学医累,学医费用还挺贵;细胞组织都要背,解剖杀人皆要会。 一手笔,一手刀,谁不服我谁残废。不怕僵尸不怕鬼,死人看多无所谓。 长夜无妻伴尸睡,多吃人脑能开胃!(瀑布寒……) 31、QQ一美女说自己瓜子脸,特漂亮。 寝室老大淌着口水出去约人家见面……。 夜,老大推门就扑倒在床上墩足号啕大哭:"西——瓜子脸也就罢了,关键问题是她尖头朝上啊!!!"…… 32、大学时代第一次聚会选择在动物园,大家共同的理由是:只有在这里,才能感慨到自己还是个人碍… 33、MM边照镜子边高兴地对我说:我真的瘦了,你看我下巴都尖了! 偶看看她脸,鼓起勇气说道:嗯,确实每个下巴都尖了…… |
- 作者: Jo Ja Yong 2006年02月28日, 星期二 09:41 回复(0) | 引用(0) 加入博采
我的看楼日记(广州)
盼望着盼望着,终于开始计划自己供楼了。将自己和BF的总收入小小计算了一下,心里暗自窃喜,嗯,应该一套小三房的首期是没问题的了。于是乎趁着新年正好BF有空,就拖着他开始看楼了。原计划是过完大年的前三天,初四再开始的,但实在按捺不住那种激动而又冲动的心情,初二便踏上了征程。这里事先声明一下,我这个人属于比较主观和情绪化的类型,所以里面所提到的纯属个人喜好,大家看看就好了,千万别砸我啊。
2006年1月30日(大年初二)华景新城――小城之春――东方新世界――隽园
原本是打算起个大早过去的,所以前一天晚上调了好几个闹钟,跟BF发誓一定不会赖床。事实证明我的控制力远远比我想象中要低,睡觉的劲头又远远比我想象中要高,到了实在不能再赖的时候一看时间,11点多了。匆匆洗漱完毕,随便吃了点东西,准备出发。这时才傻眼了,与BF两个人站在大门口面面相觑:我们该上哪呢?之前只是嚷嚷着要看楼,却一无所知,毫无计划。商量研究了老半天,最后决定,上宏城广场看看,那里似乎是看楼车云集的地方。
下午2:30分,到达宏城广场,一路走过去,手里被塞满了各楼盘的资料。我们似模似样的研究了老半天,发现似乎没有一个心水的地方。其实原本我们也没有计划过买哪里,只是前些天去了一个同学在天河北的新房,特喜欢,便一心想去看看天河。结果那里似乎是没有楼巴去天河北一带的。BF说,你就傻了,天河北这么近,怎么会有楼巴呢。想想也是,没办法,极不情愿的跳上了华景新城的看楼车,想着反正是第一次,就随便转转吧。
说实话,我一开始对天河公园一带的盘没什么好感,主要是嫌远。因为现在就住东山,家在地铁站附近,交通生活都是超方便,所以不大习惯那么远而且没有地铁的地方。真的是远,也不知是过了多久,BF说到了,看,那里掉头进去就是了。结果楼巴似乎没有要掉头的意思,只是一直开一直开。坏了,该不是遇上什么黑车了吧,呵呵,乱想一下。又开了好远,到了一个叫做骏景花园的地方才停下来,原来这里也是合生的盘,有个人不知是看楼的还是业主要在这里下车。然后又兜兜转转的回到了华景的售楼部(司机大佬居然说没有车回去了,只能自己坐车,郁闷)。那个sales估计看我们是第一次来,而且看起来也不大像有购买力的,所以不怎么搭理我们,简单介绍了下,就让我们自己去看样板房了。说实话,因为一开始就抗拒这么远的地方,加上兜了这么一圈情绪不好,再加上sales不是非常好的态度,所以到现在我已经完全不记得样板间什么样子的了,唯一的感觉就是这里好远好吵,因为里面的大马路都是车来车往的,所以决定肯定不会买这里了。
看完这里BF就已经没什么兴趣再看了,嚷嚷着要回去,在我的坚持下又往回走了一段。忘了补充一下,因为他说他有个同事是买在东方新世界的,然后当时路过那里他指给我看了一下,就一眼,我就对这里产生了些许的好感,因为外观看起来不错,而且楼下就是百佳,所以一定要求回去那里看看,尽管BF再三强调那里早就卖光了,我还是抱着一丝希望的往那边走。
走啊走,走啊走,这条华景路可真是长,路过一间7-11还是C-store的便利店,进去吃了个雪糕两串鱼旦,精神了点,继续走。临到路口了,看见有个好大的广告写着“小城之春,直入××米”,依稀想起好像在地铁站经常见到这个楼盘的广告,于是就跑过去看看。虽然只是左转进去了一点点,但却和外面是两个完全不同的环境,这里要安静多了,还能听见鸟叫。鸟语花香,这不正是我想要的吗?于是来劲了,一扫刚刚的没精打采,兴冲冲的直奔售楼部。依然是没什么人搭理我们,那些sales都忙着在给一些一家好几口的,或者一些中年的师叔师奶们介绍。没关系,我们自力更生。自己拿了资料自己研究模型,然后又自己冲上去看样板间。户型还是不大记得了,应该是还不错吧,但上到100平米的都有个入户花园,BF不喜欢,说浪费空间,我是觉得无所谓,甚至说是有些喜欢。用BF的话说就是:你们这些女人,就看中外表,一点都不注重实用。呵呵,题外话。装修一般般,居然还好意思说是1200一平米的标准,我看有500就差不多了。这里的均价是7200,补充下刚刚华景的均价大概是6800。心里暗叫,居然这么远的地方都这么贵了,没天理啊。小城之春似乎是几栋单体楼,楼下可能会有小范围的绿化吧,好像首层是要做商铺的,这点我就不是很喜欢了。虽然是第一次看还下不了什么定论,但看BF的意思是肯定不会选择这里的了,所以,别了,我第一套有好感的房子,别了,我的鸟语花香,别了,我的入户花园,别了,我的小城之春。
继续往前走,向东方新世界进发,BF一个劲的说肯定没了肯定没了,看我是多么执着的人啊,还是一定要去看。越来越近越来越近,哈哈,我偷笑了,远远的就望见新世界那里挂着一副大大的广告“东方新世界•锦逸,公开发售,电话:××××××××”我是得意的笑啊得意的笑,BF没辙,一脸无奈的只好跟着我四处找售楼部。左转一圈,没有,右转一圈,还是没有。没办法了,打电话去问,居然没人接。这下轮到BF得意的笑了,说,这个广告肯定是挂了好久的了,你看,我说卖完了吧你还不信。唉,刚刚转的时候又把它看了一遍,小区的规划管理似乎都不错,越看越喜欢啊,只可惜没了。
最后一站隽园,我有种不达目的誓不罢休的感觉,千辛万苦的走过去(其实离新世界很近的,只是刚刚折腾了一阵没了气力),居然吃了闭门羹,初四才开门。又是狂郁闷一阵。眼看天色渐晚,也没力气再坚持下去了,便只好回家了。
2006年1月31日(大年初三)珠江帝景苑(克莱尔国际公寓)――帝景华苑――泓景花园――(途径金海湾)――大学印象――尚海――瀚林水岸――晓港美院――江南新苑
回去后跟BF的父母描述了一番,老爷子也来了兴致,要第二天跟我们一起去看。于是,初三,我们便和他一起踏上了看楼的艰苦旅程。他爸一直很喜欢珠江帝景。对于帝景我是早有耳闻了,好像开发了有四五年了吧。当初有个朋友买在这里,那时还是5000多一方。买的那户并没有临江,只能斜斜的望到那条支流的小河涌,当时他还很痛心疾首,没有抢到前面那些。那时号称一线江景的第一排都差不多卖到快一万一方,仍是很多人买。可是计划追不上变化啊,据说市政规划前面起了条大路,从琶州一直延伸过来。现在不仅江景给破坏了,还会比较吵,于是我那个朋友又偷笑了,呵呵。前几期靠里面的那些中高层应该早早就卖完了,现在卖的大概是会所后面那三栋高层的,应该是帝景将来最靠近地铁站出口的地方了,超贵的,好像叫什么克莱尔国际公寓,10000多一平方。老爷子已经去看过好几次了,非说这里好,什么临江,什么观光塔,什么近地铁,还有什么未来的领馆区也在附近,说将来肯定升值,一定要带我们去看看。呵呵,我心想,咱买不起难不成还看不起吗,反正老爷子高兴,就去见识下呗。
说是靠近地铁站(赤岗塔站),但楼盘附近的那个出口根本还未开通,只好走了另一个出口。那叫一片荒凉啊,出来就是个什么破旧不堪的船厂,走了好久的荒草丛生的泥巴路,终于来到了。合生不愧是大公司,早就听说这里很气派,今日一见,果然非同凡响,和刚刚完全是两个世界。面对着的就是个罗马式建筑的大会所,绿化、喷泉什么的,都做的挺漂亮。社区的范围很大,远远的看见三栋高高的楼在建,心想这就应该是那个克莱尔吧。进去问了下sales,好像19层以下的9500起价,19以上的就都要上万了,而且似乎都是大户型,大概是一百三四十方起吧。穿过一些小水池小花园,去看了看样板房。奇怪,我现在怎么不记得是什么样子的呢,而且都怀疑自己是不是去看过了。印象中应该还是不错的,毕竟是大公司的盘。(后来还在和朋友讨论,为什么像合生之类的盘所有的楼都是整整齐齐的一排排一个样,而有些其他的盘就是千奇古怪的,似乎每户都不一样。然后得出的结论就是,像大公司一般圈地范围比较大,所以想建成什么样就可以建成什么样。而有些面积比较小的盘,因为受限制所以只能有多少地起多大的楼,而且要尽可能的利用好一切可利用的面积,户型就自然没有那么方正了。)可能是因为想着根本不会也不可能更没能力买这里,所以没有很留意吧,纯属参观。
出来帝景再往前,大概到路口那里有个叫帝景华苑的盘,也是合生的,老爷子看样子又是去看过的了,呵呵,无妨,跟着再去看看。一个字,好,两个字,喜欢,三个字,很喜欢。小区门口就有公交车站,看了下,有去我单位的车,不错。而且楼前的一片绿化都看起来很舒服,正对着赤岗这里的一片大草地,据说领馆区就建在对面。这里很僻静,又不会像珠江帝景那样要往里走那么老远。单是看外观我就喜欢上了。进去一问,呵呵,意料之中,又是我们买不起的。靠里面那栋好像便宜一点的已经卖完了,外面这栋9500起价,最小的户型都是140多。买是肯定买不起了,还是去看了看样板间。我喜欢的那户厅里有个小小的两三级的楼梯上房间的,我比较喜欢这种感觉,房子很大,饭厅的一整面墙上装了面镜子,就显得更大了。于是想着以后我的房子也要这么装修。因为是二楼,外面送了一个平台做了个小花园,好漂亮,真喜欢,一问,二楼的因为送了这个平台所以要去到15000一方。不过有一点不好的似乎有一个厕所和一间房的采光不大好,黑糊糊的,其他都很漂亮,不过价钱也是相当漂亮啊。一样,还是纯属参观。
这里再补充下,出来帝景是先去看了对面一个叫泓景花园的地方的,不过也是初四才开市。心想五一十一都是买楼黄金周,怎么偏偏春节就这么冷清呢,看来我们真是生手,没选对时候。
尽管是第二次吃闭门羹了,兴致依然未减,于是向中大北门进发,BF对那个叫做大学印象的地方似乎挺感兴趣。路过金海湾,真想哭啊。这样的地方,这样16000起价的地方,居然还有1800平方的单位,居然还有8米层高的单位。估计人家一个厕所就能住下我们全家了。为什么呢,为什么呢,为什么就这么多有钱人呢,唉!!!
感叹归感叹,楼还是要看。大学印象,关门,尚海,关门,翰林水岸,还是关门!!!BF说,还是算了,反正这里给我的感觉也不大好,楼下都很杂,环境也不好,还是去其他地方吧。我忽然想起总是在报纸上看到什么晓港那里有个小复式的楼,便提议去那里看看。也不知道具体位置,便打着车往那边走。还是很容易找的。应该就是晓港美院吧,一栋单体楼竖在那里,而且也关门。无所谓了,反正我也不喜欢单体的。又掉回头,BF想去看中大西门对面的江南新苑。说实话我是不喜欢那里,旁边就是布匹市场,总觉得比较乱。但想来也没其他地方去了,便去看看吧。其实外面看上去还不错,而且这里近百佳近地铁近中大,无奈还是关门。(后来听说这里也要8000多一方了,而且应该也卖完了。)所以,只好,回家了。
2006年2月2日(大年初五)中海观园国际――马赛国际公寓――星汇雅苑――东方新世界东逸花园――隽园――历德雅舍
有了前两次的惨痛教训,这次决定打个有准备的仗。所以初四的晚上就在网上搜寻了下相关讯息,列出了一张清单,好家伙,任务很艰巨啊,有十几二十个那么多。本来是想去天河北的协和新世界,因为前两天刚有朋友推荐,但没有直达车,所以打算去赛马场那边看看。但还没有开到那边,忽然看到路边有栋在起的楼,就拉着BF下了车。这里打个茬,往后的几天我都是这样,只要一看见路边有棚子就来劲,就有冲过去看的冲动,呵呵,有点看楼综合症了。下车后发现,怎么也找不到入口,又走了好长一段才找到,原来是到了珠江新城的中海观园国际。对于这个,网上的报价是写着8500的均价,就是这个价我们也是不考虑的,但都已经进来了,看看也无妨。七拐八弯的进了售楼部,心里祈祷着千万别又关门了,还好,开着。珠江新城的环境自是没话说,而且中海的盘我向来都有好感,所以尽管到处都在建,但售楼部门口已经建好的一个小花园还是透着它的大气和不一般。果然,进门后,售楼人员还是一样的不搭理我们。自顾自的看了下模型,BF说我们找那个保安问问吧,我说干吗不找sales啊,他扮的超可爱的样子说我不敢,我怕他不理我。咱底气不足啊,估计这里又是超贵的,怕又受人家白眼。呵呵,保安是肯定不知道的,我还是鼓足勇气去问了下sales,管他呢。人家看都不怎么看我的说这两天还没开市,均价在13000-16000。心里狂晕一下,表面上装的很轻松很随意的样子又问了几个问题,要了份资料。Sales似乎不是很愿意给,因为是厚厚的印刷很好的一本,成本估计也不便宜,看我们样子也是买不起的,无谓浪费。但还是犹豫了下给了我。拿了资料匆匆出门,一出去就和BF两个狂笑不止,他说,你刚刚装的好鬼镇定啊。笑归笑,心里还是有些气的,屡屡受歧视的滋味可不是那么好受。我跟BF开玩笑说,咱掏两万块的定金出来砸死他,BF说,你以为两万块就能吓住人家啊。我说,那我们全部换成1块的硬币,总能砸死他了吧。后来,只要一遇到不热情的sales,我就会说,咱掏××块砸死他!!!
其实本来还有个叫做中海花城湾的地方,网上报价8000,本来还想看来着。经历了这么一次发现,网上的报价信不得啊。想想也是,珠江新城8000多?做梦还差不多。不过在观园国际那里看到了花城湾的规划,离市政规划中的两座高塔挺近,位置真的不错啊。
接着就是马赛国际公寓,售楼部是在谭村路进去的地方。本来以为谭村是和冼村一样人多且杂的地方,但那条路还挺宽,也没什么太多人,感觉还不错。进去问了一下,大户型的已经都卖完了,只剩70多平的小户了。楼是靠近马路边的,那里还有高架,估计也会比较吵。再往前走点就是星汇雅苑,但也没开市。所以直到现在我还对那里抱着一丝的希望,好像7000多吧,用天涯有个人的说法,这是珠江新城一带他唯一买的起的楼了。但又听说开盘的时候就已经抢购一空了。那里的电话我到现在还没打通过,所以周末还是打算看看,估计就算有现在也没有这个价了吧。
受了n多次打击后,想着天河能买的起的房子估计只有天河公园了吧,所以还是打了个车去那边。因为前一天做了功课,大概知道了东方新世界的锦逸还是在售的,记下位置之后就过去了。难怪那天找不到,原来根本就和马路边的那栋不在一起,在东方三路的东逸花园里。因为不是在大马路旁了,所以这里很安静。而且位置开阔,比前面的东方新世界的楼距要宽,所以后来sales也说这里虽然交通没前面方便,也不近超市,但胜在环境好,所以卖的比前面要贵。走进售楼部,立即就有两三个sales过来招呼,感觉不错。后来跟我们的那个真的很热情,而且很专业(呵呵,我自己这么觉得),给我们介绍了大致规划后就带我们去看楼。门口还遇到个财神爷打扮的人在派利是,后来打开发现是一块金币样的巧克力。尽管不怎么样,但也能感觉到毕竟是大公司,想的就是会比别人多一些啊。
我想说,看了这么些天的楼,新世界这里是我最满意的户型了。无论是层高、朝向、楼距都很好,装修也还不错。层高是3米的,我最喜欢就是这点,因为一直嫌现在大多数房子都太矮太压抑。厨具用的是方太,开关用的好像也是个名牌,这个我就不大认识,但BF说是很不错的。我们看中的那户是南向,120多方的三房两厅。每个房间的通风采光都非常好,但是只剩下顶楼的单位,每平方去到9200,而且还是折后的特价。Sales说他们这里的确会比较贵,虽然远,交通也不方便,但小区的环境、房子空间的设计都会比较好。这话是真话,至少我也是这么觉得,但还是太贵,毕竟真不是一般的远啊。看楼途中居然还遇到一个认识的师兄,呵呵,他也是看中了我们喜欢的那个单位,心想真是巧啊。看完板房下来,sales招呼我们先坐下,然后又讲解了一番,说帮我们算算,只消一会的功夫,我们看中的三个单位的总价、均价、首期、月供等等的费用表便清清楚楚的打出来了,又让我小感叹一番,因为在此之前的确没见过这么专业的,呵呵有些没见过世面吧。但即使是后面几天看的盘,也都没有这样的,要么就是只给个总价让你自己算,要么是算个大概,即使有表也是自己拿个计算器一项项算出来填的。后来我们还让他算了一个住房公积金的贷款方案,总共能比商贷便宜五万多呢。Sales还说,因为是大公司,所以不存在资金周转的问题,所以他们的盘无论是一次性付款还是按揭打的折扣都是一样的。而且因为公积金贷款的周转比较慢,有些其他公司的盘会不愿意做,但他们都是一视同仁的。后来证明他说的是真的,的确很多盘都会有这些问题的存在。BF又问到样板房的价格,他说样板房是在最后卖的,到那时肯定会更贵,不会有一点折扣,而且因为很多人走过看过,肯定存在这样那样的问题,到时修起来麻烦很多。最重要的一点是,很多板房都是赶工赶出来的,质量肯定没那么好。我是个比较容易感情用事和轻信别人的人,所以,这个sales说了这么多,让我对他的印象很好,也很信他说的话,而且本来也挺喜欢这个盘,所以尽管它贵,尽管已经超出我们预算很多了,还是有些少的心动,不止是些少,是很心动。用BF的话说,感觉我都想下定了。把各方面都了解清楚了,而且留了电话,作了登记,因为据说我们最喜欢的那户还是有一些没有推出的,要分批推出,所以让推出了就通知。距sales说,这里的盘每推出一个单位,多则有十几个买家争,最少也有三个买家,所以一般会采取抽签的方式决定。我在这里这样说,估计又会被不少人狂砸一番,说是sales的推销策略。但我当时是相信的,这里确实好啊,如果是有钱有车一族的,这里的确是不错的选择。看看,我们不就跟那个师兄看中同一个地方了吗?sales后来还带我们在阳光家缘上查了一下他们的销售情况,确实都卖的七七八八了。在这里看过之后,我们明确了两点,一是我们原计划的八十来方的单位是肯定不够的,所以把标准提到了90-120,再就是,原来现在的首期都是要付三成的,而不是我们所预计的两成。又想哭,因为我们的积蓄能付个两成就不错了啊。
专程又去了隽园,门是开了,但还没开市,仍然是要等到初八,所以只看了下模型,问了下价,又不记得了,但也不便宜,7000多的样子吧。主要是刚刚师兄说那里不大好,虽然好像人气挺旺。后来又在网上看到各种舆论又说什么烂尾盘活的啊,又说单体楼啊这样那样的,就不打算再来了。
在那个师兄的推荐下,我们又去了东方新世界对面的历德雅舍。好像这个盘挺出名,卖的挺好。也就在中山大道的马路边,门口就是公车站,再窃喜一下,又有去我单位的车,嘻嘻。进去售楼部后,sales们也都是很忙,但还是招呼了我们。看了下他们贴出来的销售表,红点密密麻麻,也就是说也没剩几套单位了。不管它,看看再说。小区还是不错的,但就是临近马路,比较吵,抬头看,正好有驾飞机从空中掠过,飞的还不高,所以嗡嗡的很大声。进去楼里面就还好了。说实话这里户型是不错的,最好卖的是90多方的单位,虽然只有这么小,也愣是让它隔出了三房两厅两卫,比较合适像我这种又买不起大面积的,又一定要求主人房带洗手间的人,呵呵。不过还是有点挤,所以就看了看稍大些的单位,137平方的四室两厅,居然又是带入户花园,入户花园旁还有个工人间。总共也就这么大的地方,光这里就差不多去掉二十来平,还真是挺浪费。鸡肋啊,我向BF叫苦道。在后面几天看的盘中,也都是会有这种鸡肋现象,不是这里不好就是那里不好,始终没有让人非常满意的。看完后下去问了下价格,90多方的总价好像是70多万,也就是平均下来8000几一方带装修,137方的就是7000几一方的毛坯。这里我就不是很懂了,都是同一个地方的楼,干吗还两种标准呢?忘了提一下,这里sales的素质我有些不满,之前看的过程中,就听到有人向客户介绍说,你们应该都是从新世界那边过来的吧,你看,他们那里说是有1000的装修标准,其实根本不值,我们这里就不一样了,比他们那里好出许多。说实话这种明目张胆踩别人提自己的竞争手段我相当不欣赏,况且我还真没看出他们的好来。出来小区时,刚好又有驾飞机从头顶掠过,BF说,估计这里是飞机起落的必经之路。我一听,想着还是别买好了,虽然房子里还比较安静,但在小区散步时不光外面听到车水马龙的,还是不是有飞机来“轰炸”一下,我可受不了这折腾。到售楼部坐了一下,又简单了解了些情况,这时有个人凑过来问你们是不是想买楼啊,说他是这里的业主,到时如果想买就找他作介绍人,这样大家都可以送一年的物业管理费。见他太热情,我们也不忍心拒绝他,还是留下了他的联系方式走人。
后来总会看到一些帖子的标题写着历德雅舍物业管理人员打人之类的,也没去细看到底怎么回事,只是心里暗自庆幸,幸好没打算买那里。
2006年2月3日(大年初六)蓝色硅谷――中海花城湾――时代新世界――泓景花园――会展西岸――塞纳森情――富力尚溢居――大学印象――尚海――芭堤水岸
亲爱的卷毛小肥兔终于从家里回来了,前一天晚上吃饭时跟她说起了我们的看楼经历,也挑起了她的兴趣。原本她也没有打算现在买楼的,给我们说着说着心动了,所以初六一早她也抓着BF加入了我们。
经过前几天的忙活,我那张清单上的已经差不多去了一半。这次,不甘心的我还是把大家拉倒了天河一带,准备看一个叫蓝色硅谷的盘。我们在总统大酒店集合后就开始找,发现的确就在酒店旁边。顺着它指示的方向往里走,居然走到了一个军事管理区。奇怪了,怎么会在这里面呢。不管它,看看先,于是战战兢兢迈入了大门,生怕被警卫给拦下。警卫值班室的大门上赫然写着:哨兵神圣不可侵犯,笑死我们了,哈哈。进去兜了圈发现不对劲,又退出来,问了问神圣不可侵犯的哨兵,原来我们走过了。但是回到那个指示的地方,还是没找到,就看到一片烂工地,旁边圈着一圈蓝色的围栏。我们一起恍然大悟般的说,哦,原来这就是蓝色硅谷的由来,哈哈。玩笑归玩笑,尽管没找到售楼部,我们也对这里不抱什么希望了,因为又是靠近大马路,估计首层又是商铺了,再加上到处都乱糟糟的,实在让人产生不了什么好感。
在门口想打个电话给中海花城湾,因为他们对这个也还有一点点兴趣。网上是没有提供售楼部的电话的,忽然发现手里拿着昨天看的中海观园国际的资料,上面写着中海集团的销售热线,便打了过去。请问中海花城湾售楼部的电话是多少?那里还没有电话。那请问售楼部的位置在哪里?那里还没有售楼部。那请问那个楼盘在哪里?那里还没有开始起。得到这三个没有的答案后,我们几个免不了又把中海批判一通,居然连个影儿都没有呢,还好意思打广告,唉,这些发展商。
时代新世界,地址实在天河区禹东西路的省军区司令部旁边。听起来就是个很远的地方,但是网上的报价很吸引人,均价只在4000多。还得意洋洋的盘算说,远点没关系,反正这么便宜,大不了把省下的钱买部10来万的车好了。而且好像也是新世界的盘,所以有些好感。还真的挺远的,图中还路过了白云区医院。我气鼓鼓的说,那这不都到白云区了吗,怎么说是天河区,真能骗人。不过我也不了解这些区划问题,也只是随便说说。到了之后一看,好家伙,那叫一个吵啊,旁边几条高架路经过。楼盘是已经起好的了,但里面却冷冷清清,似乎还没什么人住的样子。没找到售楼部,在下面的一间快客问了一下,答案是早就卖完啦。难怪这么便宜,原来是这么远这么吵;难怪这么便宜,原来估计都是几年前的价格了。唉,这个网站的,你的资料什么时候才能更新一下呢。
为了防止接下来再出现这种白费力气的情况,我们决定一个个打电话了解清楚情况后再行动。忽然想起来昨天那个师兄,他不是也看楼吗?对,问问他今天在哪里看,我们也好参考一下。打了个电话过去,这老兄,居然又去了东方新世界,更打击人的是,他已经带着家人去签合同了!!!唉,真是有钱人哪!
摆在我们面前是两条线路,要么就去滨江东一带,要么就去赤岗一带。后来赤岗的车先到,我们便跳了上去,准备去前两天没看到的那个泓景花园。下车后没走多远就到了。泓景门前也是一条大路,但没什么车经过,还比较安静,对面就是奇星制药厂。这里号称是双地铁物业,向左走是二号线的赤岗站,向右走是三号线的赤岗塔站。但我有个朋友说过,双地铁物业的真实理解就是没地铁物业,两边都不着地儿。事实也是,好像无论去哪一边都不算近的那种。进去售楼部问了下,均价在6200,还不错。看了下样板间,装修还可以接受,大户型的有111和116两种选择,小的就有70多90多的。111的那种,厕所是在门口,也就是一进大门右手边,先是厨房门,再是厕所门,怎么看怎么怪,后来去到许多盘发现现在似乎挺流行这种设计的。我反正是不习惯。116的就还好,属于那种正常户型,进门先是厨房再是饭厅、客厅。然后一条巷子进去,房间洗手间什么的都藏在里面。小户型的也是70多的那个还不错,肥兔就看中这一户。下来一问,发现这两种都已经卖光了。2月底就还会推出几栋,均价在6500,但只有70多的和111的那种选择,116的就已经没有了。我颇不解的问那个sales,为什么不做116的呢,比111那个好多了。Sales笑了笑说你喜欢那个吗?我们很多客户都不喜欢哦,你没看那个朝向吗,夕晒会很厉害的。在此声明一下,这之前我是一直不大懂这个朝向问题的。不甘心的问了问,就不会再有其他户型了吗?答案是今年10月还会再推出一期,均价就要到7500了。看了看户型的模型,有很多种,有一些还比较满意,至少比现在这个111的好,但是要等那么久而且还涨价,估计都不会考虑了。所以退而求其次的仔细研究了111的这个单位,试图在几栋中找出最好的一户来。肥兔那个70多的就还不错,南向的。我们兴奋的说不如买在一层吧,实现我们两梯三户的梦想。因为之前我们几个总是会发梦般的说房子要买在一起,两梯三户那种。虽然现在这个是两梯六户,多了一倍,但想到今后大家可以一起上下班一起玩,还是很开心啊。留了联系方式,月底开盘时通知,于是到目前为止,泓景成为我们的第一个可选择对象。尽管户型不是很理想,也尽管它的外观看上去比较土,但还是勉强能接受的。
出来后已经12点多了,四处找地方吃饭未果,周围看上去都不是很好的样子,毕竟是老区了,只好继续往前走,走了好远好远才见到一个KFC和M记。这时已经离我们的下一个目的地,会展西岸非常近了。匆匆吃完赶过去,发现这个房子的外观并不怎么样,楼层也都不高。离二号线磨碟沙站还算近。但是地理位置上来说还是让人觉得比较偏远。进去问了下,均价好像是六千多,还要是毛坯。本来就对它没什么好感,还要这么贵,所以就没有做打算。还是去看了下样板间,又是完全不记得什么样子了。只是记得楼距很近,小区的蘑菇里藏着有音箱,放着一些流行歌曲,整个小区的上空都回荡着,最开始还以为是哪家的音乐放的这么大声呢,旁边有条小路有些小孩在放鞭炮,时不时的“啪”的一声,用肥兔BF的话说,给人感觉好诡异啊,呵呵,还是走吧。
本来准备去塞纳森晴,但打电话去没人接,便改道去了富力尚溢居。好像是一栋单体楼,外观还可以,但售楼部没开门。楼已经建的差不多了,所以估计也已经卖完了。再抬头一看,原来塞纳森情就和这里遥遥相望。今天的计划里已经没什么可看的了,但反正都来到这边了,我提议再回去中大北门一带转转。大学印象和尚海还是没开门,对面的好像是海珠半岛花园吧,好像楼都已经建了好久了,却还有个售楼部在。我提议去看看,遭到一致否决。理由是江边的楼就甭想了,肯定都是超贵的。事实证明也不是这样,隔了几天我打电话去问,价格是在6000-8000,8000的价格就是可以侧望江的了。不明白为什么这么便宜,可能是因为是尾楼卖了很久卖不出去吧。
实在没地方可去了,还特地打了车兜了一下珠江广场那边,有个叫芭堤水岸的盘,售楼部没开门。过了些天打电话去问了一下,这里要到四月才开盘。
回家后上网,看了下天涯,加入了广州楼盘的群。正好咱天涯房产的名人鬼王在线,就上去说了说这些天的经历,也跟鬼王咨询了一下。鬼王不愧是鬼王,真是什么都知道啊,似乎广州的楼盘他都看遍了。后来又淘出了了几个地方,准备第二天再看。另外还查了下今天看的几个盘,好像泓景就有人说开发商抵押了些楼套现,让我对它的好感大打折扣,大学印象和尚海的评价好像也不怎么样,所以就不打算再去第三次了。
2006年2月4日(大年初七)颐景华苑――晓城――万华花园――翠城花园――鹅潭明珠――金碧湾――富基广场
这一天应该算是触动最大也最受打击的一天了。我们的第一站是颐景华苑,合生的盘。鬼王说这里比较吵。挺远的,东晓南路,从来没到过这里,感觉太陌生了。颐景就在大马路边,车来车往的真的很吵。这里奇怪一下,不大像合生的风格啊,看过的帝景、逸景、骏景那些应该都是挺静的啊。不过大公司还是大公司,售楼部都比人家的气派很多,看了下规划模型,居然后面几期也都是圈着马路建的,中间就是小区。将来规划小区里会有个中学,好像是97中进来的,还有个足球场、跑道、游泳池什么的。合生的配套应该一向都是不错的。这里的均价是6000多,带装修的,三种户型,分别是110多,130多和140多,110多的已经卖完了。两梯三户的,我的梦想啊!!!样板房设计的不错,处处透着大气,反正我很喜欢,装修也不错,洁具那些好像合生惯用的都是美标的。总的来说,这里除了比较吵比较远以外,别的都挺好。据说地铁二号线的延长线途径这里,好像走路过去还挺近。所以这个盘的广告打的也是这个卖点。但问了下,要到08年才开通呢。广佛轻轨以后也会经过这里,那就更不知要等到什么时候了。
对面就是晓城,马路边的一栋单体楼。后面有栋稍矮些的早前的楼似乎都和它连在一起了,可见楼距之密。他们打趣说,可以打广告说××层送私家花园,其实就是旁边楼的天台,哈哈。吸引我们进去看的主要是价钱,广告打着5100多一平方还送精装修。这是我们这些天所看的最便宜的了。进去问了下,样板间要到初八才开门,拿了份资料闪人。
接下来这站是鬼王介绍的万华花园,印象中离晓城不是很远吧,我们好像是走路过去的。就在英豪花园对面。万华应该是个比较成熟的小区了,前面的一些楼看样子都有些年份了。小区外面应该生活来说还算是挺方便的,门口就有间便利店,附近还有很多饼店、药店、食肆什么的。售楼部是小小的一间,走进去问了下,新的那期叫广弘•叠水雨林,听上去很诗情画意的一个名字。价格是5000多一方,毛坯,但是都卖的七七八八了,只剩下二楼的单位,分别是99和107方的。sales说107的那户是有个平台送的哦,而且每平方的价格是一样的。基于前面对帝景华苑那个平台的好感,一听到这个我就心动了,兴冲冲的去看剩的那几套房。小区里面的环境挺不错,挺幽静的,到这里,我们几个都有些把它列入考虑范围了。比较搞笑的是,虽说是看毛坯,仍是要让我们穿上鞋套,有些不大理解这个有什么作用,房间里面到处都是水泥石灰,走出来不是一样也弄脏外面那个走廊?后来想想,估计人家那是怕弄脏我们的鞋吧,哈哈。因为看的是毛坯,所以看不出什么感觉来,送的那个平台也很丑,跟我想象中完全两个样,就是个大水泥场子。最有一点不好的是,本来小区里面都是挺安静的,偏偏这栋似乎是近马路的,一出去平台外就是马路,还是挺吵。可能高层的会好一些吧,可惜早就没有了。所以,这里也被否定掉了。
我们又走回晓城那边,准备坐车去翠城花园。只见到一个273的总站。这辆车的线路比较搞笑,先是围着晓城经过一些工地兜了一大圈,而且速度极为缓慢,我们说估计这是看楼专车呵呵。然后经过的全是些小路,什么村什么乡的。我们不禁感叹,太偏远了,还是不要买这里的好。兜转了好久到了昌岗路,我们下车打车直奔翠城。翠城附近的环境就要好多了,大马路很开阔,不是很闹的那种,但也不是人迹罕至,周围的环境感觉还挺安全。小区还比较大,绿化不错,楼是在小区里。外部环境得到了我们的一致通过,价格是在6000多一方带装修的,也通过。不过现在还没有开盘,大概要到3月。然后就坐那种电瓶车去看样板间。那叫一个人多啊,看了这些天的楼,这里的人气是最旺的了。三梯八户,户型好像很多,似乎每一户都不一样。看样板时发现好像有两户是在电梯后面的,也就是说下了电梯要通过一个安全出口才能到那两户,有种被关在门外的感觉。最大的好像是110多,最小的54,但是每一户的户型都不好,要么就是那种厕所在门口的设计,要么就是空间浪费,主人房很小,却带了个很大的工作阳台,又没有主卫,真不知道设计师是怎么想的。厨房和洗手间也都很小,总之是我看的所有盘中最奇怪最不好的户型了。只有一户还不错,肥兔看中了,88方的小三房,是所有当中最正常的了,而且从阳台望下去正对小区的泳池,景观还不错。但是厕所也在门口,而且可能是为了省事吧,像其他的几个单位一样,无论是厅还是房间都有很多角位,不仅不好放东西,让人感觉也很不舒服。样板间是属于创意装修那一类的,稍微做了些掩饰,但还是很明显。但想想这里的其他方面都还可以接受,肥兔准备忍受一下。他BF说,那半夜起来去厕所还要走好远啊,特别是如果开错门就糟糕咯,呵呵。出来后发现,小区的对面就是珠江医院,仅供对此有所避忌的朋友参考。
接下来就是我们伟大的鬼王住的豪宅了,据说是一线江景哦。说真的,我对这个江景到没有太大的兴趣,就一条小水沟有啥好看的呢?很不明白为什么那么多人要花那么高的价钱去买江景房,哪怕是一点点都觉得很好的样子。不过既然伟大的鬼王都说这里好,去看看也无妨。还不算太难找,鹅潭明珠。外面是很生活化很典型的广州老城区的样子,应该还挺舒适的。往里拐进去就看到矗在江边的两栋单体楼,广告写着仅剩5套。我和肥兔边走边说,不知道会不会遇到鬼王呢,呵呵。虽然是单体楼,但是楼下临江的那边还是有绿化的,做的也不错,小小的挺精致,我认为已经够了,每天下楼就可以在江边漫步,夫复何求呢?中间还做了个小小的人造沙滩,挺特别,不过后来听sales说这里以后要改成一条滨江的人行道,沙滩就没有了。进去售楼部向sales咨询了一下,只剩130多和140多的大单位了,也是两梯三户,另一种110多的户型已经没有了。好像03年就已经开始卖了,现在卖的是尾楼。Sales说他们没有做广告的,所以知道的人比较少。酒香不怕巷子深嘛。130多的还剩2、3和顶层的,140的就只剩顶层的两套了。楼层就都一般了,都是一口价,2、3层的平均应该是6000多一方,顶层130的是7000多,140的就是8500了,全是毛坯交楼。但想想是江景房哦,这个价格真的算挺便宜了。Sales先带我们去看了2层的那个单位,阳台出去就可以望江,但因为视野被旁边140那户挡住了一半,所以一般。我们又要求去看顶楼那间,上去才发现130那个没带钥匙,便去看了140的。进门就是饭厅客厅,很方正的,接着就是落地玻璃的大阳台。怎么形容我当时的感觉呢,好难,我只能说我们几个都彻彻底底的惊呆了,接下来就都是大叫,好爽啊!!!绝对的一线江景,正望江,不偏不斜,阳台很大,视野那是相当开阔啊,而且因为楼层高,更有种君临天下的感觉。然后去看了其他房间,每个房间都能看到江景,真好啊。特别是斜望过去就是白天鹅一带,BF说到了晚上江边的灯全亮了应该会更漂亮。肥兔的BF也站在阳台上对她勾画着:你看,以后每到傍晚夕阳铺满整个江面的时候,金灿灿的江水,金灿灿的沙滩,你就站在这里笑意盈盈幸福的看着我和孩子们在沙滩上打滚,多美啊。(这里要小小的插一句,肥兔的BF似乎到每一个楼盘的阳台上都要勾画一个类似的场景,只是景观随着场地的不同而变化,比如花园啊、游泳池啊什么的。有一点不理解的是,可怜的肥兔每次都是被安排在上面看着,他则和孩子们在楼下逍遥的或打滚或游泳或打篮球堆泥巴什么或的。肥兔就这样被剥夺掉了参与权,呵呵。)到了这个时候,我才体会到鬼王那天为什么说非江景房不住了,到了这个时候,我才明白为什么那么多人要在这个上面一掷千金了,到了这个时候,我再也不想去看其他的地方了。唉,喜欢归喜欢,咱没钱啊。如果说二层那个130的,咬咬牙估计还能接受,但BF说,这种地方,要买就要买最好的那套,不然不伦不类的多没劲。我们让sales算了下130顶层的价钱,大概要一百零几万,而且首期要付四成的,140那个就要120多万,更贵了,还要再加上装修,唉。而且这里离我和BF的单位都很远,只能伤心失望的作罢了。往回走的时候,肥兔愤愤的异想天开的说,如果是50万一套,我立即就买下来。我说,如果是50万一套,我就把那5套都买下来,转手卖掉那可是赚一大笔啊!!!
带着倍受打击无比失望特别沮丧的心情,我们又来到了旁边的金碧湾,鬼王的心头好。这里就比鹅潭明珠更远一些了,但因为是大公司的盘,整体的规划还是要好一些。小区还不错,靠里面的是一些底层的楼,估计有些年代了,然后江边就斜斜的矗着三栋高层,应该卖的就是这里。售楼部有很多人,但sales只有一个,所以不是很忙的过来。我们插空问了几个问题,大概价格是两房的均价是8000,三房的是10000。心里先咯噔一下,跟事先了解的情况有出入啊。先不理这个,上去看看再说。三栋楼分别叫10、11、12栋,每栋好像是两梯四户,两户两房的70多方,还有两户三房的是105和110多方。每一栋楼的四间房样板间都开了,中间是连通的,所以对于我这个毫无方向感的人来说,看的我有点晕头转向。还是BF厉害,他一早分析了模型的位置就说,这三栋要看江的话应该是12栋最好,因为12栋是靠边的,而且望过去的江景应该是往白鹅潭方向的,会比较漂亮。所以10、11栋我们都每怎么看,就直接去了12栋。01和04分别是105和70多方,用我们的话说就是郁闷单位,是向里面的,几乎望不到什么江。因为我喜欢大户一点的,所以又看了02的110多方的,房间布局都不错,江景也都很好,唯一有些美中不足的就是阳台的方向是向着白鹅潭另一头方向的江景的,而且视线被旁边的那户稍有遮挡。最好的位置应该是03那户70多方了,因为是最靠边的,视线没有任何东西挡住,客厅、每一个房间、连厨房厕所都是望江的,而且方向都是朝白鹅潭那边的,怎一个爽字了得啊!!!我们四个坐在主人房的窗台上发了好久的呆,真想一直在这里待下去啊!!!不过整个来说,楼的外观我不是很喜欢,内部装修的色调也一般,特别是木地板的颜色不大好看,厨具好像是用的美的的,整体还过的去吧,而且想想这江景,这些细节也就可以忽略不计了。所以综合各方面的因素考虑,包括价钱,我们决定考虑03的这户70多方的单位。计算了下应该是50多万,价钱是相当诱人啊!尽管是只有两房,而且主人房没有洗手间,但为了这无敌的江景,我第一次同意去掉我之前怎么都不肯去掉的这个硬性要求。呵呵,足以见得它有多么好了吧。我们商量好了,因为看中的是一个单位,就不能在同一层了,但楼上楼下也还不错,呵呵。看楼的人很多,所以BF在一旁说,先别高兴的太早,这么好的单位估计别人也都会看中,可能早就卖光了。我一听慌了,觉得有理,就拉着他们急匆匆的返回售楼部,大叫着“手快有手慢没啊!”冲下去。BF无奈的在后面跟着叫,“慢着点别那么急,好像弄的今天就要下定了似的。”我就是这样,一看到喜欢的东西就恨不得立即买下来,生怕别人抢了去。可他们却还在后面慢悠悠的跟着,我心里那叫一个急啊。终于回到售楼部了,居然没什么人,我心里暗自窃喜,想着,哈哈,这下没人跟我争了。结果才发现,连sales也不见了。问了下保安,居然已经下班了!!!这不才四点么,这么早就下班??!!真没天理。看来人家的好东西就是不愁卖,就是要吊起来卖,过分!我试探性的想跟保安了解下情况,结果人家比我想象的知道的还多。很不幸的,12栋那个03已经卖光了,只剩2楼的一套了,问了下价格,这套70多的居然也要70多万!!!02那户110多的倒还剩一些,但差不多都是要110、120多万起了。我说刚刚不是还说均价8000吗,现在都差不多去到一万了,他居然说没有一万啊,也就9000多,8000那些是不望江的,望江的带装修的全都要9000多一万多起价的。我狂分特,居然就这样欺骗了我们纯真的感情,伤害了我们弱小的不堪一击的心灵,没天理啊!!!有一次从高高的云端跌下来,又一次让满心的希冀受到重创,我那个伤心啊!!!BF倒没什么所谓,说算啦,这里这么远,交通也不是很方便,要买这里起码还要买部车,咱没那么多钱啊。于是我们又一次沮丧的拖着沉重的步伐走出来,这时正好太阳斜照过来,到处都是金灿灿明晃晃的,真像梦幻中一般,好漂亮。然后肥兔的BF又开始发梦了……
不过说真的,这里的江景比起鹅潭明珠那套140的单位还是差不少啊。
回去的路上,精神有点恍惚,脑子里都是充斥着江景啊什么的,情绪挺低落的。BF就累的够呛,在晃晃悠悠的公车上睡着了。慢着,似乎前方又有什么东西吸引我的视野了,越来越近,我的眼睛就越来越亮。哈哈,这不前面又有个在起的楼么,看了下周边,好像已经到江南西一带了,而且旁边就有个地铁站。揉揉眼睛仔细看看广告牌,写着光大•榕岸。我摇醒BF让他看看,他极不情愿的睁开眼睛,然后又闭上,说榕岸不是很贵么。我不理那么多,一定要下去看。他拗不过我,只好在临近的车站下了车,原来就是婚纱街的附近。走过去才发现,原来不是光大的盘,是个叫富基广场的地方。周围的环境还不错,有商场有地铁站(市二宫),而且因为婚纱街是以前经常坐车会经过的地方,对这里感觉会比较熟悉,自然有种亲切感。但看着天色已晚,估计售楼部已经下班了,所以没抱什么希望的问了问保安,居然还开着!!!我开心坏了,一扫刚刚沮丧的心情,那种狂热的心情又回来了,再次冲进售楼部。先看了看规划,不错,再看看户型,也还可以。这里是三梯八户的,均价是6000多,南向的要7000多,但是毛坯交楼。我们喜欢的大户型的大概是???方,南北向的都有,但考虑价钱的因素,还是决定要北向的。不过我们看中的那户仍然是厨房厕所在门口的设计,不过稍有不同的是门对门那种,而不是在一边。我现在才觉得,其实自己的原则性也没这么强的,喜欢一个地方那就是喜欢,多少缺点都能包容,不喜欢就是不喜欢,再怎么好也总要去挑出些毛病来,呵呵。Sales说北向靠最旁边的这户也是挺好的,因为刚好和前面的朗晴居错开,远远的可以望江。我一听有江景,更是喜欢,但sales说这会样板房已经关门了,没的看。我们就先让她帮忙算算价格。好像这里也卖的七七八八了,只剩一些高层的了。我们算了21层的价格,大概是??万,虽然没有装修,但也还能接受。Sales说其实自己装修更好啊,也花不了多少钱,其实那些带装修的盘说是多少多少的标准,其实根本值不了。我想想也是,而且自从看了鹅潭明珠(那里也是毛坯交楼的),也爱屋及乌的觉得自己装修其实更好。这两天新春特惠,是有些折头的,我一看,差不多能便宜5万多块呢,但是只到初八。我又开始急了,又想下定了,因为初八我们是要上班的,根本没有时间过来了。BF说先别急,样板间都没看过,说不定和图上的有很大出入呢?然后我们就跟sales说了这个情况,看看能不能想想办法让我们去看一下。呵呵,有生意哪能不做呢,她还是找保安开楼带我们去看了。BF觉得几栋楼一字排开,几乎是连在一起的,看上去密密麻麻,他不是很喜欢,而且因为周围还有很多破破烂烂的房子,虽然小区的规划是很不错很大的,而且这块地也征下来了,但因为回迁楼年底才建好,所以还没那么快拆迁,也就是说到了年底交楼的时候,这里还会是这样破烂。我问sales那两年内能不能全部完善呢,她支支吾吾答不上来。样板间是底层的,所以都被周围的低楼挡住,采光不是太好,不过到21层就应该没问题了。布局也都还可以,而且可以自己改造嘛。主人房还有个弧形的飘出去的阳台,挺漂亮,但上面居然有道宽宽的梁,有些遮挡视线,而且是不能拆的。BF就觉得这样不爽,开始否定这里了,我倒觉得没什么所谓。站在阳台上看着对面那些破楼,忽然想起既然这一片都已经征下来了,那会不会对面就起什么二期三期呢?sales说肯定会起的,不过具体在什么位置她就不清楚了,但即使对面会起楼距应该也会比较宽,没什么问题吧。我就觉得问题大了,本来对面就是朗晴居,虽然这里错开了,但如果另一边再起一栋,别说江景了,除了和对面的人傻傻的互望,什么都没的看,我是喜欢比较开阔的视野的,特别是看了那些无敌江景以后。但因为实在喜欢这里,有些不甘心,想着要么就再买高一点,要么就买另外一户南向的。因为即使那边也会再起楼,但至少楼下还有小区的花园可以看。下去又算了南向那户的价钱,贵出七万多块。而且我还没放弃这个两梯三户的梦想,所以又让她帮肥兔算了那户北向80多方的,大概是50万出头。各方面都考虑周全,也留了联系电话后,我们说明天再来看看吧,就出来了。我觉得BF似乎是不大喜欢这里,他对主卧的那道梁很介意,我们一路上争了好久,我都有些不高兴了。他后来总算说出了一个比较有说服力的理由,说你看这里各方面都刚刚开始的样子,也就是说即使等交楼了周围的不管是配套还是花园什么的都还是在拆在建,将来再在临近的地方起什么二期三期的,估计五年内我们都会听到外面敲敲打打不得宁静了。因为我现在住的地方旁边也在起一栋楼,不仅吵,而且还时不时轰一声大锤砸下去,连地板都会震,对于我这个周末要赖到中午才起床的人来说实在太痛苦了。所以,暂时赞同了BF的观点。只不过还没死心,至今还觉得那是可以考虑的对象。
- 作者: Jo Ja Yong 2006年02月28日, 星期二 09:18 回复(0) | 引用(0) 加入博采
2005年彩铃用户调查








- 作者: Jo Ja Yong 2006年01月5日, 星期四 18:07 回复(0) | 引用(0) 加入博采
如何撰写促销活动方案
- 作者: Jo Ja Yong 2006年01月5日, 星期四 18:00 回复(1) | 引用(0) 加入博采
明年4至7月3G将发牌 TD-SCDMA有望
- 作者: Jo Ja Yong 2005年12月22日, 星期四 18:01 回复(0) | 引用(0) 加入博采