??xml version="1.0" encoding="utf-8" standalone="yes"?>91官网在线,亚洲高清在线观看,国产成人福利视频http://www.aygfsteel.com/honzeland/category/16282.html记录Ҏ。。?/description>zh-cnFri, 22 Oct 2010 14:51:44 GMTFri, 22 Oct 2010 14:51:44 GMT60Servlet Mappings - rules, pattern....http://www.aygfsteel.com/honzeland/archive/2010/10/22/335921.htmlhonzelandhonzelandFri, 22 Oct 2010 14:41:00 GMThttp://www.aygfsteel.com/honzeland/archive/2010/10/22/335921.htmlhttp://www.aygfsteel.com/honzeland/comments/335921.htmlhttp://www.aygfsteel.com/honzeland/archive/2010/10/22/335921.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/335921.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/335921.htmlhttp://www.rawbw.com/~davidm/tini/TiniHttpServer/docs/ServletMappings.html

honzeland 2010-10-22 22:41 发表评论
]]>
Java remote invocation frameworks (RPC)http://www.aygfsteel.com/honzeland/archive/2010/06/09/323153.htmlhonzelandhonzelandWed, 09 Jun 2010 06:25:00 GMThttp://www.aygfsteel.com/honzeland/archive/2010/06/09/323153.htmlhttp://www.aygfsteel.com/honzeland/comments/323153.htmlhttp://www.aygfsteel.com/honzeland/archive/2010/06/09/323153.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/323153.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/323153.html1. Remote Method Invocation (RMI)

2. Hessian

3. Burlap

4. HTTP invoker

5. EJB

6. JAX-RPC

7. JMX



honzeland 2010-06-09 14:25 发表评论
]]>
Tomcat Architecture Diagramhttp://www.aygfsteel.com/honzeland/archive/2010/05/10/320458.htmlhonzelandhonzelandMon, 10 May 2010 02:39:00 GMThttp://www.aygfsteel.com/honzeland/archive/2010/05/10/320458.htmlhttp://www.aygfsteel.com/honzeland/comments/320458.htmlhttp://www.aygfsteel.com/honzeland/archive/2010/05/10/320458.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/320458.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/320458.html

Valve and Filter:
"Valve" is Tomcat specific notion, and they get applied at a higher level than anything in a specific webapp. Also, they work only in Tomcat.

"Filter" is a Servlet Specification notion and should work in any compliant servlet container. They get applied at a lower level than all of Tomcat's
Valves.

However, consider also the division between your application and the application  server. Think whether the feature you're planning is part of your application, or is it rather a generic feature of the application server, which could have uses in other applications as well. This would be the correct criteria to decide between Valve and Filter.

Order for filter: The order in which they are defined matters. The container will execute the filters in the order in which they are defined.


honzeland 2010-05-10 10:39 发表评论
]]>
Quartz scheduled executionshttp://www.aygfsteel.com/honzeland/archive/2010/01/21/310422.htmlhonzelandhonzelandThu, 21 Jan 2010 09:38:00 GMThttp://www.aygfsteel.com/honzeland/archive/2010/01/21/310422.htmlhttp://www.aygfsteel.com/honzeland/comments/310422.htmlhttp://www.aygfsteel.com/honzeland/archive/2010/01/21/310422.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/310422.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/310422.html 我们知道QQuartz采用JobDataMap实现向Job实例传送配|属性,正如Quartz官方文档说的那样Q?br />
How can I provide properties/configuration for a Job instance? The key is the JobDataMap, which is part of the JobDetail object.
The JobDataMap can be used to hold any number of (serializable) objects which you wish to have made available to the job instance when it executes.
JobDataMap map Q?context.getJobDetail().getJobDataMap();

我们通过map向Job实例传送多个objectsQ其中有一个是个beanQ一个是基本cd。对于scheduled triggersQ我们要求bean对于所有的序列都不变,包括其属性,而基本类型可以在Jobq行q程中改变,q媄响下一个序列。实际情冉|Q对于下个序列,bean的属性被上次的修改了Q而基本类型却l持W一ơput到Map里面的倹{正好和我们要求的相反?br />
受bean的媄响,以ؓmap里面包含的都是更新的对象Q即每个序列里面的JobDetail是同一个对象,但是基本cd的结果否认了q一炏V回头重新翻阅了下Quartz的文档:

Now, some additional notes about a job's state data (aka JobDataMap): A Job instance can be defined as "stateful" or "non-stateful". Non-stateful jobs only have their JobDataMap stored at the time they are added to the scheduler. This means that any changes made to the contents of the job data map during execution of the job will be lost, and will not seen by the job the next time it executes.

Job有两个子接口QStatefulJob and InterruptableJobQ我们承的是InterruptableJobQ或许Quartz应该有个InterruptableStatefulJob。另外StatefulJob不支持ƈ发执行,和我们的需求不匚wQ我们有自己的同步控ӞJob必须可以q发q行?br />
然后查看了Quartz的相x码:

// RAMJobStore.storeJob
public void storeJob(SchedulingContext ctxt, JobDetail newJob,
            
boolean replaceExisting) throws ObjectAlreadyExistsException {
        JobWrapper jw 
= new JobWrapper((JobDetail)newJob.clone()); // clone a new one
        .
        jobsByFQN.put(jw.key, jw);
        
}

也就是说Qstore里面攄是初始JobDetail的克隆,在序列运行完Ӟ只有StatefulJob才会更新store里面的JobDetailQ?br />
// RAMJobStore.triggeredJobComplete
public void triggeredJobComplete(SchedulingContext ctxt, Trigger trigger,
            JobDetail jobDetail, 
int triggerInstCode) {
    JobWrapper jw 
= (JobWrapper) jobsByFQN.get(jobKey);
    
    
if (jw != null) {
        JobDetail jd 
= jw.jobDetail;
        
if (jd.isStateful()) {
            JobDataMap newData 
= jobDetail.getJobDataMap();
            
if (newData != null) {
                newData 
= (JobDataMap)newData.clone();
                newData.clearDirtyFlag();
            }
            jd.setJobDataMap(newData); 
// set to new one
            
        
    }

}



然后Q每ơ序列运行时所用的JobDetailQ是存放在Store里面的克隆?br />
// RAMJobStore.retrieveJob
public JobDetail retrieveJob(SchedulingContext ctxt, String jobName,
        String groupName) {
    JobWrapper jw 
= (JobWrapper) jobsByFQN.get(JobWrapper.getJobNameKey(
        jobName, groupName));
    
return (jw != null? (JobDetail)jw.jobDetail.clone() : null// clone a new
}


问题很清楚了Q存攑֜Store里面的JobDetail是初始对象的克隆Q然后每个序列所用的JobDetailQ?是Store里面的克隆,只有Stateful jobQStore里面的JobDetail才更新?br /> 最有Quartz里面使用的clone():

// Shallow copy the jobDataMap.  Note that this means that if a user
// modifies a value object in this map from the cloned Trigger
// they will also be modifying this Trigger.
if (jobDataMap != null) {
    copy.jobDataMap 
= (JobDataMap)jobDataMap.clone();
}


所以对于前面所讲的Q修改bean的属性,会媄响所有clone的对象,因此Q我们可以将基本cd装C个bean里面Qmap里面存放的是beanQ然后通过修改bean的属性,来达到媄响下一个序列的目的?br />


honzeland 2010-01-21 17:38 发表评论
]]>
Useful Links: ing...http://www.aygfsteel.com/honzeland/archive/2008/06/03/205565.htmlhonzelandhonzelandTue, 03 Jun 2008 07:09:00 GMThttp://www.aygfsteel.com/honzeland/archive/2008/06/03/205565.htmlhttp://www.aygfsteel.com/honzeland/comments/205565.htmlhttp://www.aygfsteel.com/honzeland/archive/2008/06/03/205565.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/205565.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/205565.html http://www.theserverside.com
http://www.javablogs.com
http://www.java2s.com
Java(TM) Platform Performance: Strategies and Tactics
A Simple Data Access Layer using Hibernate
Discover the secrets of the Java Serialization API
Setting up two-way (mutual) SSL with Tomcat on Java5
Basic Tomcat Tour and Tomcat Security
When Runtime.exec() won't
Asynchronous processing support in Servlet 3.0
About security:
The Types Of Digital Certificates
Cryptography Lecture PPT
MD5 considered harmful today
Cryptography Tutorials - Herong's Tutorial Notes
Defective Sign & Encrypt in S/MIME, PKCS#7, MOSS, PEM, PGP, and XML
Cryptography resources by Bouncycastle
Others:
Colors for the webColors for the web
Test Frameworks
Lightstreamer: a scalable and reliable Server for pushing live data to Rich Internet Applications


honzeland 2008-06-03 15:09 发表评论
]]>
Managing HttpSession Objectshttp://www.aygfsteel.com/honzeland/archive/2008/05/21/201933.htmlhonzelandhonzelandWed, 21 May 2008 07:49:00 GMThttp://www.aygfsteel.com/honzeland/archive/2008/05/21/201933.htmlhttp://www.aygfsteel.com/honzeland/comments/201933.htmlhttp://www.aygfsteel.com/honzeland/archive/2008/05/21/201933.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/201933.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/201933.htmlzz: java.sys-con.com

Java servlet technology provides developers with functionality, scalability, and portability that can't be found in other server-side languages. One feature of the Java servlet specification that's commonly used, and sometimes misused, is the HttpSession interface. This simple interface allows you to maintain a session or state for Web site visitors.

In my previous article ("Introduction to Session Management," [JDJ, Vol. 7, issue 9]), I introduced you to session management and the HttpSession interface. In that article, we walked through using the HttpSession API to create, use, and destroy session objects for Web site visitors. The next step is to better understand how to manage the sessions and those objects in a session. This article will help you achieve this by helping you understand the following concepts:

  • Code-based session management through listeners
  • Proper design of the session and the objects it contains
  • Controlling what is in the session and why it's there
  • Session persistence
  • Memory management
The Java APIs discussed in this article are from Sun's Java Servlet 2.3 specification.

Listeners
A listener is an object that's called when a specified event occurs. There are four listener interfaces that allow you to monitor changes to sessions and the objects that are in those sessions:

  • HttpSessionListener
  • HttpSessionBindingListener
  • HttpSessionAttributeListener
  • HttpSessionActivationListener
Figure 1 provides a method summary for each of the listener interfaces. The implementing class that you write will override these methods to provide the functionality you need.

HttpSessionListener
The HttpSessionListener interface is used to monitor when sessions are created and destroyed on the application server. Its best practical use would be to track session use statistics for a server.

The use of HttpSessionListener requires a configuration entry in the deployment descriptor, or web.xml file, of the application server. This entry points the server to a class that will be called when a session is created or destroyed. The entry required is simple. All you need is a listener and listener-class element in the following format. The listener-class element must be a fully qualified class name.

<listener>
<listener-class>package.Class</listener-class>
</listener>

As you can see in Figure 1, the class that implements this listener can override two methods: sessionCreated() and sessionDestroyed(). These methods will be notified when the server creates or destroys a session.

These methods take an HttpSessionEvent object as a parameter. HttpSessionEvent is simply a class that represents notifications of changes to the Web application's sessions. HttpSessionEvent has one method, getSession(), that returns the HttpSession object that's been modified.

HttpSessionBindingListener
The HttpSessionBindingListener interface is implemented when an object needs to be notified if it's being bound to a session or unbound from a session.

This interface has two methods, valueBound() and valueUnbound(), that are notified when the status of the object has changed (see Figure 1).

These methods have an HttpSessionBindingEvent parameter that can be used to retrieve the session that the object was bound to and the name it was given in the session. In Figure 2, you can see the methods of this object that are used to get the name that's assigned to the object, the session it's bound to, and the actual object.

HttpSessionAttributeListener
The HttpSessionAttributeListener interface is used to monitor changes to attributes in any session on the server. This can be useful when you know the name assigned to a specific object that gets put into the session and you want to track how often it's being used.

As with HttpSessionListener, HttpSessionAttributeListener also requires an entry in the deployment descriptor for the server. This entry tells the server which class to call when an attribute in a session has changed.

The HttpSessionAttributeListener interface has three methods - attributeAdded(), attributeRemoved(), and attributeReplaced(). These methods, shown in Figure 1, are called by the server when attributes of a session are changed.

HttpSessionActivationListener
The final listener, HttpSessionActivationListener, is implemented when an object needs to know if the session that it's bound to is being activated or passivated (moved). You would come across this scenario if your session is being shared across JVMs or your server is persisting the session in a database or file system.

This interface, displayed in Figure 1, has two methods that are overridden by the implementing class: sessionDidActivate() and sessionWillPassivate(). These methods are called when the status of the session in a JVM is changed.

Session Persistence
Today's J2EE-compliant servers allow for fault-tolerance and failover to provide support in the event that a server suddenly becomes unavailable because of hardware, software, or network failure. This support is usually provided by allowing two or more application servers, often called a cluster, to run together and provide backup support for each other. If one server fails, the others pick up the requests and continue on as if nothing happened. This allows your Web site visitors to keep going without interruption.

A proxy server is usually used in front of the application servers. This server is responsible for directing each HTTP request to the appropriate server. The proxy server can be set up to ensure that the server receiving the first request from a user will continue to receive all subsequent requests from that user. This means that a session created for the user on the application server will continue to be available for that user. If the server suddenly fails, there has to be a system in place to allow the session to continue on without it.

Session persistence allows the session contents to be saved outside the application server so that other servers can access it. Figure 3 shows the relationship between the persisted session data and the application servers that access it. In this figure, you see a client accessing a Web site's HTTP server. The HTTP server is forwarding requests for application resources to one of the application servers through the use of a proxy server. The application servers are persisting the session data in an external form.

There are four types of session persistence:

  1. Memory persistence (one server or a cluster of two or more)
  2. File system persistence
  3. Database persistence
  4. Cookie persistence
Every application server will handle session persistence differently and all servers may not support all types of persistence. Objects that are placed in the session must be serializable for persistence to work.

Memory Persistence
In most cases, a single standalone server will store sessions in memory. This allows for fast retrieval and update of the information. It also means that the session information will be lost when the server is shut down. This is usually the default configuration on most application servers. Memory persistence can be used when two or more servers need to share the session information. The application servers can be configured to share any changes made to the session so that the information is available on multiple servers. This redundancy of the session information helps the cluster preserve the session during a failure.

File System Persistence
File system persistence can be used to serialize any objects that are in the session. The object contents are placed in a file on the server. The location of the files created is configurable; however, the files must be accessible by all the servers in the cluster. The speed at which the file system is accessed can be a factor in the performance of your Web site. A slow disk drive, for example, would result in a delay as data is read from or written to the file.

Database Persistence
Database persistence can be used to provide a central data store for the session contents. Each application server in the cluster must be able to access the database. When sessions are modified, the changes are immediately persisted in the database. A data source is usually set up for JDBC persistence and the connections are pooled. This provides a quicker response. There's also the issue of database failover, which would be addressed at the database level of the system.

Cookie Persistence
The fourth type of session persistence, cookie persistence, is so ineffective and insecure that it doesn't deserve consideration when designing a fail-safe system. Cookie persistence, as the name implies, persists session data by storing the session information in browser cookie(s). There's a limitation on data handling because cookies store only text, not objects, and the amount of data that can be transmitted in a cookie is limited. There's also the fact that cookies transmit data back and forth between the client and the server. This prevents you (at least it should) from saving sensitive information, like a social security number. This type of persistence should be used in only the smallest of Web sites, and only if there's a good reason not to store the session in memory.

The most common type of persistence is database persistence. It provides an efficient way of saving session data and it's usually fairly easy to set up on the application server. Memory persistence in a cluster is also easy to use, if your application server supports it. The only drawback is that sessions can sometimes hold large amounts of data. Storing the session in memory reduces the amount of memory available to the other processes on the server. File system persistence can be slow at times and the file system may not always be accessible to multiple servers.

Watching the Session Size
As you and your fellow employees work on a Web application, you may notice that more and more objects are being thrown into the session, often "for convenience" or "just temporarily." The session becomes a quick catch-all for any information you need to get from your servlets to your JSPs. The HttpSession interface makes sessions easy to use, which can lead to the session being overused. This is a concern because the session takes up space. In most cases that would be memory space. In other cases, it could be database or file system space. In all cases, it means more work for the server and more work for the programmers to manage what is there.

Although the session is convenient because it's accessible from every servlet or JSP, it's not always the best place to put information. Most of the data that's retrieved for display in a Web application will only be used on one page. Instead of putting the information into the session scope, use the request scope and then forward the request from the servlet to the JSP. This causes the objects to be destroyed after the request has ended, which is after the data is displayed by the JSP. If you put the objects into the session, you would either have to remove them in your code or leave them there. Leaving objects in the session is not a good idea because you're using up valuable resources for no reason. This becomes even more of an issue when your Web site has hundreds or thousands of visitors, all of whom have a session that's loaded with objects.

Some objects should be stored in the session. Objects that may be needed over and over again as a user moves through a Web site are those that should be put into the session. Anything that needs to exist longer than one request can be stored in the session, as long as these objects are removed as soon as they're no longer needed.

Considerations for Managing Sessions
When working with sessions, there are a few things to consider before designing or redesigning a Web application:

  • Are sessions needed in the application?
  • How long should the session be inactive before timing out?
  • Are all the objects in the session serializable?
  • Are the objects being bound to the session too large?
  • Do the objects that are in the session really need to be there?
A Need for Sessions
If you have unique users on a Web site and need to know who they are or need to get specific information to them, such as search results, then you should be using sessions. If you follow the guidelines set here, there's no reason not to use the HttpSession interface that Java provides. It's easy to use, flexible, secure, and it helps you to build a better Web site.

There's another architecture that deals with maintaining state for a client. Instead of relying on the HttpSession interface, state for clients can be maintained within Enterprise JavaBeans (EJBs). The EJB architecture takes the business logic for an application and places it in components or beans. A session bean is a type of EJB that exists for a given client/server session and provides database access or other business logic, such as calculations. Session beans can be stateless or they can maintain the state for a client, very much like an HttpSession object.

There is still some debate over where the state for a Web site visitor should be maintained. The best design for the application at this time is to continue using the HttpSession object for maintaining the state of the presentation layer of the Web application and to use stateful EJBs to maintain the state of the business logic and data layer. There are many other factors that should be considered with EJBs, one being the better performance of stateless beans over those that maintain state. These issues, which are outside the scope of this article, should be considered carefully when architecting an application.

Session Timeout
By default, on most servers the session is set to expire after 30 minutes of inactivity. The amount of time can be configured in the deployment descriptor of the Web application. The HttpSession API also provides a setMaxInactiveInterval() method that you can use to specify the timeout period for a session. The getMaxInactiveInterval() method will return this timeout value. The value given is in seconds.

The length of time will vary depending on what your visitors are doing on your site. If they're logging in to check their account balance, a shorter session timeout period can be used because it doesn't take long for a person to read a couple of numbers. If, on the other hand, the user is logging in to read large amounts of data, you need to be sure that you provide enough time for the user to do what he or she wants without being logged out. If the user is constantly navigating through your site, the session will last indefinitely.

Implement Serializable
It's important to make sure that all objects placed in the session can be serialized. This may not be an issue if you know that your Web application will not run in a cluster, but it should still be done anyway. What happens if your Web site grows too big for one server and you suddenly have to move to two? If you implement Serializable in your code now, you won't have to go back and do it later.

Keep It Simple
You should design objects that are going to be placed into a session so that they're not too big and don't contain unnecessary information. A JavaBean that contains a customer's name, address, phone number, e-mail address, credit card numbers, and order history should not be placed into the session if you're only going to use the object to get the customer's name.

Session Contents
When you're working on a Web site, it's important to know which objects are in the session and why they're needed. The size of the session should be kept as small as possible. If you're building a new Web site, work out ahead of time what goes in the session, why it's there, and where it gets removed. If you're redesigning an existing site, this may be a little tougher, especially when you have hundreds of servlets and JSPs to deal with. In this case, try implementing an HttpSessionAttributeListener to get an idea of what is going into the session. With this information, you may be able to better manage your sessions.

Conclusion
Hopefully this article helped you to better understand the design issues involved in using the HttpSession interface. Java provides a more robust session implementation than other languages. It's because of this power and flexibility that you must take the time to properly lay out the use of the session. A well-designed session will help make a Web application better for the programmers and the users.

References

  • Hall, M. (2002). More Servlets and JavaServer Pages. Prentice Hall PTR.
  • Java Servlet Technology: http://java.sun.com/products/servlet
  • Enterprise JavaBeans Technology: http://java.sun.com/products/ejb
  • Java BluePrints (J2EE): http://java.sun.com/blueprints/guidelines/ designing_enterprise_applications


  • 另外Q还有一些收集的材料
    关于HttpSession的误解实在是太多了,本来是一个很单的问题Q怎会搞的如此的复杂呢Q下面说说我的理解吧Q?br /> 1、HTTP协议本n?#8220;q接-h-应答-关闭q接”模式的,是一U无状态协议(HTTP只是一个传输协议)Q?br /> 2、Cookie规范是ؓ了给HTTP增加状态跟t用的(如果要精把握,仔细阅读一下相关的RFCQ,但不是唯一的手D;
    3、所谓SessionQ指的是客户端和服务端之间的一D交互过E的状态信息(数据Q;q个状态如何界定,生命期有多长Q这是应用本w的事情Q?br /> 4、由于B/S计算模型中计是在服务器端完成的Q客L只有单的昄逻辑Q所以,Session数据对客L应该是透明的不可理解的q且应该受控于服务端QSession数据要么保存到服务端QHttpSessionQ,要么在客L和服务端之间传递(Cookie或url rewritting或Hidden inputQ;
    5、由于HTTP本n的无状态性,服务端无法知道客L相发来的请求是来自一个客LQ所以,当用服务端HttpSession存储会话数据的时候客L的每个请求都应该包含一个session的标?sid, jsessionid {等)来告诉服务端Q?br /> 6、会话数据保存在服务端(如HttpSessionQ的好处是减了HTTPh的长度,提高了网l传输效率;客户端session信息存储则相反;
    7、客LSession存储只有一个办法:cookie(url rewritting和hidden input因ؓ无法做到持久化,不算Q只能作Z换session id的方式,即a method of session tracking)Q而服务端做法大致也是一个道理:容器有个session理器(如tomcat?org.apache.catalina.session包里面的c)Q提供session的生命周期和持久化管理ƈ提供讉Ksession数据?apiQ?br /> 8、用服务端q是客户端session存储要看应用的实际情늚。一般来说不要求用户注册d的公共服务系l(如googleQ采?cookie做客Lsession存储Q如google的用户偏好设|)Q而有用户理的系l则使用服务端存储。原因很昄Q无需用户d的系l唯一能够标识用户的就是用L电脑Q换一台机器就不知道谁是谁了,服务端session存储Ҏ不管用;而有用户理的系l则可以通过用户id来管理用户个人数据,从而提供Q意复杂的个性化服务Q?br /> 9、客L和服务端的session存储在性能、安全性、跨站能力、编E方便性等斚w都有一定的区别Q而且优劣ql对Q譬如TheServerSideL不用HttpSessionQ所以性能好,q很昄Q一个具有上亿的讉K用户的系l,要在服务端数据库中检索出用户的偏好信息显然是低效的,Session理器不用什么数据结构和法都要耗费大量内存和CPU旉Q而用cookieQ则Ҏ不用索和l护session数据Q服务器可以做成无状态的Q当焉效)Q?br /> reply1:
    不过我们也不能在session里面攑օq多的东?br /> 一般来说不能超q?K
    太多?br /> 对系l资源是一个很严重的浪?br /> reply2:
    4K已是很大的一个数字了?br /> 我一般喜Ƣ写一个类。封装用L陆后的一些信息?br /> 然后把这个类攑֜session中,取得直接用类的方法取相关信息Q?br />


    honzeland 2008-05-21 15:49 发表评论
    ]]>
    Svn revision retrieve and logging to databasehttp://www.aygfsteel.com/honzeland/archive/2008/04/28/196772.htmlhonzelandhonzelandMon, 28 Apr 2008 07:43:00 GMThttp://www.aygfsteel.com/honzeland/archive/2008/04/28/196772.htmlhttp://www.aygfsteel.com/honzeland/comments/196772.htmlhttp://www.aygfsteel.com/honzeland/archive/2008/04/28/196772.html#Feedback2http://www.aygfsteel.com/honzeland/comments/commentRss/196772.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/196772.html 1Q?logging to database
    l过调查Q决定采用log4j的org.apache.log4j.jdbc.JDBCAppenderQ于是采用:
    # logging to db
    log4j.logger.com.example=DEBUG, DATABASE
    log4j.additivity.com.example=false
    log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
    log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test
    log4j.appender.DATABASE.driver=org.postgresql.Driver
    log4j.appender.DATABASE.user=pguser
    log4j.appender.DATABASE.password=post
    log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('%d{ISO8601}','YYYY-MM-DD HH:MI:SS.MS'),'%c.%M:%L','%p','%m')
    log4j.appender.DB.layout=org.apache.log4j.PatternLayout
    log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601} %p %c.%M:%L %m
    很直观,用v来还很方便,但是不久出C问题Qtomcat抛出了exception。只好把之前fixed ticket reopenQ提交新的commentsQUnfortunately, org.apache.log4j.jdbc.JDBCAppender that ships with the Log4j distribution is not able to process logging messages that have characters like ' (single quote) and , (comma) in it. When logging messages contains characters like single quote or comma, the program will throw an exception.
    重新google了,扑ֈ了一个plusjdbcQLooking further, I found an alternative JDBCAppender package (org.apache.log4j.jdbcplus.JDBCAppender) from http://www.dankomannhaupt.de/projects/index.html. It can solve this problem. 长叹了一下?br />
    最后采用:
    log4j.appender.DATABASE=org.apache.log4j.jdbcplus.JDBCAppender
    log4j.appender.DATABASE.url=jdbc:postgresql://localhost:5432/test
    log4j.appender.DATABASE.dbclass=org.postgresql.Driver
    log4j.appender.DATABASE.username=pguser
    log4j.appender.DATABASE.password=post
    log4j.appender.DATABASE.sql=INSERT INTO debug_log(created, logger, priority, message) VALUES (to_timestamp('@LAYOUT:1@', 'YYYY-MM-DD HH:MI:SS.MS'),'@LAYOUT:3@','@LAYOUT:2@','@LAYOUT:4@')
    log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
    log4j.appender.DATABASE.layout.ConversionPattern=%d{ISO8601}#%p#%c.%M:%L#%m
    log4j.appender.DATABASE.layoutPartsDelimiter=#
    log4j.appender.DATABASE.buffer=1
    log4j.appender.DATABASE.commit=true
    log4j.appender.DATABASE.quoteReplace=true
    问题解决Q但是中间有点小波折Q在我的目中,log4j.jarQ?gt;1.2.9Q重复了Q在$CATALINA_HOME/lib下有一份,在web工程下的WEB-INF/lib下也有一份,而plus-jdbc.jar攄?CATALINA_HOME/lib下,l果启动TomcatQ出?br /> log4j:ERROR A "org.apache.log4j.jdbcplus.JDBCAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
    log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
    log4j:ERROR [WebappClassLoader^M
      delegate: false^M
      repositories:^M
    ----------> Parent Classloader:^M
    org.apache.catalina.loader.StandardClassLoader@1ccb029^M
    ] whereas object of type
    log4j:ERROR "org.apache.log4j.jdbcplus.JDBCAppender" was loaded by [org.apache.catalina.loader.StandardClassLoader@1ccb029].
    log4j:ERROR Could not instantiate appender named "DATABASE".
    原来是两个JDBCAppender实例不在同一个classlaoder里面Q将WEB-INF/lib下的log4j.jar删除掉,重启没问题了,按理Q将$CATALINA_HOME/lib下的plus-jdbc.jarUdWEB-INF/lib下,应该也没问题Q没有测试?br />
    2QAdd build revision info in war file and read it on tomcat startup
    q个l历比较惨痛Q两个问题,如何获取revisionQ?And how to read it when tomcat startup? W二个问题倒是没什么,采用javax.servlet.ServletContextListener可以实玎ͼ很简单,走弯路的是第一个问题,google后发现有两种常见的实玎ͼ
    As I have learned, there are totally two solutions to get svn revision info.

    First, retrieve the svn revision from local file($BASE_HOME/.svn/entries). Just parsing the xml file, get the revision property and write it to a properties file.Q就是该ȝxmlQ远在乌克兰的同事,该文件却不是xml的,也只怪自p研不充分Q还得折腾了半天Q后来发玎ͼ最新版的svnZperformance的考虑Q采用meta data来实现entriesQ?br />
    Second, retrieve the svn revision from the remote repository. The solution always use a svn client to perform a demand with remote server to retrieve the revision info. Installing a snv client and using SvnAnt? are most commonly used at present. SvnAnt? is an ant task that provides an interface to Subversion revision control system and encapsulates the svn client. It uses javahl - a native (JNI) java interface for the subversion api if it can find the corresponding library. javahl is platform-dependent.

    Because of needing interaction with the server(服务器在国外Q更新很?, now I employ the first solution. But I found a flaw of this method when i was going off duty. Generally, we may update our project with svn before committing. This may make a mismatch with svn revision between remote server and local file. Svn revision in local file is usually updated when we update our project. But when we take a commit after update, the svn revision in the remote server will change to a new one.

    So, the case is that if we update, commit, and then build, we may get a mismatch with the newest svn revision, and build the error revision into our ROOT.war. If we update , then build ,without commit, we can get right revision info.

    下面是第一版实玎ͼ
        <!--  retrieve the svn revision from the remote repository
        <path id="svnant.lib" >
            <fileset dir="${lib.dir}">
                <include name="svnant.jar"/>
                <include name="svnClientAdapter.jar"/>
                <include name="svnjavahl.jar"/>
            </fileset>
        </path>
       
        <taskdef name="svn" classpathref="svnant.lib" classname="org.tigris.subversion.svnant.SvnTask" />
       
        <target name="get-svn-revision">
            <svn username="*******" password="******" javahl="true">
                    <status urlProperty="https://example.com" path="." revisionProperty="svn.revision" />
            </svn>
            <echo>svn revision: ${svn.revision}</echo>
        </target>   
        -->
       
        <!--  retrieve the svn revision from local file(.svn/entries). The file may contain several  'wc-entries.entry.revision' elements.
        The property will get several values seperated by ',' when using xmlproperty task.  Then the svn revison expected will be the
        max one of these property values.
         -->
        <property name="svn.revision.file" value=".svn/entries" />
        <!-- This property is used to run xmlproperty task successfully with a low version of svn client (under 1.3.1). Don't  sure whether it really makes sense -->
        <property name="build.id" value="foo" />
        <target name="get-svn-revision">
            <xmlproperty file="${svn.revision.file}" collapseAttributes="true"/>
            <echo>svn revision: ${wc-entries.entry.revision}</echo>
        </target>

        <!--
            If the file doesn't contain any 'wc-entries.entry.revision' element, the content of the property file will be: revision = ${wc-entries.entry.revision};
            If contain a 'wc-entries.entry.revision' element, mark this value as $revision_value, then  the content will be: revision = $revision_value;
            If contain several 'wc-entries.entry.revision' elements, mark these values as $value1, $value2, ..., respectively, then the content will be: revision = $value1,$value2,..., seperated by a ',';
        -->
        <property name="svn.revision.propertyfile" value="${build.dir}/revision.properties" />
        <target name="write-svn-revision-to-file" depends="get-svn-revision">
            <delete file="${svn.revision.propertyfile}"/>
            <propertyfile file="${svn.revision.propertyfile}" comment="record svn revision">
                <entry  key="revision" value="${wc-entries.entry.revision}"/>
            </propertyfile>
        </target>

    l果write-svn-revision-to-fileq个在我q倒是可以获取本地的svn revisionQ但是远方的同事可急了Qbuild老失败,只好把这部分build注释了,q好Q到周末了,可以在家好好研究一下,很快找了一个新的工P
    It's my fault. In my version of svn, the entries file is xml formatted. So i parse it using ant task - 'xmlproperty'. Now i have fix this problem by using 'svnkit' tools, a pure java svn toolkit. Now there are two ways to retrieve svn revision. One is from remote repository server. For this one, before building, you should set your own username and password for the remote repository server('remote.repository.username' and 'remote.repository.password' properties in build.xml,respectively). Another one is retrieving revision from local working copy. If using this one, you should set 'local.repository' property in build.xml to your own directory.
    利用svnkitQ从服务器上获取revision大概是:
                repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(urlStr));
                ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
                repository.setAuthenticationManager(authManager);
                headRevision = repository.getLatestRevision();
    从本地working copy获取revisionQ?br />             SVNClientManager clientManager = SVNClientManager.newInstance();
                SVNWCClient wcClient = clientManager.getWCClient();   
                SVNInfo info = wcClient.doInfo(new File(fileUrl), SVNRevision.WORKING);
                headRevision = info.getRevision().getNumber(); 

    利用ant task获取的revision写入C个配|文件中Q如revision.propertiesQ?在tomcat启动的时候加载进来,可以了?nbsp;  


    honzeland 2008-04-28 15:43 发表评论
    ]]>
    Tomcat ClassLoader and load resourceshttp://www.aygfsteel.com/honzeland/archive/2008/04/24/195605.htmlhonzelandhonzelandThu, 24 Apr 2008 07:46:00 GMThttp://www.aygfsteel.com/honzeland/archive/2008/04/24/195605.htmlhttp://www.aygfsteel.com/honzeland/comments/195605.htmlhttp://www.aygfsteel.com/honzeland/archive/2008/04/24/195605.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/195605.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/195605.html
    1 - Tomcat的类载入器的l构
    Tomcat Server在启动的时候将构造一个ClassLoader树,以保证模块的cd是私有的
    Tomcat Server的ClassLoaderl构如下Q?br />         +-----------------------------+

            |         Bootstrap           |

            |             |               |

            |          System             |

            |             |               |

            |          Common             |

            |         /      \            |

            |     Catalina  Shared        |

            |               /    \        |

            |          WebApp1  WebApp2   |

            +-----------------------------+

    其中Q?br /> - Bootstrap - 载入JVM自带的类?JAVA_HOME/jre/lib/ext/*.jar
    - System - 载入$CLASSPATH/*.class
    - Common - 载入$CATALINA_HOME/common/...Q它们对TOMCAT和所有的WEB APP都可?br /> - Catalina - 载入$CATALINA_HOME/server/...Q它们仅对TOMCAT可见Q对所有的WEB APP都不可见
    - Shared - 载入$CATALINA_HOME/shared/...Q它们仅Ҏ有WEB APP可见Q对TOMCAT不可见(也不必见Q?br /> - WebApp - 载入ContextBase?/WEB-INF/...Q它们仅对该WEB APP可见

    2 - ClassLoader的工作原?br />
    每个q行中的U程都有一个成员contextClassLoaderQ用来在q行时动态地载入其它c?br /> pȝ默认的contextClassLoader是systemClassLoaderQ所以一般而言javaE序在执行时可以使用JVM自带的类?JAVA_HOME/jre/lib/ext/中的cd$CLASSPATH/中的c?br /> 可以使用Thread.currentThread().setContextClassLoader(...);更改当前U程的contextClassLoaderQ来改变其蝲入类的行?br />
    ClassLoader被组l成树ŞQ一般的工作原理是:
    1) U程需要用到某个类Q于是contextClassLoader被请求来载入该类
    2) contextClassLoaderh它的父ClassLoader来完成该载入h
    3) 如果父ClassLoader无法载入c,则contextClassLoader试图自己来蝲?br />
    注意QWebApp?ClassLoader的工作原理和上述有少怸同:
    它先试图自己载入c(在ContextBase?/WEB-INF/...中蝲入类Q,如果无法载入Q再h父ClassLoader完成

    由此可得Q?br /> - 对于WEB APPU程Q它的contextClassLoader是WebApp?ClassLoader
    - 对于Tomcat ServerU程Q它的contextClassLoader是CatalinaClassLoader

    3 cȝ查找

    ClassLoadercMloadClassҎ为缺省实玎ͼ用下面的序查找c:
    1、调用findLoadedClassҎ来检查是否已l被加蝲。如果没有则l箋下面的步骤?br /> 2、如果当前类装蝲器有一个指定的委托父装载器Q则用委托父装蝲器的loadClassҎ加蝲c,也就是委托给父装载器加蝲相应的类?br /> 3、如果这个类装蝲器的委托层体系没有一个类装蝲器加载该c,则用类装蝲器定位类的特定实现机Ӟ调用findClassҎ来查扄?br />
    4 - 部分原代码分?br /> 4.1 - org/apache/catalina/startup/Bootstrap.java
    Bootstrap中定义了三个classloader:commonLoader,catalinaLoader,sharedLoader.三者关pd下:
    //注意三个自己定置的ClassLoader的层ơ关p:
                // systemClassLoader (root)
                //   +--- commonLoader
                //          +--- catalinaLoader
                //          +--- sharedLoader

    Tomcat ServerU程的v?br /> 构造ClassLoader树,通过Thread.currentThread().setContextClassLoader(catalinaLoader)讄当前的classloader为catalinaLoader?br /> 载入若干c,然后转入org.apache.catalina.startup.CatalinacM

    4.2 org.apache.catalina.loader.StandardClassLoader.java

    通过看loadClassq个Ҏ来看tomcat是如何加载类的,序如下Q?br />
    (0) Check our previously loaded class cache查找已经装蝲的class
            clazz = findLoadedClass(name);

    (1) If a system class, use system class loader通过pȝclassloader来装载class
            ClassLoader loader = system;
                clazz = loader.loadClass(name);

    (2) Delegate to our parent if requested如果有代理则使用父类classloader
                ClassLoader loader = parent;
                if (loader == null)
                    loader = system;
                clazz = loader.loadClass(name);

    (3) Search local repositories 查找本地cLQ比?CATALINA_HOME/server
               clazz = findClass(name);

    (4) Delegate to parent unconditionally 默认使用代理装蝲?br />
    [查看代码]

    4.3 - org/apache/catalina/startup/ClassLoaderFactory.java

    Ҏ讄创徏q返回StandardClassLoader的实?br />
    [查看代码]

    4.4 - org/apache/catalina/loader/StandardClassLoader.java

    c蝲入器

    4.5 - org/apache/catalina/startup/SecurityClassLoad.java

    该类仅包含一个静态方法,用来为catalinaLoader载入一些类

    [查看代码]

    Appendix - 参?br />
    [1] http://jakarta.apache.org/tomcat/中的Tomcat 4.1.x文档Class Loader HOW-TO

    在一个JVM中可能存在多个ClassLoaderQ每个ClassLoader拥有自己的NameSpace。一个ClassLoader只能拥有一个class对象cd的实例,但是不同的ClassLoader可能拥有相同的class对象实例Q这时可能生致命的问题。如ClassLoaderAQ装载了cA的类型实例A1Q而ClassLoaderBQ也装蝲了类A的对象实例A2。逻辑上讲A1=A2Q但是由于A1和A2来自于不同的ClassLoaderQ它们实际上是完全不同的Q如果A中定义了一个静态变量cQ则c在不同的ClassLoader中的值是不同的?br />
    [2] 深入Java2q_安全

    zz: http://mail-archives.apache.org/mod_mbox/tomcat-users/200212.mbox/raw/%3c20021204192034.P86616-100000@icarus.apache.org%3e
    try {
        Properties props = new Properties();
        InputStream in = getClass().getResourceAsStream("/conf/db.properties");
        props.load(in);
        ......
        propertie1 = props.getProperty("propertie1");

    The examples already given will find properties files for you just fine whether the file is in a directory structure or inside an archive.  How do you think Java loads classes?  It works out of archives, no? here are some various was to access a properties file ( or any resource, for that matter) in whether the app is deployed as a directory or as a .war file (even inside a .jar file in WEB-INF/lib)....

    1. This will load a file in WEB-INF/classes/conf or any jar file in the classpath with a package of "conf"...
        getClass().getResourceAsStream("/conf/db.properties");
    2. This will load a file relative to the current class.  For instance, if the class is "org.mypackage.MyClass", then the file would be loaded at "org.mypackage.conf.dbproperties".  Note that this is because we didn't prepend "/" to the path.  When that is done, the file is loaded from the root of the current classloader where this loads it relative to the current class...
        getClass().getResourceAsStream("conf/db.properties");
    3. This will find db.properties anywhere in the current classloader as long as it exists in a "conf" package...
        getClass().getClassLoader().getResourceAsStream("conf/db.properties");
    4. This will find the file in a "conf" directory inside the webapp (starting from the root).  This starts looking in the same directory as contains WEB-INF.  When I say "directory", I don't mean "filesystem".  This could be in a .war file as well as in an actual directory on the filesystem...
        getServletContext().getResourceAsStream("/conf/db.properties");
    5. Of course you would probably not want just anyone seeing your db.properties file, so you'd probably want to put in inside WEB-INF of your webapp, so....
        getServletContext().getResourceAsStream("/WEB-INF/conf/db.properties");
    6. If your db.properties exists in another classloader which your app has access to, you can reach it by using:
        Thread.currentThread().getContextClassLoader().getResourceAsStream("conf/db.properties");
    that will act similar to getClass().getClassLoader(), but it can see across all available classloaders where the latter can only see within the classloader that loaded the current class.

    honzeland 2008-04-24 15:46 发表评论
    ]]>
    Double Checked Locking 模式http://www.aygfsteel.com/honzeland/archive/2008/02/19/180666.htmlhonzelandhonzelandTue, 19 Feb 2008 06:21:00 GMThttp://www.aygfsteel.com/honzeland/archive/2008/02/19/180666.htmlhttp://www.aygfsteel.com/honzeland/comments/180666.htmlhttp://www.aygfsteel.com/honzeland/archive/2008/02/19/180666.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/180666.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/180666.html Double-checked locking: Clever, but broken
    Warning! Threading in a multiprocessor world

    When is a singleton not a singleton?


    honzeland 2008-02-19 14:21 发表评论
    ]]>
    实现java UDP Server Q-2008农历新年W一_原创Q?/title><link>http://www.aygfsteel.com/honzeland/archive/2008/02/15/180097.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 15 Feb 2008 08:19:00 GMT</pubDate><guid>http://www.aygfsteel.com/honzeland/archive/2008/02/15/180097.html</guid><wfw:comment>http://www.aygfsteel.com/honzeland/comments/180097.html</wfw:comment><comments>http://www.aygfsteel.com/honzeland/archive/2008/02/15/180097.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.aygfsteel.com/honzeland/comments/commentRss/180097.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/honzeland/services/trackbacks/180097.html</trackback:ping><description><![CDATA[一、UDP Server<br /> 目的需要,需要利用java实现一个udp serverQ主要的功能是侦听来自客L的udphQ客戯求可能是大ƈ发量的,对于每个hServer端的处理很简单,处理每个h的时间大U在1ms左右Q但是Server端需要维护一个对立于h的全局变量CacheQ项目本w已l采用Mina架构Qhttp://mina.apache.org/Q,我要开发的Server作ؓ整个目的一个模块,׃之前没有开发UDP ServerQ受TCP Server的媄响,很自然的惛_用多U程来实玎ͼ对于每个客户hQ新Z个线E来处理相应的逻辑Q在实现的过E中Q利用Mina的Thread ModelQ实C一个多U程的UDP ServerQ但是由于要l护一个全局CacheQ需要在各线E之间同步,加之处理h的时间很短,很快发现在此利用多U程Qƈ不能提高性能Q于是决定采用单U程来实玎ͼ在动手之前,q是发现有两U方案来实现单线EUDP ServerQ?br /> 1Q?采用JDK的DatagramSocket和DatagramPacket来实?br /> public class UDPServerUseJDK extends Thread{ <br />     /**<br />      * Constructor<br />      * @param port port used to listen incoming connection<br />      * @throws SocketException error to consturct a DatagramSocket with this port<br />      */<br />     public MediatorServerUseJDK(int port) throws SocketException{<br />         this("MediatorServerThread", port);<br />     }<br />     <br />     /**<br />      * Constructor<br />      * @param name the thread name<br />      * @param port port used to listen incoming connection<br />      * @throws SocketException error to consturct a DatagramSocket with this port<br />      */<br />     public MediatorServerUseJDK(String name, int port) throws SocketException{<br />         super(name);<br />         socket = new DatagramSocket(port); <br />         System.out.println("Mediator server started on JDK model...");<br />         System.out.println("Socket buffer size: " + socket.getReceiveBufferSize());<br />     }<br />     <br />     public void run(){<br />         long startTime = 0;<br />         while(true){<br />             try {<br />                 buf = new byte[1024];<br />                 // receive request<br />                 packet = new DatagramPacket(buf, buf.length);<br />                 socket.receive(packet); <br />                 .........<br />             }catch (IOException e) {<br />             .........<br />             }<br />         }<br />     }<br /> ?br /> 2Q?采用Mina的DatagramAcceptor来实玎ͼ在创建Exector的时候,只传递单个线E?br /> public class MediatorServerUseMina {<br />     private DatagramAcceptor acceptor;<br /> <br />     public MediatorServerUseMina() {<br /> <br />     }<br /> <br />     public void startListener(InetSocketAddress address, IoHandler handler) {<br />         // create an acceptor with a single thread<br />         this.acceptor = new DatagramAcceptor(Executors.newSingleThreadExecutor());<br />         // configure the thread models<br />         DatagramAcceptorConfig acceptorConfig = acceptor.getDefaultConfig();<br />         acceptorConfig.setThreadModel(ThreadModel.MANUAL);<br />         // set the acceptor to reuse the address<br />         acceptorConfig.getSessionConfig().setReuseAddress(true);<br />         // add io filters<br />         DefaultIoFilterChainBuilder filterChainBuilder = acceptor.getFilterChain();<br />         // add CPU-bound job first,<br />         filterChainBuilder.addLast("codec", new ProtocolCodecFilter(new StringCodecFactory())); <br />         try {<br />             // bind<br />             acceptor.bind(address, handler);<br />             System.out.println("Mediator Server started on mina model...");<br />             System.out.println("Socket buffer size: " + acceptorConfig.getSessionConfig().getReceiveBufferSize());<br />         } catch (IOException e) {<br />             System.err.println("Error starting component listener on port(UDP) " + address.getPort() + ": "<br />                     + e.getMessage());<br />         }<br />     } <br /> }<br /> 二、Performance Test<br /> Z试两个Server的性能Q写了个单的试客户?br /> import java.io.IOException;<br /> import java.net.DatagramPacket;<br /> import java.net.DatagramSocket;<br /> import java.net.InetAddress;<br /> import java.net.SocketException;<br /> import java.net.UnknownHostException;<br /> <br /> /**<br />  * @author Herry Hong<br />  * <br />  */<br /> <br /> public class PerformanceTest {<br />     /** Number of threads to be created */<br />     static final int THREADS = 100;<br />     /** Packets to be sent per thread */<br />     static final int PACKETS = 500;<br />     /** The interval of two packets been sent for each thread */<br />     private static final int INTERVAL = 80;<br />     private static final String DATA = "5a76d93cb435fc54eba0b97156fe38f432a4e1da3a87cce8a222644466ed1317";<br /> <br />     private class Sender implements Runnable {<br />         private InetAddress address = null;<br />         private DatagramSocket socket = null;<br />         private String msg = null;<br />         private String name = null;<br />         private int packet_sent = 0;<br /> <br />         public Sender(String addr, String msg, String name) throws SocketException,<br />                 UnknownHostException {<br />             this.address = InetAddress.getByName(addr);<br />             this.socket = new DatagramSocket();<br />             this.msg = msg;<br />             this.name = name;<br />         }<br /> <br />         @Override<br />         public void run() {<br />             // send request<br />             byte[] buf = msg.getBytes();<br />             DatagramPacket packet = new DatagramPacket(buf, buf.length,<br />                     address, 8000);<br />             try {<br />                 for (int i = 0; i < PerformanceTest.PACKETS; i++) {<br />                     socket.send(packet);<br />                     packet_sent++;<br />                     Thread.sleep(INTERVAL);<br />                 }<br />             } catch (IOException e) {<br />                 e.printStackTrace();<br />             } catch (InterruptedException e) {<br />                 e.printStackTrace();<br />             }<br />             //System.out.println("Thread " + name + " sends " + packet_sent + " packets.");<br />             //System.out.println("Thread " + name + " end!");<br />         }<br />     }<br /> <br />     /**<br />      * @param args<br />      */<br />     public static void main(String[] args) {<br />         if (args.length != 1) {<br />             System.out.println("Usage: java PerformanceTest <hostname>");<br />             return;<br />         }<br />         String msg; <br />         for (int i = 0; i < THREADS; i++) {<br />             if(i % 2 == 0){<br />                 msg = i + "_" + (i+1) + ""r"n" + (i+1) + "_" + i + ""r"n" + DATA;<br />             }else{<br />                 msg = i + "_" + (i-1) + ""r"n" + (i-1) + "_" + i + ""r"n" + DATA;<br />             }<br />             try {<br />                 new Thread(new PerformanceTest().new Sender(args[0], msg, "" + i)).start();<br />             } catch (SocketException e) { <br />                 e.printStackTrace();<br />             } catch (UnknownHostException e) { <br />                 e.printStackTrace();<br />             }<br />         } <br />     }<br /> }<br /> 三、测试结?br /> 试环境Q?br /> ServerQAMD Athlon(tm) 64 X2 Dual Core Processor 4000+Q?G memory<br /> ClientQAMD Athlon(tm) 64 X2 Dual Core Processor 4000+Q?G memory<br /> 在测试的q程中,当INTERVAL讄的太时Q服务器端会出现丢包现象QINTERVAL小Q丢包越严重Qؓ了提高Server的性能Q特Socket的ReceiveBufferSize讄成默认大的两倍,<br /> 对于JDK实现Q?br />     public MediatorServerUseJDK(String name, int port) throws SocketException{<br />         super(name);<br />         socket = new DatagramSocket(port);<br />         // set the receive buffer size to double default size<br />         socket.setReceiveBufferSize(socket.getReceiveBufferSize() * 2); <br />         System.out.println("Mediator server started on JDK model...");<br />         System.out.println("Socket buffer size: " + socket.getReceiveBufferSize());<br />     }<br /> 对于Mina实现Q?br />         DatagramAcceptorConfig acceptorConfig = acceptor.getDefaultConfig();<br />         acceptorConfig.setThreadModel(ThreadModel.MANUAL);<br />         // set the acceptor to reuse the address<br />         acceptorConfig.getSessionConfig().setReuseAddress(true);<br />         // set the receive buffer size to double default size<br />         int recBufferSize = acceptorConfig.getSessionConfig().getReceiveBufferSize();<br />         acceptorConfig.getSessionConfig().setReceiveBufferSize(recBufferSize * 2);<br /> 此时Q相同的INTERVALQ丢包现象明昑և?br /> 接下来,再测试不同实现的性能差异Q?br /> UDP server started on JDK model...<br /> Socket buffer size: 110592<br /> INTERVAL Q?100msQ没有出C包,<br /> Process time: 49988<br /> Process time: 49982<br /> Process time: 49984<br /> Process time: 49986<br /> Process time: 49984<br /> INTERVAL Q?80msQ仍然没有丢包,不管Server是不是初ơ启?br /> Process time: 40006<br /> Process time: 40004<br /> Process time: 40003<br /> Process time: 40005<br /> Process time: 40013<br /> UDP Server started on mina model...<br /> Socket buffer size: 110592<br /> INTERVAL Q?80msQServer初次启动Ӟl常会出C包,当第一ơ(指服务器初次启动Ӟ没有丢包Ӟ随后基本不丢包,<br /> Process time: 39973<br /> Process time: 40006<br /> Process time: 40007<br /> Process time: 40008<br /> Process time: 40008<br /> INTERVAL Q?100msQ没有出C?br /> Process time: 49958<br /> Process time: 49985<br /> Process time: 49983<br /> Process time: 49988<br /> 四、结?br /> 在该要求下,采用JDK和Mina实现性能相当Q但是在Server初次启动时JDK实现基本不会出现丢包Q而Mina实现则在Server初次启动时经常出C包现象,在经历第一ơ测试后Q两U实现处理时间相q,hq发量大概ؓ每ms一个请求时Q服务器不会出现丢包?br /> <br /> <img src ="http://www.aygfsteel.com/honzeland/aggbug/180097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/honzeland/" target="_blank">honzeland</a> 2008-02-15 16:19 <a href="http://www.aygfsteel.com/honzeland/archive/2008/02/15/180097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Openfire导入到Eclipse?/title><link>http://www.aygfsteel.com/honzeland/archive/2008/01/25/177812.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 25 Jan 2008 09:36:00 GMT</pubDate><guid>http://www.aygfsteel.com/honzeland/archive/2008/01/25/177812.html</guid><wfw:comment>http://www.aygfsteel.com/honzeland/comments/177812.html</wfw:comment><comments>http://www.aygfsteel.com/honzeland/archive/2008/01/25/177812.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.aygfsteel.com/honzeland/comments/commentRss/177812.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/honzeland/services/trackbacks/177812.html</trackback:ping><description><![CDATA[1?从Openfire SVN Server中dump出源码;<br /> 2?Build: ant  & ant plugins<br /> 3?build后的target/openfire作ؓopenfire_home<br /> 4?在target/openfire下徏立两个目录:src和classesQ将dump下来的源码copy到src路径下,classes讄为eclipse~译后的输出路径<br /> 5??openfire_home/lib下的openfire.jar中src中存在的部分删除Q剩下的部分作ؓ新的openfire.jarQ注意,在ubuntu下之间打开openfire.jarӞ直接?org/jivesoftware/admin, /org/jivesoftware/openfire, /org/jivesoftware/util三个目录删除Q而对?org/jivesoftware/database目录Q只源码中有的那部分删除,/org/jivesoftware下面q有一个隐藏目?org/jivesoftware/stringprepQ不能删除,接下来,?openfire_home/lib下的jar包作为工E的Referenced Libraries.<br /> 6?取出来的工E下src/web/WEB-INF/classes/openfire_init.xml导入到eclipse的查询\径里Q如src/web/WEB-INF/classes目录作ؓeclipse的源目录Q这样openfire_init.xml自动copy?openfire_home/classses下面Q将openfire_init.xml中的openfireHome讄?openfire_home<br /> 7?修改org.jivesoftware.openfire.starter.ServerStarter中的如下两个fieldQ?br />            private static final String DEFAULT_LIB_DIR = "../lib";<br />            private static final String DEFAULT_ADMIN_LIB_DIR = "../plugins/admin/webapp/WEB-INF/lib";<br /> ҎQ?br />            private static final String DIR_PREFIX = "$openfire_home";     // to be your own openfire_home<br />            private static final String DEFAULT_LIB_DIR = DIR_PREFIX + "lib";<br />            private static final String DEFAULT_ADMIN_LIB_DIR = DIR_PREFIX + "plugins/admin/webapp/WEB-INF/lib";<br /> <img src ="http://www.aygfsteel.com/honzeland/aggbug/177812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/honzeland/" target="_blank">honzeland</a> 2008-01-25 17:36 <a href="http://www.aygfsteel.com/honzeland/archive/2008/01/25/177812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DWR 调用q回值方?/title><link>http://www.aygfsteel.com/honzeland/archive/2008/01/15/175465.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Tue, 15 Jan 2008 06:45:00 GMT</pubDate><guid>http://www.aygfsteel.com/honzeland/archive/2008/01/15/175465.html</guid><wfw:comment>http://www.aygfsteel.com/honzeland/comments/175465.html</wfw:comment><comments>http://www.aygfsteel.com/honzeland/archive/2008/01/15/175465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/honzeland/comments/commentRss/175465.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/honzeland/services/trackbacks/175465.html</trackback:ping><description><![CDATA[zz: http://daoger.javaeye.com/blog/47801<br /> <br /> 2.调用有简单返回值的javaҎ <br /> 2.1?span class="hilite1">dwr</span>.xml的配|? <br /> 配置?.1 <br /> <<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <allow> <br /> <create creator="new" javascript="testClass" > <br /> <param name="class" value="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass" /> <br /> <include method="testMethod2"/> <br /> </create> <br /> </allow> <br /> </<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> 2.2、javascript中调? <br /> 首先Q引入javascript脚本 <br /> 其次Q编写调用javaҎ的javascript函数和接收返回值的回调函数 <br /> Function callTestMethod2(){ <br /> testClass.testMethod2(callBackFortestMethod2); <br /> } <br /> Function callBackFortestMethod2(data){ <br /> //其中date接收Ҏ的返回? <br /> //可以在这里对q回D行处理和昄{等 <br /> alert("the return value is " + data); <br /> } <br /> 其中callBackFortestMethod2是接收返回值的回调函数 <br /> <br /> <br /> 3、调用有单参数的javaҎ <br /> 3.1?span class="hilite1">dwr</span>.xml的配|? <br /> 配置?.1 <br /> <<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <allow> <br /> <create creator="new" javascript="testClass" > <br /> <param name="class" value="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass" /> <br /> <include method="testMethod3"/> <br /> </create> <br /> </allow> <br /> </<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> 3.2、javascript中调? <br /> 首先Q引入javascript脚本 <br /> 其次Q编写调用javaҎ的javascript函数 <br /> Function callTestMethod3(){ <br /> //定义要传到javaҎ中的参数 <br /> var data; <br /> //构造参? <br /> data = “test String”; <br /> testClass.testMethod3(data); <br /> } <br /> <br /> <br /> 4、调用返回JavaBean的javaҎ <br /> 4.1?span class="hilite1">dwr</span>.xml的配|? <br /> <<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <allow> <br /> <create creator="new" javascript="testClass" > <br /> <param name="class" value="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass" /> <br /> <include method="testMethod4"/> <br /> </create> <br /> <convert converter="bean" match=""com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestBean"> <br /> <param name="include" value="username,password" /> <br /> </convert> <br /> </allow> <br /> </<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <creator>标签负责公开用于Webq程的类和类的方法,<convertor>标签则负责这些方法的参数和返回类型。convert元素的作用是告诉<span id="wmqeeuq" class="hilite1">DWR</span>在服务器端Java 对象表示和序列化的JavaScript之间如何转换数据cd?span class="hilite1">DWR</span>自动地在Java和JavaScript表示之间调整单数据类型。这些类型包括Java原生cd和它们各自的装c表C,q有String、Date、数l和集合cd?span class="hilite1">DWR</span>也能把JavaBean转换成JavaScript 表示Q但是出于安全性的原因Q要求显式的配置Q?lt;convertor>标签是完成此功能的。converter="bean"属性指定{换的方式采用JavaBean命名规范Qmatch=""com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestBean"属性指定要转换的javabean名称Q?lt;param>标签指定要{换的JavaBean属性? <br /> 4.2、javascript中调? <br /> 首先Q引入javascript脚本 <br /> 其次Q编写调用javaҎ的javascript函数和接收返回值的回调函数 <br /> Function callTestMethod4(){ <br /> testClass.testMethod4(callBackFortestMethod4); <br /> } <br /> Function callBackFortestMethod4(data){ <br /> //其中date接收Ҏ的返回? <br /> //对于JavaBeanq回|有两U方式处? <br /> //不知道属性名U时Q用如下方? <br /> for(var property in data){ <br /> alert("property:"+property); <br /> alert(property+":"+data[property]); <br /> } <br /> //知道属性名U时Q用如下方? <br /> alert(data.username); <br /> alert(data.password); <br /> } <br /> 其中callBackFortestMethod4是接收返回值的回调函数 <br /> <br /> 5、调用有JavaBean参数的javaҎ <br /> 5.1?span class="hilite1">dwr</span>.xml的配|? <br /> 配置?.1 <br /> <<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <allow> <br /> <create creator="new" javascript="testClass" > <br /> <param name="class" value="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass" /> <br /> <include method="testMethod5"/> <br /> </create> <br /> <convert converter="bean" match="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestBean"> <br /> <param name="include" value="username,password" /> <br /> </convert> <br /> </allow> <br /> </<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> 5.2、javascript中调? <br /> 首先Q引入javascript脚本 <br /> 其次Q编写调用javaҎ的javascript函数 <br /> Function callTestMethod5(){ <br /> //定义要传到javaҎ中的参数 <br /> var data; <br /> //构造参敎ͼdate实际上是一个object <br /> data = { username:"user", password:"password" } <br /> testClass.testMethod5(data); <br /> } <br /> <br /> <br /> 6、调用返回List、Set或者Map的javaҎ <br /> 6.1?span class="hilite1">dwr</span>.xml的配|? <br /> 配置?.1 <br /> <<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <allow> <br /> <create creator="new" javascript="testClass" > <br /> <param name="class" value="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass" /> <br /> <include method="testMethod6"/> <br /> </create> <br /> <convert converter="bean" match="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestBean"> <br /> <param name="include" value="username,password" /> <br /> </convert> <br /> </allow> <br /> </<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> 注意Q如果List、Set或者Map中的元素均ؓ单类型(包括其封装类Q或String、Date、数l和集合cdQ则不需?lt;convert>标签? <br /> 6.2、javascript中调?以返回ListZQList的元素ؓTestBean) <br /> 首先Q引入javascript脚本 <br /> 其次Q编写调用javaҎ的javascript函数和接收返回值的回调函数 <br /> Function callTestMethod6(){ <br /> testClass.testMethod6(callBackFortestMethod6); <br /> } <br /> Function callBackFortestMethod6(data){ <br /> //其中date接收Ҏ的返回? <br /> //对于JavaBeanq回|有两U方式处? <br /> //不知道属性名U时Q用如下方? <br /> for(var i=0;i<data.length;i++){ <br /> for(var property in data){ <br /> alert("property:"+property); <br /> alert(property+":"+data[property]); <br /> } <br /> } <br /> //知道属性名U时Q用如下方? <br /> for(var i=0;i<data.length;i++){ <br /> alert(data[i].username); <br /> alert(data[i].password); <br /> } <br /> } <br /> <br /> <br /> 7、调用有List、Set或者Map参数的javaҎ <br /> 7.1?span class="hilite1">dwr</span>.xml的配|? <br /> <<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <allow> <br /> <create creator="new" javascript="testClass" > <br /> <param name="class" value="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass" /> <br /> <include method="testMethod7"/> <br /> </create> <br /> <convert converter="bean" match="com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestBean"> <br /> <param name="include" value="username,password" /> <br /> </convert> <br /> </allow> <br /> <<span id="wmqeeuq" class="hilite2">signatures</span>> <br /> <![CDATA[ <br /> import java.util.List; <br /> import com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass; <br /> import com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestBean; <br /> TestClass.testMethod7(List<TestBean>); <br /> ]]> <br /> </<span id="wmqeeuq" class="hilite2">signatures</span>> <br /> </<span id="wmqeeuq" class="hilite1">dwr</span>> <br /> <<span id="wmqeeuq" class="hilite2">signatures</span>>标签是用来声明javaҎ中List、Set或者Map参数所包含的确切类Q以便java代码作出判断? <br /> 7.2、javascript中调?以返回ListZQList的元素ؓTestBean) <br /> 首先Q引入javascript脚本 <br /> 其次Q编写调用javaҎ的javascript函数 <br /> Function callTestMethod7(){ <br /> //定义要传到javaҎ中的参数 <br /> var data; <br /> //构造参敎ͼdate实际上是一个object数组Q即数组的每个元素均为object <br /> data = [ <br /> { <br /> username:"user1", <br /> password:"password2" <br /> }, <br /> { <br /> username:"user2", <br /> password:" password2" <br /> } <br /> ]; <br /> testClass.testMethod7(data); <br /> } <br /> <br /> 注意Q? <br /> 1、对于第6U情况,如果javaҎ的返回gؓMapQ则在接收该q回值的javascript回调函数中如下处理: <br /> function callBackFortestMethod(data){ <br /> //其中date接收Ҏ的返回? <br /> for(var property in data){ <br /> var bean = data[property]; <br /> alert(bean.username); <br /> alert(bean.password); <br /> } <br /> } <br /> 2、对于第7U情况,如果java的方法的参数为MapQ假讑օkey为StringQvalue为TestBeanQ,则在调用该方法的javascript函数中用如下Ҏ构造要传递的参数Q? <br /> function callTestMethod (){ <br /> //定义要传到javaҎ中的参数 <br /> var data; <br /> //构造参敎ͼdate实际上是一个objectQ其属性名为Map的keyQ属性gؓMap的value <br /> data = { <br /> "key1":{ <br /> username:"user1", <br /> password:"password2" <br /> }, <br /> "key2":{ <br /> username:"user2", <br /> password:" password2" <br /> } <br /> }; <br /> testClass.testMethod(data); <br /> } <br /> q且?span class="hilite1">dwr</span>.xml中增加如下的配置D? <br /> <<span id="wmqeeuq" class="hilite2">signatures</span>> <br /> <![CDATA[ <br /> import java.util.List; <br /> import com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestClass; <br /> import com.<span id="wmqeeuq" class="hilite1">dwr</span>.TestBean; <br /> TestClass.testMethod7(Map<String,TestBean>); <br /> ]]> <br /> </<span id="wmqeeuq" class="hilite2">signatures</span>> <br /> 3、由以上可以发现Q对于javaҎ的返回gؓList(Set)的情况,<span id="wmqeeuq" class="hilite1">DWR</span>其转化为Object数组Q传递个javascriptQ对于javaҎ的返回gؓMap的情况,<span id="wmqeeuq" class="hilite1">DWR</span>其转化Z个ObjectQ其中Object的属性ؓ原Map的key|属性gؓ原Map相应的value倹{? <br /> 4、如果javaҎ的参CؓList(Set)和Map的情况,javascript中也要根?U所_构造相应的javascript数据来传递到java中?br /> <img src ="http://www.aygfsteel.com/honzeland/aggbug/175465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/honzeland/" target="_blank">honzeland</a> 2008-01-15 14:45 <a href="http://www.aygfsteel.com/honzeland/archive/2008/01/15/175465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>glassfish java.net.UnknownHostException: xxx: xxxhttp://www.aygfsteel.com/honzeland/archive/2008/01/09/174021.htmlhonzelandhonzelandWed, 09 Jan 2008 07:19:00 GMThttp://www.aygfsteel.com/honzeland/archive/2008/01/09/174021.htmlhttp://www.aygfsteel.com/honzeland/comments/174021.htmlhttp://www.aygfsteel.com/honzeland/archive/2008/01/09/174021.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/174021.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/174021.html xxx@xxx:/opt$ asadmin start-domain domain1
    Jan 9, 2008 2:49:18 PM com.sun.enterprise.util.ASenvPropertyReader setSystemProperties
    SEVERE: property_reader.unknownHost
    java.net.UnknownHostException: xxx: xxx
            at java.net.InetAddress.getLocalHost(InetAddress.java:1353)
            at com.sun.enterprise.util.net.NetUtils.getCanonicalHostName(NetUtils.java:102)
            at com.sun.enterprise.util.ASenvPropertyReader.setSystemProperties(ASenvPropertyReader.java:201)
            at com.sun.enterprise.cli.commands.S1ASCommand.<init>(S1ASCommand.java:164)
            at com.sun.enterprise.cli.commands.BaseLifeCycleCommand.<init>(BaseLifeCycleCommand.java:101)
            at com.sun.enterprise.cli.commands.StartDomainCommand.<init>(StartDomainCommand.java:78)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
            at java.lang.Class.newInstance0(Class.java:355)
            at java.lang.Class.newInstance(Class.java:308)
            at com.sun.enterprise.cli.framework.CommandFactory.createCommand(CommandFactory.java:91)
            at com.sun.enterprise.cli.framework.CLIMain.invokeCommand(CLIMain.java:160)
            at com.sun.enterprise.cli.framework.CLIMain.main(CLIMain.java:79)
    Starting Domain domain1, please wait.
    Log redirected to /opt/glassfish/domains/domain1/logs/server.log.
    Redirecting output to /opt/glassfish/domains/domain1/logs/server.log
    Domain domain1 is ready to receive client requests. Additional services are being started in background.
    java.net.UnknownHostException: hongzeguo: hongzeguo
    CLI156 Could not start the domain domain1.

    SolutionQ?br /> xxx@xxx:/opt$ nslookup xxx
    Server:         202.106.46.151
    Address:        202.106.46.151#53

    ** server can't find xxx: NXDOMAIN

    Check your /etc/hosts file. Does it have an entry with actual name and ip address of your box?
    For example: append follows  to /etc/hosts
    127.0.0.1 xxx




    honzeland 2008-01-09 15:19 发表评论
    ]]>
    JMock Exampleshttp://www.aygfsteel.com/honzeland/archive/2007/12/13/167464.htmlhonzelandhonzelandThu, 13 Dec 2007 04:45:00 GMThttp://www.aygfsteel.com/honzeland/archive/2007/12/13/167464.htmlhttp://www.aygfsteel.com/honzeland/comments/167464.htmlhttp://www.aygfsteel.com/honzeland/archive/2007/12/13/167464.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/167464.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/167464.html
    The servlet:
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.ServletException;
    import java.io.IOException;
    import java.util.Map;

    public class MyServlet extends HttpServlet {
        private MyService myService;
        public void setMyService(MyService myService) {
            this.myService = myService;
        }

        public void process(HttpServletRequest request, HttpServletResponse response) {
            String action = request.getParameter("action");
            if ("update".equals(action)) {
                Map parameters = request.getParameterMap();
                try {
                    myService.updateModel(parameters);
                } catch (MyException e) {
                    request.setAttribute("error", e.getMessage());
                }
            }
            request.setAttribute("model", myService.getModel());
            getServletContext().getRequestDispatcher("myView.jsp").forward(request, response);
        }

        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            process(request, response);
        }
    }

    The unit test:
        * if the action is update, does it call myService.updateModel (example is below)
        * if myService.updateModel throws an exception does the response contain the exceptions message (not implemented below)
    import org.jmock.Mock;
    import org.jmock.MockObjectTestCase;
    public class MyServletTest extends MockObjectTestCase {
        private Mock mockMyService;
        private Mock mockRequest;
        private Mock mockResponse;
        private MyService myService;
        private HttpServletRequest request;
        private HttpServletResponse response;
        private MyServlet myServlet;
        
        protected void setUp() throws java.lang.Exception {
            mockMyService = mock(MyService.class);
            mockRequest = mock(HttpServletRequest.class);
            mockResponse = mock(HttpServletResponse.class);
            myService = (MyService) mockMyService.proxy();
            request = (HttpServletRequest) mockRequest.proxy();
            response = (HttpServletResponse) mockResponse.proxy();
            myServlet = new MyServlet();
        }

        public void testUpdate() {
            // SETUP ANY OBJECTS USED ONLY IN THIS TESTCASE
            Map parameters = new Hashtable();
            // SETUP THE EXPECTED CALLS TO THE MOCK OBJECTS
            // setup the mock request object to have the getParameter
            // method called once with argument being equal to the
            // string action and have it return the string update
            mockRequest.expects(once()).method("getParameter").
                with(eq("action")).will(returnValue("update"));
            // setup the mock request object to have the getParameterMap
            // method called once with no arguments and have it
            // return an empty map
            mockRequest.expects(once()).method("getParameterMap")
                .will(returnValue(parameters));
            // setup the mock myService object to have the updateModel
            // method called once with the parameters map as the
            // argument
            mockMyService.expects(once()).method("updateModel").with(same(parameters));
            // setup the mock myService object to have the getModel
            // method called once with no arguments and have it
            // return an empty map
            mockMyService.expects(once()).method("getModel")
                .will(returnValue(parameters));
            // setup the mock myService object to have the updateModel
            // method called once with the parameters map as the
            // argument
            mockRequest.expects(once()).method("setAttribute").with(eq("model"), same(parameters));
            // RUN THE TEST
            // add the myService mock object to the servlet so
            // that it can handle calls later
            myServlet.setMyService(myService);
            myServlet.process(request, response);
        }
    }





    honzeland 2007-12-13 12:45 发表评论
    ]]>
    Eclipse 启动讄Q避免Out of Memoryhttp://www.aygfsteel.com/honzeland/archive/2007/12/13/167463.htmlhonzelandhonzelandThu, 13 Dec 2007 04:40:00 GMThttp://www.aygfsteel.com/honzeland/archive/2007/12/13/167463.htmlhttp://www.aygfsteel.com/honzeland/comments/167463.htmlhttp://www.aygfsteel.com/honzeland/archive/2007/12/13/167463.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/167463.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/167463.html -Xmx512M
    -XX:PermSize=64M
    -XX:MaxPermSize=128M



    honzeland 2007-12-13 12:40 发表评论
    ]]>
    国外著名java技术资料网?/title><link>http://www.aygfsteel.com/honzeland/archive/2007/05/18/118366.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 18 May 2007 06:59:00 GMT</pubDate><guid>http://www.aygfsteel.com/honzeland/archive/2007/05/18/118366.html</guid><wfw:comment>http://www.aygfsteel.com/honzeland/comments/118366.html</wfw:comment><comments>http://www.aygfsteel.com/honzeland/archive/2007/05/18/118366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/honzeland/comments/commentRss/118366.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/honzeland/services/trackbacks/118366.html</trackback:ping><description><![CDATA[<p style="color: red;"><a target="_blank">http://www.onjava.com</a></p> <p>    <span style="color: red;">O'Reilly的Java|站. 每周都有新文?/span></p> <p><a target="_blank">http://java.sun.com</a></p> <p>    官方的Java开发者网?- 每周都有新文章发?/p> <p><a target="_blank">http://www.developer.com/java</a></p> <p>    <span style="color: red;">由Gamelan.com l护的Java技术文章网?/span></p> <p><a target="_blank">http://www.java.net</a></p> <p>    Sun公司l护的一个JavaC֌|站</p> <p><a target="_blank">http://www.ibm.com/developerworks/java</a> </p> <p>    IBM的Developerworks技术网? q是其中的Java技术主?/p> <p><a target="_blank">http://www.javaworld.com</a></p> <p>    <span style="color: red;">最早的一个Java站点. 每周更新Java技术文?/span></p> <a target="_blank">http://www.javadesktop.org</a> <p>    位于Java.net的一个Java桌面技术社区网? </p> <p><a target="_blank">http://www.theserverside.com</a> </p> <p>    q是一个讨论所有Java服务器端技术的|站. </p> <p><a target="_blank">http://www.jars.com</a> </p> <p>    提供Java评论服务. 包括各种framework和应用程?/p> <p><a target="_blank">http://www.ibiblio.org/javafaq/javafaq.html</a> </p> <p>    comp.lang.java的FAQ站点 - 攉了来自comp.lang.java新闻l的问题和答案的分类目录. </p> <p><a target="_blank">http://java.sun.com/docs/books/tutorial/</a> </p> <p>    来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮助. </p> <p><a target="_blank">http://www.javablogs.com</a> </p>     互联|上最z跃的一个Java Blog|站. <p style="color: red;"><a target="_blank">http://www.java2s.com</a></p>   <span style="color: red;">  Java Codes</span><br> <img src ="http://www.aygfsteel.com/honzeland/aggbug/118366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/honzeland/" target="_blank">honzeland</a> 2007-05-18 14:59 <a href="http://www.aygfsteel.com/honzeland/archive/2007/05/18/118366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于ServerSocket.accept()http://www.aygfsteel.com/honzeland/archive/2006/11/30/84607.htmlhonzelandhonzelandThu, 30 Nov 2006 08:46:00 GMThttp://www.aygfsteel.com/honzeland/archive/2006/11/30/84607.htmlhttp://www.aygfsteel.com/honzeland/comments/84607.htmlhttp://www.aygfsteel.com/honzeland/archive/2006/11/30/84607.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/84607.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/84607.html 对于TCP套接字,在服务器端通常采用下面的语句来实现Q?/font>
        ServerSocket welcomeSocket = new ServerSocket(6789);  (1)
        Socket connectionSocket = welcomeSocket.accept();     (2)
    W(1Q句创徏了一个能监听某些客户?span lang="EN-US">?/span>敲门?/span>声的门,welcomeSocket?span lang="EN-US">6789端口上监听;当某些客h?span lang="EN-US">welcomeSocket
    q接ӞW(2Q句创徏了一个新的套接字Q称?span lang="EN-US">connectionSocketQ这个套接字也?span lang="EN-US">6789端口Q这Ӟ两个套接字用了相同的端口号Q因?span lang="EN-US">TCPq接套接?/span>׃个四元组Q源IP地址Q源端口P目的IP地址Q目的端口号Q来标识Q?span lang="EN-US">UDP套接字(面向无连接的Q由一个包含目?span lang="EN-US">IP地址和目的端口号l成的二元组来标识。之后,TCP在客L?span lang="EN-US">clientSocket和服务器端的connectionSocket之间建立了一条直接的虚礼道Q该客户Z服务器可以通过该管道彼此发送字节,q且发送的所有字节将按顺序到辑֯斏V随着connectionSocket的徏立,该服务器能l?span lang="EN-US">welcomeSocket监听其它客户机的q接h?span lang="EN-US">

     



    honzeland 2006-11-30 16:46 发表评论
    ]]>
    Override and Overloadhttp://www.aygfsteel.com/honzeland/archive/2006/11/10/80325.htmlhonzelandhonzelandFri, 10 Nov 2006 02:37:00 GMThttp://www.aygfsteel.com/honzeland/archive/2006/11/10/80325.htmlhttp://www.aygfsteel.com/honzeland/comments/80325.htmlhttp://www.aygfsteel.com/honzeland/archive/2006/11/10/80325.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/80325.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/80325.html Override: Q覆盖)
    1 ?/span> Override 发生在承中Q得一个子c?/span> Override 其父cȝ一?/span> method ?/span>
    2
    ?/span> Override Rules Q?/span> Keeping the contract 。子c?/span> override 父类?/span> method Ӟ必须要保?/span> overriding method 和父cM?/span> overridden method h相同的对外协?/span> contract Q即相同的参数列表和兼容的返回类?/span>?/span>
    3
    ?/span> Arguments must be the same, and return types must be compatible.
    4
    ?/span> The method can't be less accessible. 考虑如下情况Q如果访问权限变了Q如qc?/span> Parent 中的 public void test() 变成子类 Son 中的 private void test() Q如果编译器允许权限变小Q在某一cM有如下语句: Parent p = new Son() Q?/span> p.test() Q则q些语句能够通过~译Q当该类加蝲q行Ӟ会出现错误Q因为父c?/span> reference p 指向的是一子类 Son 的对象,?/span> Son 中的 test() ?/span> private Q不能在其他cM invoke ?/span>
          
    另外Q上面的语句在编译器允许权限变小情况下之所以能够通过~译Q是因ؓ?/span> “Parent p = new Son() Q?/span> ?/span> 中,声明了一个父c?/span> Parent ?/span> reference p Q由?/span> p 是父cȝ reference Q由于父cM?/span> test() ?/span> public Q故 “p.test() Q?/span> ?/span> 能够通过~译Q而在q行Ӟ p 指向的是一个子cȝ对象Q?/span> p.test() 在运行时调用的是子类对象中的 test() ?/span>

    Overload
    Q(重蝲Q?/span>
    1 、重载:两个或多?/span> methods h相同?/span> name Q?/span> ?/span> 不同?/span> argument lists ?/span>
    2
    ?/span> The return types can be different.
    3
    ?/span> You can't change ONLY the return type Q不能仅仅改变返回类型, To overload a method, you MUST change the argument list, although you can change the return type to anything.
    4
    ?/span> You can vary the access levels in any direction.



    honzeland 2006-11-10 10:37 发表评论
    ]]>
    全面解析Java中的String数据cdhttp://www.aygfsteel.com/honzeland/archive/2006/11/05/79190.htmlhonzelandhonzelandSun, 05 Nov 2006 06:32:00 GMThttp://www.aygfsteel.com/honzeland/archive/2006/11/05/79190.htmlhttp://www.aygfsteel.com/honzeland/comments/79190.htmlhttp://www.aygfsteel.com/honzeland/archive/2006/11/05/79190.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/79190.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/79190.html 1. 首先 String 不属?/span> 8 U基本数据类型, String 是一个对象?/span>
      因ؓ对象的默认值是 null Q所?/span> String 的默认g?/span> null Q但它又是一U特D的对象Q有其它对象没有的一些特性?/span>
    2. new String()
    ?/span> new String(“? 都是x一个新的空字符Ԍ是空串不?/span> null Q?/span>
    3. String str=”kvill?/span>
    Q?/span> String str=new String (“kvill?; 的区别:在这里,我们不谈堆,也不谈栈Q只先简单引入常量池q个单的概念?/span>
      帔R?/span> (constant pool) 指的是在~译期被定Qƈ被保存在已编译的 .class 文g中的一些数据。它包括了关于类、方法、接口等中的帔RQ也包括字符串常量?/span>
      看例 1 Q?/span>
    String s0=”kvill?
    String s1=”kvill?
    String s2=”kv?+ “ill?
    System.out.println( s0==s1 );
    System.out.println( s0==s2 );

      l果为:
    true
    true
      首先Q我们要知结果ؓ?/span> Java 会确保一个字W串帔R只有一个拷?/span> ?/span>
      因ؓ例子中的 s0 ?/span> s1 中的 ”kvill?/span> 都是字符串常量,它们在编译期p定?/span>Q所?/span> s0==s1 ?/span> true Q?/span> ”kv?/span> ?/span> ”ill?/span> 也都是字W串帔RQ当一个字W串由多个字W串帔Rq接而成Ӟ它自p定也是字W串帔RQ所?/span> s2 也同样在~译期就被解析ؓ一个字W串帔RQ所?/span> s2 也是帔R池中 ”kvill?/span> 的一个引用?/span>
      所以我们得?/span> s0==s1==s2; ?/span> new String() 创徏的字W串不是帔RQ不能在~译期就定Q所?/span> new String() 创徏的字W串不放入常量池中,它们有自q地址I间?/span>
      看例 2 Q?/span>
    String s0=”kvill?
    String s1=new String(”kvill?;
    String s2=”kv?+ new String(“ill?;
    System.out.println( s0==s1 );
    System.out.println( s0==s2 );
    System.out.println( s1==s2 );
      l果为:
    false
    false
    false

      ?/span> 2 ?/span> s0 q是帔R池中 ”kvill?/span> 的应用, s1 因ؓ无法在编译期定Q所以是q行时创建的新对?/span> ”kvill?/span> 的引用, s2 因ؓ有后半部?/span> new String(“ill? 所以也无法在编译期定Q所以也是一个新创徏对象 ”kvill?/span> 的应?/span> ; 明白了这些也q道ؓ何得出此l果了?/span>
    4. String.intern()
    Q?/span>
      再补充介l一点:存在?/span> .class 文g中的帔R池,在运行期?/span> JVM 装蝲Qƈ且可以扩充?/span> String ?/span> intern() Ҏ是扩充帔R池的一个方法;当一?/span> String 实例 str 调用 intern() ҎӞ Java 查找帔R池中是否有相?/span> Unicode 的字W串帔RQ如果有Q则q回其的引用Q如果没有,则在帔R池中增加一?/span> Unicode {于 str 的字W串q返回它的引用;看例 3 清楚了
      ?/span> 3 Q?/span>
    String s0= “kvill?
    String s1=new String(”kvill?;
    String s2=new String(“kvill?;
    System.out.println( s0==s1 );
    System.out.println( ?*********?);
    s1.intern();
    s2=s2.intern(); //
    把常量池?/span> “kvill?/span> 的引用赋l?/span> s2
    System.out.println( s0==s1);
    System.out.println( s0==s1.intern() );
    System.out.println( s0==s2 );
      l果为:
    false
    **********
    false //
    虽然执行?/span> s1.intern(), 但它的返回值没有赋l?/span> s1
    true //
    说明 s1.intern() q回的是帔R池中 ”kvill?/span> 的引?/span>
    true
      最后我再破除一个错误的理解Q有Q?/span> ?/span> 使用 String.intern() Ҏ则可以将一?/span> String cȝ保存C个全局 String 表中Q如果具有相同值的 Unicode 字符串已l在q个表中Q那么该Ҏq回表中已有字符串的地址Q如果在表中没有相同值的字符Ԍ则将自己的地址注册到表?/span> ?/span> 如果我把他说的这个全局?/span> String 表理解ؓ帔R池的话,他的最后一句话Q?/span> ?/span> 如果在表中没有相同值的字符Ԍ则将自己的地址注册到表?/span> ?/span> 是错的:
      看例 4 Q?/span>
    String s1=new String("kvill");
    String s2=s1.intern();
    System.out.println( s1==s1.intern() );
    System.out.println( s1+" "+s2 );
    System.out.println( s2==s1.intern() );
      l果Q?/span>

    false
    kvill kvill
    true
      在这个类中我们没有声名一?/span> ”kvill?/span> 帔RQ所以常量池中一开始是没有 ”kvill?/span> 的,当我们调?/span> s1.intern() 后就在常量池中新d了一?/span> ”kvill?/span> 帔RQ原来的不在帔R池中?/span> ”kvill?/span> 仍然存在Q也׃?/span> ?/span> 自q地址注册到常量池?/span> ?/span> 了?/span>
       s1==s1.intern() ?/span> false 说明原来?/span> “kvill?/span> 仍然存在Q?/span> s2 现在为常量池?/span> “kvill?/span> 的地址Q所以有 s2==s1.intern() ?/span> true ?/span>
    5.
    关于 equals() ?/span> ==
      q个对于 String 单来说就是比较两字符串的 Unicode 序列是否相当Q如果相{返?/span> true; ?/span> == 是比较两字符串的地址是否相同Q也是是否是同一个字W串的引用?/span>
    6.
    关于 String 是不可变?/span>
      q一说又要说很多Q大家只要知?/span> String 的实例一旦生成就不会再改变了Q比如说Q?/span> String str=”kv?”ill???”ans?
      是?/span> 4 个字W串帔RQ首?/span> ”kv?/span> ?/span> ”ill?/span> 生成?/span> ”kvill?/span> 存在内存中,然后 ”kvill?/span> 又和 ?? 生成 ”kvill ?/span> 存在内存中,最后又和生成了 ”kvill ans? q把q个字符串的地址赋给?/span> str, 是因ؓ String ?/span> ?/span> 不可?/span> ?/span> 产生了很多时变量,q也是Z么徏议用 StringBuffer 的原因了Q因?/span> StringBuffer 是可改变的?/span>



    honzeland 2006-11-05 14:32 发表评论
    ]]>
    Abstract class and interfacehttp://www.aygfsteel.com/honzeland/archive/2006/10/26/77439.htmlhonzelandhonzelandThu, 26 Oct 2006 09:27:00 GMThttp://www.aygfsteel.com/honzeland/archive/2006/10/26/77439.htmlhttp://www.aygfsteel.com/honzeland/comments/77439.htmlhttp://www.aygfsteel.com/honzeland/archive/2006/10/26/77439.html#Feedback0http://www.aygfsteel.com/honzeland/comments/commentRss/77439.htmlhttp://www.aygfsteel.com/honzeland/services/trackbacks/77439.html 1 、抽象类和接口都不能被实例化Q?/span>

    2 、抽象类Q抽象类中可以不包含抽象ҎQ即cM的方法都是非抽象的,但是在类的声明中加上 abstract Q以使得该类是抽象的Q目的是防止客户端程序员创徏该类的对象;

    3 、接口中的方法L abstract and public Q不是否被昄的声明;

    4 、接口中?/span> field 只能?/span> public static final Q?/span>

    5 、接口本w可以是 public or protected Q?/span>

    6 ?/span> extended class 必须实现抽象cM的所有抽象方法, implemented class 必须实现接口中的所有方法,因ؓ接口中的所有方法都?/span> abstract ?/span>



    honzeland 2006-10-26 17:27 发表评论
    ]]>
    J2EE学习W记Q?/title><link>http://www.aygfsteel.com/honzeland/archive/2006/10/13/75013.html</link><dc:creator>honzeland</dc:creator><author>honzeland</author><pubDate>Fri, 13 Oct 2006 07:53:00 GMT</pubDate><guid>http://www.aygfsteel.com/honzeland/archive/2006/10/13/75013.html</guid><wfw:comment>http://www.aygfsteel.com/honzeland/comments/75013.html</wfw:comment><comments>http://www.aygfsteel.com/honzeland/archive/2006/10/13/75013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/honzeland/comments/commentRss/75013.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/honzeland/services/trackbacks/75013.html</trackback:ping><description><![CDATA[ <p> <font color="#ff0000" size="5"> <strong>Part One: The Web Tier</strong> </font> </p> <p> <font size="5"> <strong> <font size="4">Section One: Configuring Web Applications</font> </strong> </font> </p> <p> <font size="4"> <strong> <font size="3">Mapping URLs to Web Components</font> </strong> </font> </p> <p class="pBody">When a request is received by the web container it must determine which web component should handle the request. It does so by mapping the URL path contained in the request to a web application and a web component. A URL path contains the context root and an alias: </p> <p class="pPreformattedRelative">http://<code class="cVariable">host</code>:<code class="cVariable">port</code>/<code class="cVariable">context_root</code>/<code class="cVariable">alias</code><a name="wp219218"></a></p> <p>A context root identifies a web application in a Java EE server. You specify the context root when you deploy a web module. A context root must start with a forward slash (/) and end with a string.<br /> <br />The alias identifies the web component that should handle a request. The alias path must start with a forward slash (/) and end with a string or a wildcard expression with an extension (for example, *.jsp). Since web containers automatically map an alias that ends with *.jsp, you do not have to specify an alias for a JSP page unless you wish to refer to the page by a name other than its file name. </p> <p class="pHeading2"> <font size="4"> <strong> <font size="3">Declaring Welcome Files</font> </strong> </font> </p> <a name="wp85893"> </a> <p class="pBody">For example, suppose you define a welcome file welcome.html. When a client requests a URL such as host:port/webapp/directory, where directory is not mapped to a servlet or JSP page, the file host:port/webapp/directory/welcome.html is returned to the client.<br /></p> <p class="pBody">If no welcome file is specified, the Application Server will use a file named <code class="cCode">index.</code><code class="cVariable">XXX</code>, where <code class="cVariable">XXX</code> can be <code class="cCode">html</code> or <code class="cCode">jsp</code>, as the default welcome file. If there is no welcome file and no file named <code class="cCode">index.</code><code class="cVariable">XXX</code>, the Application Server returns a directory listing. </p> <a name="wp222536"> </a> <p class="pBody">To specify a welcome file in the web application deployment descriptor, you need to nest a <code class="cCode">welcome-file</code> element inside a <code class="cCode">welcome-file-list</code> element. The <code class="cCode">welcome-file</code> element defines the JSP page to be used as the welcome page. Make sure this JSP page is actually included in your WAR file. <br /><br /></p> <p class="pHeading2"> <font size="4"> <strong> <font size="3">Setting Initialization Parameters</font> </strong> </font> </p> <a name="wp222559"> </a> <p class="pBody">The web components in a web module share an object that represents their application context. You can pass initialization parameters to the context or to a web component. </p> <a name="wp226898"> </a> <p class="pBody">To add a context parameter you need the following in the example's web.xml file: </p> <div id="wmqeeuq" class="pSmartList1"> <ul class="pSmartList1"> <a name="wp226899"> </a> <div id="wmqeeuq" class="pSmartList1"> <li>A <code class="cCode">param-name</code> element that specifies the context object </li> </div> <a name="wp229279"> </a> <div id="wmqeeuq" class="pSmartList1"> <li>A <code class="cCode">param-value</code> element that specifies the parameter to pass to the context object. </li> </div> <a name="wp229280"> </a> <div id="wmqeeuq" class="pSmartList1"> <li>A <code class="cCode">context-param</code> element that encloses the previous two elements. </li> </div> </ul> </div> <a name="wp229284"> </a> <p class="pBody">To add a web component initialization parameter you need the following in the example's web.xml file: </p> <div id="wmqeeuq" class="pSmartList1"> <ul class="pSmartList1"> <a name="wp229291"> </a> <div id="wmqeeuq" class="pSmartList1"> <li>A <code class="cCode">param-name</code> element that specifies the name of the initialization parameter </li> </div> <a name="wp229292"> </a> <div id="wmqeeuq" class="pSmartList1"> <li>A <code class="cCode">param-value</code> element that specifies the value of the initialization parameter </li> </div> <a name="wp229293"> </a> <div id="wmqeeuq" class="pSmartList1"> <li>An <code class="cCode">init-param</code> element that encloses the previous two elements </li> </div> </ul> </div> <a name="wp83548"> </a> <p class="pHeading2"> <strong>Mapping Errors to Error Screens </strong> </p> <p class="pHeading2"> <strong>Declaring Resource References </strong> </p> <p class="pBody"> <br /> </p> <img src ="http://www.aygfsteel.com/honzeland/aggbug/75013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/honzeland/" target="_blank">honzeland</a> 2006-10-13 15:53 <a href="http://www.aygfsteel.com/honzeland/archive/2006/10/13/75013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank">ָɽ</a>| <a href="http://" target="_blank">ʹ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank">²</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ϻ</a>| <a href="http://" target="_blank">ˮ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ͼ</a>| <a href="http://" target="_blank">̩</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">߱</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ļ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">׶</a>| <a href="http://" target="_blank">Ժ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ؿ˹</a>| <a href="http://" target="_blank">ϽϽ</a>| <a href="http://" target="_blank">Զ</a>| <a href="http://" target="_blank">̫</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">Ԫ</a>| <a href="http://" target="_blank">Һ</a>| <a href="http://" target="_blank">Ҫ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ϫ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ϲ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>