﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-super</title><link>http://www.blogjava.net/super/</link><description /><language>zh-cn</language><lastBuildDate>Thu, 07 May 2026 17:36:16 GMT</lastBuildDate><pubDate>Thu, 07 May 2026 17:36:16 GMT</pubDate><ttl>60</ttl><item><title>使用 apache common dbcp +common pool+mysql连接无效的问题</title><link>http://www.blogjava.net/super/archive/2010/09/15/332102.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Wed, 15 Sep 2010 09:57:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2010/09/15/332102.html</guid><wfw:comment>http://www.blogjava.net/super/comments/332102.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2010/09/15/332102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/332102.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/332102.html</trackback:ping><description><![CDATA[<br />
<br />
<br />
Throwable occurred: org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 50,123,505 milliseconds ago.&nbsp; The last packet sent successfully to the server was 50,123,505 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.<br />
<br />
<br />
这主要是由两个原因引起来的:<br />
1.mysql 会自动关闭长时间不用的connection,一个连接如果处于sleep状态达到mysql的参数wait_timeout指定的时间(默认为8小时),就是自动关闭这个连接<br />
2.common pool中没有指定相应的连接检查参数<br />
<br />
<br />
解决办法:从common pool的配置参数来解决:<br />
<br />
<p>&nbsp;&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;<br />
&nbsp;&nbsp;&lt;property name="driverClassName"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.driver}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="url"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.url}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="username"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.user}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="password"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;${db.password}&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="maxActive"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;100&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="maxIdle"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;50&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="maxWait"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;10000&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</p>
<p><br />
<span style="color: red">&nbsp;&nbsp;&lt;property name="timeBetweenEvictionRunsMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;3600000&lt;/value&gt;&lt;!--1 hours--&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</span><br />
&lt;!--<br />
&nbsp;&nbsp;&lt;property name="minEvictableIdleTimeMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;20000&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
--&gt;<br />
&nbsp;&nbsp;<br />
<span style="color: red">&nbsp;&nbsp;&lt;property name="testWhileIdle"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="validationQuery"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;select 1 from dual&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</span><br />
&nbsp;&lt;/bean&gt;<br />
</p>
使用上述的三个红色的参数,就可以避免这个问题.这三个参数的意义:<br />
<br />
timeBetweenEvictionRunsMillis:启动connection校验定时器,定时器运行时间间隔就是timeBetweenEvictionRunsMillis的值.默认为-1,表示不启动定时器,这里设定为1小时,只要小于mysql的wait_timeout就可以了<br />
<br />
testWhileIdle: true,表示检查idle的connection,false为不检查<br />
<br />
validationQuery:用于检查connection的sql语句.<br />
<br />
<br />
这只是一种方法,另外的几种方法:<br />
<br />
timeBetweenEvictionRunsMillis+minEvictableIdleTimeMillis:这种方式不检查Connection的有效性,而是检查连接的空闲时间,大于minEvictableIdleTimeMillis就清除.<br />
<br />
&nbsp;&nbsp;&lt;property name="timeBetweenEvictionRunsMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;3600000&lt;/value&gt;&lt;!--1 hours--&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
<br />
&nbsp;&nbsp;&lt;property name="minEvictableIdleTimeMillis"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;120000&lt;/value&gt;&lt;!--connection的空闲时间大于这个值,就直接被关闭,并从连接池中删除--&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
<br />
<br />
如果不喜欢用定时器,也可以配置testOnBorrow+validationQuery参数:每次从连接池取参数都会校验连接的有效性.实际上这种方式性能会比定时器差些.<br />
&nbsp;&nbsp;&lt;property name="testOnBorrow"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="validationQuery"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;select 1 from dual&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
<br />
<br />
另外,也可以用testOnReturn+validationQuery,不过未必会解决问题:这表示每次使用完连接,归还连接池的时候检查连接的有效性,这有可能导致使用一次无效的连接,最好不要用.<br />
<br />
<br />
上面的几种方法可以合并使用,只是检查的点多了,未必是好事<br />
<br />
<br />
另外,也可以使用Abandoned的那几个参数,来删除连接池中的连接.也能达到效果.我没测试.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/super/aggbug/332102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2010-09-15 17:57 <a href="http://www.blogjava.net/super/archive/2010/09/15/332102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android中点中overlay弹出带尾巴的气泡的实现</title><link>http://www.blogjava.net/super/archive/2010/08/12/android_mapview_overlay.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Thu, 12 Aug 2010 07:03:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2010/08/12/android_mapview_overlay.html</guid><wfw:comment>http://www.blogjava.net/super/comments/328671.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2010/08/12/android_mapview_overlay.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/328671.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/328671.html</trackback:ping><description><![CDATA[<p><img alt="" src="http://www.blogjava.net/images/blogjava_net/super/mappop.png" border="0" /></p>
<br />
<br />
<br />
就是上面的样子<br />
<br />
做这个过程中我碰到两个问题:<br />
1:如何做带尾巴的气泡View<br />
2:如何把这个View添加到MapView中.<br />
<br />
<br />
1:如何做带尾巴的气泡View<br />
我是采用背景图的方式来实现的.当然,普通的PNG在View&nbsp;缩放的时候会失真,尤其是那个尖尖的尾巴.<br />
后来采用9.png的格式,才完成了不变形的效果.9.png格式的Png可以用SDK\Tools\draw9patch.bat来处理,只要把普通的png的边上标志一下就可以了,具体draw9patch.bat如何使用这里就不说了,网上有很多文档,自己查查就知道了.<br />
我生成的9.png就是下面这个样子,注意四周的黑线.就是9png拉伸时的标识<br />
<img height="51" alt="" src="http://www.blogjava.net/images/blogjava_net/super/bubble_background.9.png" width="65" border="0" /><br />
<br />
有了这个png,直接放到你的工程下的res/drawable目录就可以了,<br />
然后在res/layout目录下建立你的view的xml文件,比如叫overlay_pop.xml,我的是这样的:<br />
<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"<br />
&nbsp;android:orientation="vertical" <br />
&nbsp;android:background="@drawable/bubble_background"<span style="color: red">&nbsp;&lt;!--这就是那个9.png--&gt;<br />
</span>&nbsp;android:layout_width="wrap_content" <br />
&nbsp;android:layout_height="wrap_content"<br />
&nbsp;android:paddingLeft="5px"<br />
&nbsp;android:paddingTop="5px"<br />
&nbsp;android:paddingRight="5px"<br />
&nbsp;android:paddingBottom="20px"&nbsp;&nbsp;&nbsp; <span style="color: red">&lt;!--注意加上padding,否则view里面的东西就画到边框上了--&gt;<br />
</span>&nbsp;&nbsp; &gt;<br />
&nbsp;&nbsp;&nbsp; &lt;TextView android:id="@+id/map_bubbleTitle" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:ellipsize="marquee" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:layout_width="match_parent" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:layout_height="wrap_content"<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:gravity="center_horizontal"<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:singleLine="true" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;style="@style/map_BubblePrimary" /&gt; <span style="color: red">&lt;!--style可以没有,我这里第一个TextView表示标题,用的是大字体--&gt;<br />
</span>&nbsp;&nbsp;&nbsp; &lt;TextView&nbsp; android:id="@+id/map_bubbleText" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:layout_width="match_parent" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:layout_height="wrap_content" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;android:singleLine="false" <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;style="@style/map_BubbleSecondary" /&gt;<span style="color: red">&lt;!--style可以没有,我这里第二个TextView表示描述信息,用的是大字体--&gt;<br />
</span>&lt;/LinearLayout&gt;<br />
<br />
<br />
这样popView就建立好了<br />
<br />
<br />
2:如何把这个View添加到MapView中.<br />
通常是在mapView中点击某个位置,弹出popView<br />
或者点击某个Overlay弹出popView,这里用点击Overlay来说明,<br />
<br />
overlay有onTap()方法,你可以实现自己的overlay,overideonTap()方法,弹出popView,<br />
也可以使用setOnFocusChangeListener(),在listener中实现弹出popView,.<br />
我是用的listener,因为setOnFocusChangeListener在失去焦点也会触发,我可以再失去焦点的时候隐藏popView.<br />
<br />
MapView是<span style="color: red">继承自ViewGroup</span>的,因此,MapView有addView()方法,同时还有<span style="color: red">MapView.LayoutParams<br />
</span><span style="color: red"><span style="color: #000000">MapView.LayoutParams 可以根据GeoPoint来定位,我就是利用这个特性来定位弹出的popView的.<br />
</span><br />
<span style="color: #000000">PointItemizedOverlay overlay = new PointItemizedOverlay(drawable); &lt;!--这是我继承自ItemizedOverlay的overlay,主要就是画一个图片,写一个名称,很简单,这里不贴具体代码了--&gt;</span><br />
</span><br />
public class BaseMapActivity extends MapActivity {<br />
<br />
&nbsp;/**<br />
&nbsp; * 地图View<br />
&nbsp; */<br />
&nbsp;protected MapView mapView;<br />
<p>&nbsp;/**<br />
&nbsp; * 弹出的气泡View<br />
&nbsp; */<br />
&nbsp;private View popView;<br />
/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;监听器<br />
*/<br />
&nbsp;private final ItemizedOverlay.OnFocusChangeListener onFocusChangeListener = new ItemizedOverlay.OnFocusChangeListener() {</p>
<p>&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;public void onFocusChanged(ItemizedOverlay overlay, OverlayItem newFocus) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建气泡窗口<br />
&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;if (popView != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popView.setVisibility(View.GONE);<br />
&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;if (newFocus != null) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;MapView.LayoutParams geoLP = (MapView.LayoutParams) popView.getLayoutParams();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000">geoLP.point = newFocus.getPoint();//这行用于popView的定位<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;TextView title = (TextView) popView.findViewById(R.id.map_bubbleTitle);<br />
&nbsp;&nbsp;&nbsp;&nbsp;title.setText(newFocus.getTitle());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;TextView desc = (TextView) popView.findViewById(R.id.map_bubbleText);<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (newFocus.getSnippet() == null || newFocus.getSnippet().length() == 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;desc.setVisibility(View.GONE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;desc.setVisibility(View.VISIBLE);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;desc.setText(newFocus.getSnippet());<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;mapView.updateViewLayout(popView, geoLP);<br />
&nbsp;&nbsp;&nbsp;&nbsp;popView.setVisibility(View.VISIBLE);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;};<br />
</p>
<br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void onCreate(Bundle savedInstanceState) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.onCreate(savedInstanceState);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;省略其他代码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; **/<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//初始化气泡,并设置为不可见<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;popView = inflater.inflate(R.layout.overlay_popup, null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mapView.addView(&nbsp;popView,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000">new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;null, MapView.LayoutParams.BOTTOM_CENTER));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //由于我的气泡的尾巴是在下边居中的,因此要设置成MapView.LayoutParams.BOTTOM_CENTER.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这里没有给GeoPoint,在onFocusChangeListener中设置<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;views.add(popView);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; popView.setVisibility(View.GONE);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;添加overlay<br />
&nbsp;&nbsp;&nbsp; PointItemizedOverlay overlay = new PointItemizedOverlay(drawable);<br />
&nbsp;&nbsp;&nbsp;&nbsp;//设置显示/隐藏泡泡的监听器<br />
&nbsp;&nbsp;&nbsp;&nbsp;overlay.setOnFocusChangeListener(onFocusChangeListener);<br />
&nbsp;&nbsp;&nbsp; overlay.addOverlay(/*你自己的overlayItem*/);<br />
&nbsp;&nbsp;&nbsp; overlay.addOverlay(/*你自己的overlayItem*/);<br />
&nbsp;&nbsp;&nbsp; overlay.addOverlay(/*你自己的overlayItem*/);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
<br />
这样就基本完工了.<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/super/aggbug/328671.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2010-08-12 15:03 <a href="http://www.blogjava.net/super/archive/2010/08/12/android_mapview_overlay.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android mapView中画轨迹的overlay</title><link>http://www.blogjava.net/super/archive/2010/08/12/android-map.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Thu, 12 Aug 2010 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2010/08/12/android-map.html</guid><wfw:comment>http://www.blogjava.net/super/comments/328661.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2010/08/12/android-map.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/328661.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/328661.html</trackback:ping><description><![CDATA[<p><br />
使用方法:<br />
LineItemizedOverlay overlay = new LineItemizedOverlay();<br />
<br />
overlay.addOverlay(/*起点的OverlayItem*/);<br />
overlay.addOverlay(/*终点的OverlayItem*/);<br />
overlay.addLinePoint(/*要画的轨迹的GeoPoint的List*/);<br />
<br />
mapView.getOverlays().add(overlay);<br />
<br />
/**<br />
&nbsp;* <br />
&nbsp;*/<br />
package com.xtyon.tuola.truck.map;</p>
<p>import java.util.ArrayList;</p>
<p>import android.graphics.Canvas;<br />
import android.graphics.Color;<br />
import android.graphics.Paint;<br />
import android.graphics.Point;<br />
import android.graphics.drawable.Drawable;</p>
<p>import com.google.android.maps.GeoPoint;<br />
import com.google.android.maps.ItemizedOverlay;<br />
import com.google.android.maps.MapView;<br />
import com.google.android.maps.OverlayItem;<br />
import com.google.android.maps.Projection;</p>
<p>/**<br />
&nbsp;* 地图上的线型图层:包括一个起点,一个终点,以及之间的曲线<br />
&nbsp;* @author superwang<br />
&nbsp;*/<br />
public class LineItemizedOverlay extends ItemizedOverlay&lt;OverlayItem&gt; {<br />
&nbsp;private static final int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG<br />
&nbsp;&nbsp;&nbsp;| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG;<br />
&nbsp;/**<br />
&nbsp; * 用于保存起点/终点数据<br />
&nbsp; */<br />
&nbsp;private final ArrayList&lt;OverlayItem&gt; mOverlays = new ArrayList&lt;OverlayItem&gt;();</p>
<p>&nbsp;/**<br />
&nbsp; * 用于保存构成曲线的点的数据<br />
&nbsp; */<br />
&nbsp;private final ArrayList&lt;GeoPoint&gt; linePoints = new ArrayList&lt;GeoPoint&gt;();</p>
<p>&nbsp;/**<br />
&nbsp; * @param defaultMarker<br />
&nbsp; */<br />
&nbsp;public LineItemizedOverlay() {<br />
&nbsp;&nbsp;super(null);</p>
<p>&nbsp;&nbsp;// TODO Auto-generated constructor stub<br />
&nbsp;}</p>
<p>&nbsp;/* (non-Javadoc)<br />
&nbsp; * @see com.google.android.maps.ItemizedOverlay#createItem(int)<br />
&nbsp; */<br />
&nbsp;@Override<br />
&nbsp;protected OverlayItem createItem(int i) {<br />
&nbsp;&nbsp;return mOverlays.get(i);</p>
<p>&nbsp;}</p>
<p>&nbsp;/* (non-Javadoc)<br />
&nbsp; * @see com.google.android.maps.ItemizedOverlay#size()<br />
&nbsp; */<br />
&nbsp;@Override<br />
&nbsp;public int size() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;return mOverlays.size();<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 调价起点/终点<br />
&nbsp; * description: <br />
&nbsp; * @param overlay<br />
&nbsp; */<br />
&nbsp;public void addOverlay(OverlayItem overlay) {<br />
&nbsp;&nbsp;mOverlays.add(overlay);<br />
&nbsp;&nbsp;populate();<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 添加曲线中的点<br />
&nbsp; * description: <br />
&nbsp; * @param point<br />
&nbsp; */<br />
&nbsp;public void addLinePoint(GeoPoint point) {<br />
&nbsp;&nbsp;linePoints.add(point);<br />
&nbsp;}</p>
<p>&nbsp;public ArrayList&lt;GeoPoint&gt; getLinePoints() {<br />
&nbsp;&nbsp;return linePoints;<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * 画起点/终点/轨迹<br />
&nbsp; */<br />
&nbsp;@Override<br />
&nbsp;public void draw(Canvas canvas, MapView mapView, boolean shadow) {<br />
&nbsp;&nbsp;if (!shadow) {<br />
&nbsp;&nbsp;&nbsp;//System.out.println("!!!!!!!!!!!!!!");</p>
<p>&nbsp;&nbsp;&nbsp;canvas.save(LAYER_FLAGS);<br />
&nbsp;&nbsp;&nbsp;//canvas.save();</p>
<p>&nbsp;&nbsp;&nbsp;Projection projection = mapView.getProjection();<br />
&nbsp;&nbsp;&nbsp;int size = mOverlays.size();<br />
&nbsp;&nbsp;&nbsp;Point point = new Point();<br />
&nbsp;&nbsp;&nbsp;Paint paint = new Paint();<br />
&nbsp;&nbsp;&nbsp;paint.setAntiAlias(true);<br />
&nbsp;&nbsp;&nbsp;OverlayItem overLayItem;</p>
<p>&nbsp;&nbsp;&nbsp;//画起点/终点<br />
&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; size; i++) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;overLayItem = mOverlays.get(i);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;Drawable marker = overLayItem.getMarker(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;//marker.getBounds()<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* 象素点取得转换 */<br />
&nbsp;&nbsp;&nbsp;&nbsp;projection.toPixels(overLayItem.getPoint(), point);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;if (marker != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boundCenterBottom(marker);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;/* 圆圈 */<br />
&nbsp;&nbsp;&nbsp;&nbsp;//Paint paintCircle = new Paint();<br />
&nbsp;&nbsp;&nbsp;&nbsp;//paintCircle.setColor(Color.RED);<br />
&nbsp;&nbsp;&nbsp;&nbsp;paint.setColor(Color.RED);<br />
&nbsp;&nbsp;&nbsp;&nbsp;canvas.drawCircle(point.x, point.y, 5, paint);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;/* 文字设置 */<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* 标题 */<br />
&nbsp;&nbsp;&nbsp;&nbsp;String title = overLayItem.getTitle();<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* 简介 */<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;String snippet = overLayItem.getSnippet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer txt = new StringBuffer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;if (title != null &amp;&amp; !"".equals(title))<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt.append(title);<br />
&nbsp;&nbsp;&nbsp;&nbsp;//<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;if (snippet != null &amp;&amp; !"".equals(snippet)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (txt.length() &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt.append(":");<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt.append(snippet);<br />
&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//Paint paintText = new Paint();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;if (title != null &amp;&amp; title.length() &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;paint.setColor(Color.BLACK);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;paint.setTextSize(15);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;canvas.drawText(title, point.x, point.y, paint);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;//画线</p>
<p>&nbsp;&nbsp;&nbsp;boolean prevInBound = false;//前一个点是否在可视区域<br />
&nbsp;&nbsp;&nbsp;Point prev = null;<br />
&nbsp;&nbsp;&nbsp;int mapWidth = mapView.getWidth();<br />
&nbsp;&nbsp;&nbsp;int mapHeight = mapView.getHeight();<br />
&nbsp;&nbsp;&nbsp;//Paint paintLine = new Paint();<br />
&nbsp;&nbsp;&nbsp;paint.setColor(Color.RED);<br />
&nbsp;&nbsp;&nbsp;//paint.setPathEffect(new CornerPathEffect(10));<br />
&nbsp;&nbsp;&nbsp;paint.setStrokeWidth(2);<br />
&nbsp;&nbsp;&nbsp;int count = linePoints.size();</p>
<p>&nbsp;&nbsp;&nbsp;//Path path = new Path();<br />
&nbsp;&nbsp;&nbsp;//path.setFillType(Path.FillType.INVERSE_WINDING);<br />
&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; count; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;GeoPoint geoPoint = linePoints.get(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;//projection.toPixels(geoPoint, point); //这一行似乎有问题<br />
&nbsp;&nbsp;&nbsp;&nbsp;point = projection.toPixels(geoPoint, null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (prev != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (point.x &gt;= 0 &amp;&amp; point.x &lt;= mapWidth &amp;&amp; point.y &gt;= 0 &amp;&amp; point.y &lt;= mapHeight) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((Math.abs(prev.x - point.x) &gt; 2 || Math.abs(prev.y - point.y) &gt; 2)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这里判断点是否重合，重合的不画线，可能会导致画线不在路上<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;canvas.drawLine(prev.x, prev.y, point.x, point.y, paint);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//path.lineTo(point.x, point.y);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev = point;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prevInBound = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//在可视区与之外<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (prevInBound) {//前一个点在可视区域内，也需要划线<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//path.lineTo(point.x, point.y);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;canvas.drawLine(prev.x, prev.y, point.x, point.y, paint);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev = point;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prevInBound = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//path.moveTo(point.x, point.y);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev = point;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;//canvas.drawPath(path, paint);<br />
&nbsp;&nbsp;&nbsp;canvas.restore();<br />
&nbsp;&nbsp;&nbsp;//DebugUtils.showMemory();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;super.draw(canvas, mapView, shadow);<br />
&nbsp;}</p>
<p>}<br />
</p>
 <img src ="http://www.blogjava.net/super/aggbug/328661.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2010-08-12 14:21 <a href="http://www.blogjava.net/super/archive/2010/08/12/android-map.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat reload时内存泄漏的处理</title><link>http://www.blogjava.net/super/archive/2010/06/30/324916.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Wed, 30 Jun 2010 10:10:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2010/06/30/324916.html</guid><wfw:comment>http://www.blogjava.net/super/comments/324916.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2010/06/30/324916.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/324916.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/324916.html</trackback:ping><description><![CDATA[<p>我做的应用是以Spring为系统的基础框架,mysql为后台数据库.在tomcat上发布后,总是不能进行热部署(reload),多次reload后,就会出OutOfMemory PermGen,</p>
<p>为此烦恼了很久,总于下定决心找找根源.<br />
经过3天的不懈努力,小有成果,记录下来</p>
<p>实际上下面的分析都已经没什么用了,如果你使用tomcat6.0.26及以后的版本,我所说的这些情况都已经被处理了,并且比我处理的还要多很多.可以下载tomcat6.0.26的源代码<br />
看看WebappClassLoader类的处理就成了.</p>
<p>&nbsp;</p>
<p>通过分析工具的分析(用了YourKit,以及JDK1.6/bin下的jps/jmap/jhat),发现有下面几个方面会造成memory leak.</p>
<p>1.SystemClassLoader与WebappClassLoader加载的类相互引用,tomcat reload只是卸载WebappClassloader中的class,SystemClassLoader是不会卸载的(否则其他应用也停止了).但是WebappClassloader加载的类被SystemClassLoader引用的化,WebappClassloader中的相关类就不会被JVM进行垃圾收集</p>
<p>目前发现2种容易产生这种leak的现象.<br />
a.在使用java.lang.ThreadLocal的时候很容易产生这种情况<br />
b.使用jdbc驱动,而且不是在tomcat中配置的公共连接池.则java.sql.DriverManager一定会产生这种现象</p>
<p><br />
ThreadLocal.set(Object),如果这个Object是WebappsClassLoader加载的,使用之后没有做ThreadLocal.set(null)或者ThreadLocal.remove(),就会产生memory leak.<br />
由于ThreadLocal实际上操作的是java.lang.Thread类中的ThreadLocalMap,Thread类是由SystemClassLoder加载的.而这个线程实例(main thread)在tomcat reload的时候不会销毁重建,必然就产生了SystemClassLoder中的类引用WebappsClassLoader的类.</p>
<p>DriverManager也是由SystemClassLoder载入的,当初始化某个JDBC驱动的时候,会向DriverManager中注册该驱动,通常是***.driver,例如com.mysql.jdbc.Driver<br />
这个Driver是通过class.forName()加载的,通常也是加载到WebappClassLoader.这就出现了两个classLoader中的类的交叉引用.导致memory leak.</p>
<p>&nbsp;</p>
<p>解决办法:<br />
写一个ServletContextListener,在contextDestroyed方法中统一删除当前Thread的ThreadLocalMap中的内容.<br />
public class ApplicationCleanListener implements ServletContextListener {</p>
<p>&nbsp;public void contextInitialized(ServletContextEvent event) {<br />
&nbsp;}</p>
<p>&nbsp;public void contextDestroyed(ServletContextEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //处理ThreadLocal<br />
&nbsp;&nbsp;ThreadLocalCleanUtil.clearThreadLocals();</p>
<p>&nbsp;&nbsp;/*<br />
&nbsp;&nbsp; * 如果数据故驱动是通过应用服务器(tomcat etc...)中配置的&lt;公用&gt;连接池,这里不需要 否则必须卸载Driver<br />
&nbsp;&nbsp; * <br />
&nbsp;&nbsp; * 原因: DriverManager是System classloader加载的, Driver是webappclassloader加载的,<br />
&nbsp;&nbsp; * driver保存在DriverManager中,在reload过程中,由于system<br />
&nbsp;&nbsp; * classloader不会销毁,driverManager就一直保持着对driver的引用,<br />
&nbsp;&nbsp; * driver无法卸载,与driver关联的其他类<br />
&nbsp;&nbsp; * ,例如DataSource,jdbcTemplate,dao,service....都无法卸载<br />
&nbsp;&nbsp; */<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;System.out.println("clean jdbc Driver......");<br />
&nbsp;&nbsp;&nbsp;for (Enumeration e = DriverManager.getDrivers(); e<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.hasMoreElements();) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Driver driver = (Driver) e.nextElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (driver.getClass().getClassLoader() == getClass()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getClassLoader()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DriverManager.deregisterDriver(driver);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;System.out<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.println("Exception cleaning up java.sql.DriverManager's driver: "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ e.getMessage());<br />
&nbsp;&nbsp;}</p>
<p><br />
&nbsp;}</p>
<p>}</p>
<p><br />
/**<br />
&nbsp;* 这个类根据<br />
*/<br />
public class ThreadLocalCleanUtil {</p>
<p>&nbsp;/**<br />
&nbsp; * 得到当前线程组中的所有线程 description:<br />
&nbsp; * <br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;private static Thread[] getThreads() {<br />
&nbsp;&nbsp;ThreadGroup tg = Thread.currentThread().getThreadGroup();</p>
<p>&nbsp;&nbsp;while (tg.getParent() != null) {<br />
&nbsp;&nbsp;&nbsp;tg = tg.getParent();<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;int threadCountGuess = tg.activeCount() + 50;<br />
&nbsp;&nbsp;Thread[] threads = new Thread[threadCountGuess];<br />
&nbsp;&nbsp;int threadCountActual = tg.enumerate(threads);</p>
<p>&nbsp;&nbsp;while (threadCountActual == threadCountGuess) {<br />
&nbsp;&nbsp;&nbsp;threadCountGuess *= 2;<br />
&nbsp;&nbsp;&nbsp;threads = new Thread[threadCountGuess];</p>
<p>&nbsp;&nbsp;&nbsp;threadCountActual = tg.enumerate(threads);<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;return threads;<br />
&nbsp;}</p>
<p>&nbsp;public static void clearThreadLocals() {<br />
&nbsp;&nbsp;ClassLoader classloader = Thread<br />
&nbsp;&nbsp;&nbsp;&nbsp;.currentThread()<br />
&nbsp;&nbsp;&nbsp;&nbsp;.getContextClassLoader();</p>
<p>&nbsp;&nbsp;Thread[] threads = getThreads();<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;Field threadLocalsField = Thread.class<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredField("threadLocals");</p>
<p>&nbsp;&nbsp;&nbsp;threadLocalsField.setAccessible(true);<br />
&nbsp;&nbsp;&nbsp;Field inheritableThreadLocalsField = Thread.class<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredField("inheritableThreadLocals");</p>
<p>&nbsp;&nbsp;&nbsp;inheritableThreadLocalsField.setAccessible(true);</p>
<p>&nbsp;&nbsp;&nbsp;Class tlmClass = Class<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.forName("java.lang.ThreadLocal$ThreadLocalMap");</p>
<p>&nbsp;&nbsp;&nbsp;Field tableField = tlmClass.getDeclaredField("table");<br />
&nbsp;&nbsp;&nbsp;tableField.setAccessible(true);</p>
<p>&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; threads.length; ++i) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;if (threads[i] == null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Object threadLocalMap = threadLocalsField.get(threads[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;clearThreadLocalMap(threadLocalMap, tableField, classloader);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;threadLocalMap = inheritableThreadLocalsField.get(threads[i]);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;clearThreadLocalMap(threadLocalMap, tableField, classloader);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;} catch (Exception e) {</p>
<p>&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>&nbsp;private static void clearThreadLocalMap(Object map,<br />
&nbsp;&nbsp;&nbsp;Field internalTableField, ClassLoader classloader)<br />
&nbsp;&nbsp;&nbsp;throws NoSuchMethodException, IllegalAccessException,<br />
&nbsp;&nbsp;&nbsp;NoSuchFieldException, InvocationTargetException {<br />
&nbsp;&nbsp;if (map != null) {<br />
&nbsp;&nbsp;&nbsp;Method mapRemove = map.getClass().getDeclaredMethod("remove",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Class[] { ThreadLocal.class });</p>
<p>&nbsp;&nbsp;&nbsp;mapRemove.setAccessible(true);<br />
&nbsp;&nbsp;&nbsp;Object[] table = (Object[]) internalTableField.get(map);<br />
&nbsp;&nbsp;&nbsp;int staleEntriesCount = 0;<br />
&nbsp;&nbsp;&nbsp;if (table != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;for (int j = 0; j &lt; table.length; ++j) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (table[j] != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boolean remove = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object key = ((Reference) table[j]).get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((key != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; (key.getClass().getClassLoader() == classloader)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("clean threadLocal key,class="<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ key.getClass().getCanonicalName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ ",value=" + key.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field valueField = table[j]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getClass()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredField("value");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;valueField.setAccessible(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object value = valueField.get(table[j]);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((value != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; (value.getClass().getClassLoader() == classloader)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("clean threadLocal value,class="<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ value.getClass().getCanonicalName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ ",value=" + value.toString());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (remove) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (key == null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++staleEntriesCount;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mapRemove.invoke(map, new Object[] { key });<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;if (staleEntriesCount &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Method mapRemoveStale = map<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getClass()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredMethod("expungeStaleEntries", new Class[0]);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;mapRemoveStale.setAccessible(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;mapRemoveStale.invoke(map, new Object[0]);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}</p>
<p>&nbsp;</p>
<p>2.对于使用mysql JDBC驱动的:mysql JDBC驱动会启动一个Timer Thread,这个线程在reload的时候也是无法自动销毁.<br />
&nbsp; 因此,需要强制结束这个timer<br />
&nbsp; <br />
&nbsp; 可以在 上面的ApplicationCleanListener中加入如下代码:</p>
<p>&nbsp; &nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;Class ConnectionImplClass = Thread<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.currentThread()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getContextClassLoader()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.loadClass("com.mysql.jdbc.ConnectionImpl");<br />
&nbsp;&nbsp;&nbsp;if (ConnectionImplClass != null<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; ConnectionImplClass.getClassLoader() == getClass()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getClassLoader()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("clean mysql timer......");<br />
&nbsp;&nbsp;&nbsp;&nbsp;Field f = ConnectionImplClass.getDeclaredField("cancelTimer");<br />
&nbsp;&nbsp;&nbsp;&nbsp;f.setAccessible(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;Timer timer = (Timer) f.get(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;timer.cancel();<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;} catch (java.lang.ClassNotFoundException e1) {<br />
&nbsp;&nbsp;&nbsp;// do nothing<br />
&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp;&nbsp;System.out<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.println("Exception cleaning up MySQL cancellation timer: "<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ e.getMessage());<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;</p>
<p><br />
3.common-logging+log4j似乎也会导致leak,看网上有人说在ApplicationCleanListene6中加入这行代码就可以:<br />
&nbsp;LogFactory.release(Thread.currentThread().getContextClassLoader());</p>
<p>&nbsp; 我没试成功,懒得再找原因,直接换成了slf4j+logback,没有问题.据说slf4j+logback的性能还要更好.</p>
<p>&nbsp;</p>
<p>&nbsp;<br />
后记:<br />
&nbsp;tomcat-6.0.26之前的版本(我用的是tomcat-6.0.18),加入上述ApplicationCleanListener后,多次reload,不会出现outOfMemory.<br />
&nbsp;但要注意,第一次启动后,reload一次,内存会增加,也就是看着还是由memory Leak,但是重复reload,内存始终保持在第一次reload的大小.似乎tomcat始终保留了双WebappClassLoader.因此,配置内存要小心些,至少要保证能够load两倍的你的所有jar包的大小(当然,是指Perm的内存大小).<br />
&nbsp;<br />
&nbsp;测试过程中最好加上 JVM参数 -verbosegc,这样,在做GC的时候可以直观的看到class被卸载.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/super/aggbug/324916.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2010-06-30 18:10 <a href="http://www.blogjava.net/super/archive/2010/06/30/324916.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat ssl的配置</title><link>http://www.blogjava.net/super/archive/2009/04/02/263551.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Thu, 02 Apr 2009 07:14:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2009/04/02/263551.html</guid><wfw:comment>http://www.blogjava.net/super/comments/263551.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2009/04/02/263551.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/263551.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/263551.html</trackback:ping><description><![CDATA[<div><br />
<br />
keytool -genkey -alias tomcat -keyalg RSA -keysize 1024 -keypass changeit -storepass changeit -keystore tomcat.keystore -validity 3600</div>
<div>&nbsp;</div>
<div>--这两步可以不用</div>
<div>keytool -export -trustcacerts -alias tomcat -file tomcat.cer -keystore&nbsp; tomcat.keystore -storepass changeit<br />
keytool -import -trustcacerts -alias tomcat -file tomcat.cer -keystore&nbsp; %JAVA_HOME%/jre/lib/security/cacerts -storepass changeit</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>Tomcat4.1.34配置：<br />
&lt;Connector className="org.apache.coyote.tomcat4.CoyoteConnector"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; port="8443" enableLookups="true" scheme="https" secure="true"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; useURIValidationHack="false" disableUploadTimeout="true"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystoreFile="tomcat.keystore"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystorePass="changeit"/&gt;&nbsp; </div>
<div>Tomcat5.5.9配置：&nbsp; <br />
&nbsp;&nbsp; <br />
&lt;Connector port="8443" maxHttpHeaderSize="8192"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" disableUploadTimeout="true"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100" scheme="https" secure="true"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystoreFile="tomcat.keystore"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystorePass="changeit"/&gt;&nbsp;&nbsp; </div>
<div>Tomcat5.5.20配置(此配置同样可用于Tomcat6.0)：<br />
&lt;Connector protocol="org.apache.coyote.http11.Http11Protocol"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; port="8443" maxHttpHeaderSize="8192"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" disableUploadTimeout="true"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100" scheme="https" secure="true"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystoreFile="tomcat.keystore"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystorePass="changeit"/&gt;&nbsp;&nbsp; </div>
<div>Tomcat6.0.10配置：<br />
&lt;Connector protocol="org.apache.coyote.http11.Http11NioProtocol"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; port="8443" minSpareThreads="5" maxSpareThreads="75"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="true" disableUploadTimeout="true"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acceptCount="100"&nbsp; maxThreads="200"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scheme="https" secure="true" SSLEnabled="true"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clientAuth="false" sslProtocol="TLS"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystoreFile="D:/tools/apache-tomcat-6.0.10/tomcat.keystore"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keystorePass="changeit"/&gt;&nbsp;&nbsp; </div>
<div>&nbsp;&nbsp;&nbsp; </div>
<div><br />
其他有用keytool命令（列出信任证书库中所有已有证书，删除库中某个证书）：<br />
keytool -list -v -keystore D:/sdks/jdk1.5.0_11/jre/lib/security/cacerts<br />
keytool -delete -trustcacerts -alias tomcat&nbsp; -keystore&nbsp; D:/sdks/jdk1.5.0_11/jre/lib/security/cacerts -storepass changeit<br />
</div>
<img src ="http://www.blogjava.net/super/aggbug/263551.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2009-04-02 15:14 <a href="http://www.blogjava.net/super/archive/2009/04/02/263551.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DocumentBuilderFactory.newInstance()查找DocumentBuilderFactory实现类的过程</title><link>http://www.blogjava.net/super/archive/2009/01/06/250083.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Tue, 06 Jan 2009 05:23:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2009/01/06/250083.html</guid><wfw:comment>http://www.blogjava.net/super/comments/250083.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2009/01/06/250083.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/250083.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/250083.html</trackback:ping><description><![CDATA[1.在系统环境变量中(System.getProperties())中查找key=javax.xml.parsers.DocumentBuilderFactory<br />
2.如果1没有找到，则找java.home\lib\jaxp.properties 文件，如果文件存在，在文件中查找key=javax.xml.parsers.DocumentBuilderFactory<br />
3.如果2没有找到,则在classpath中的所有的jar包中查找META-INF/services/javax.xml.parsers.DocumentBuilderFactory 文件<br />
&nbsp;&nbsp;&nbsp;&nbsp;全都没找到，则返回null<br />
<img src ="http://www.blogjava.net/super/aggbug/250083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2009-01-06 13:23 <a href="http://www.blogjava.net/super/archive/2009/01/06/250083.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于角色的访问控制</title><link>http://www.blogjava.net/super/archive/2007/03/14/103810.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Wed, 14 Mar 2007 08:24:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2007/03/14/103810.html</guid><wfw:comment>http://www.blogjava.net/super/comments/103810.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2007/03/14/103810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/103810.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/103810.html</trackback:ping><description><![CDATA[最近公司要做<span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-font-kerning: 1.0pt; mso-bidi-font-family: Arial; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">基于角色的访问控制的模块，<br />自己查了些资料，自己胡乱写了一些，还不成熟。<br /><br /><a href="/Files/super/RBAC">http://www.blogjava.net/Files/super/RBAC</a>-权限管理--设计说明书.rar<br /><a href="/Files/super/RBAC.rar">http://www.blogjava.net/Files/super/RBAC.rar</a></span><img src ="http://www.blogjava.net/super/aggbug/103810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2007-03-14 16:24 <a href="http://www.blogjava.net/super/archive/2007/03/14/103810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DOJO.widget的性能问题</title><link>http://www.blogjava.net/super/archive/2006/12/12/87315.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Tue, 12 Dec 2006 09:46:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2006/12/12/87315.html</guid><wfw:comment>http://www.blogjava.net/super/comments/87315.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2006/12/12/87315.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/87315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/87315.html</trackback:ping><description><![CDATA[
		<p>对DOJO基本上算是文盲，只是项目中需要一些特效页面，在网上找了找，感觉DOJO做的不错，就拿过来用了，不过感觉性能很不好，页面刷新明显迟钝<br /><br />   我的页面上大概有10几个DOJO，刷一次页面仅仅因为DOJO的widget的初始化的问题就要5-6秒钟，读了一下DOJO的代码，只要的时间都花费在dojo.hostenv.makeWidgets这个方法中，本人的js水平比较低，基本上改不了DOJO的代码，不过在这个方法中却找到了一个稍微提高些性能的办法，这就是 djConfig.searchIds的使用。<br /><br />dojo.hostenv.makeWidgets = function(){<br /> // you can put searchIds in djConfig and dojo.hostenv at the moment<br /> // we should probably eventually move to one or the other<br /> var sids = [];<br /> <font style="BACKGROUND-COLOR: #ff0000">if(djConfig.searchIds &amp;&amp; djConfig.searchIds.length &gt; 0) {<br /></font>  sids = sids.concat(djConfig.searchIds);<br /> }<br /> if(dojo.hostenv.searchIds &amp;&amp; dojo.hostenv.searchIds.length &gt; 0) {<br />  sids = sids.concat(dojo.hostenv.searchIds);<br /> }</p>
		<p> if((djConfig.parseWidgets)||(sids.length &gt; 0)){<br />  if(dojo.evalObjPath("dojo.widget.Parse")){<br />   // we must do this on a delay to avoid:<br />   // <a href="http://www.shaftek.org/blog/archives/000212.html">http://www.shaftek.org/blog/archives/000212.html</a><br />   // IE is such a tremendous peice of shit.<br />    var parser = new dojo.xml.Parse();<br />    <font style="BACKGROUND-COLOR: #ff0000">if(sids.length &gt; 0){</font><br />     for(var x=0; x&lt;sids.length; x++){<br />      var tmpNode = document.getElementById(sids[x]);<br />      if(!tmpNode){ continue; }<br />      var frag = parser.parseElement(tmpNode, null, true);<br />      dojo.widget.getParser().createComponents(frag);<br />     }<br />    }else if(djConfig.parseWidgets){<br />     var frag  = parser.parseElement(document.getElementsByTagName("body")[0] || document.body, null, true);<br />     dojo.widget.getParser().createComponents(frag);<br />    }<br />  }<br /> }<br />}<br /><br />具体使用方法就是在自己的页面上把所有的dojo的widget都要定义ID，类似这样<br /><br />&lt;input id="queryStr_0" name="queryStr_0" dojoType="ComboBox" style="width:280px;" autocomplete="false" &gt;<br /><br /><br />然后加上这样一段js<br />&lt;script language=javascript&gt;<br /> djConfig.searchIds=['queryStr_0','queryStr_1','queryStr_2'];<br />&lt;/script&gt;<br />这里的'queryStr_0'之类的就是你的widget的ID,这样对于我的10几个widget的页面，速度基本上会快上1-2倍。<br /><br /><br /></p>
<img src ="http://www.blogjava.net/super/aggbug/87315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2006-12-12 17:46 <a href="http://www.blogjava.net/super/archive/2006/12/12/87315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSON-RPC的另类用法</title><link>http://www.blogjava.net/super/archive/2006/11/27/83815.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Mon, 27 Nov 2006 08:14:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2006/11/27/83815.html</guid><wfw:comment>http://www.blogjava.net/super/comments/83815.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2006/11/27/83815.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/83815.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/83815.html</trackback:ping><description><![CDATA[JSON-RPC 大家都知道了,我比较反感JSON-RPC的客户端/服务器端的交互方式，个人认为还是DWR的框架似乎好一些，不过单纯比较后台代码的风格，似乎JSON-RPC的代码更好些---纯粹个人喜好。<br /><br />   虽然不喜欢JSON-RPC的框架，不过对于JSON的javaObject--javascriptObject的转换代码倒是很欣赏，因此直接把JSON-RPC的这部分代码直接拿过来用，感觉也不错。当然，这已经跟AJAX关系不大了。<br /><br />   1.将jsonrpc-1.0.jar包含在你的project的classpath中，<br />   2.写个简单的Util类，将你的java Object 序列化成javascript的字符串。<br /><br />public class JSONUtil {<br /> public static final JSONSerializer se = new JSONSerializer();<br /> private static Logger log = Logger.getLogger(JSONUtil.class); <br /> static <br /> {<br />  try<br />  {<br />   se.registerDefaultSerializers();<br />  }<br />  catch (Exception e)<br />  {<br />   log.error(e);<br />  }<br /> }<br /> <br /> public static String toJSON(Object obj)<br /> {<br />  try<br />  {<br />   SerializerState state = new SerializerState();<br />   Object retuObj = se.marshall(state, obj);<br />   String retuStr = retuObj.toString();<br />   //retuStr.replaceAll("<a>\\\</a>"", "<a href="file://\\'">\\'</a>");<br />   //log.debug("JSONStr:"+retuStr);<br />   return retuStr;<br />  }<br />  catch (Exception e){<br />   log.error(e);<br />   return obj.toString();<br />  }<br /> }<br /><br /><br />3.   客户端的jsp中只要简单的加上这段js<br />&lt;script language=javascript&gt;<br /> eval('jsObject = &lt;%=JSONUtil.toJSON(javaObject)%&gt;'+';');<br />&lt;/script&gt;<br />javaObject是你自己的java类的实例，这样你就可以在js中直接操作jsObject 这个js对象了。<br /><br /><br /><br /><img src ="http://www.blogjava.net/super/aggbug/83815.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2006-11-27 16:14 <a href="http://www.blogjava.net/super/archive/2006/11/27/83815.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AJAX返回XML格式文本的读取方法</title><link>http://www.blogjava.net/super/archive/2006/11/27/83811.html</link><dc:creator>王卫华</dc:creator><author>王卫华</author><pubDate>Mon, 27 Nov 2006 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/super/archive/2006/11/27/83811.html</guid><wfw:comment>http://www.blogjava.net/super/comments/83811.html</wfw:comment><comments>http://www.blogjava.net/super/archive/2006/11/27/83811.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/super/comments/commentRss/83811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/super/services/trackbacks/83811.html</trackback:ping><description><![CDATA[
		<p>对于一个AJAX请求<br />如果返回的是标准的XML(有&lt;?xml version="1.0" encoding="UTF-8"?&gt;,并且ContentType = "text/xml")，则直接操作xmlhttp.responseXML应该是可以的,比如：<br />var requestMsg=xmlhttp.responseXML;<br />alert(requestMsg.getElementsByTagName("book").length);<br /><br />如果不是标准的XML.则返回的信息实际上是以文本的方式表示的，必须从xmlhttp.responseText中取得数据，方式如下：<br />var requestMsg=getXMLDoc(originalRequest.responsetext);<br />alert(requestMsg.getElementsByTagName("book").length);<br /><br /><br />getXMLDoc方法如下:<br /><br /> function getXMLDoc(xmlText){<br />  if(window.ActiveXObject){<br />   xmlDoc=new ActiveXObject("Microsoft.XMLDOM");<br />   xmlDoc.async=false;<br />   xmlDoc.onreadystatechange = function() <br />   {<br />    //if(xmlDoc.readyState == 4) doAction();<br />   }<br />   xmlDoc.loadXML(xmlText);<br />  }else if(document.implementation&amp;&amp;document.implementation.createDocument){<br />   xmlDoc=document.implementation.createDocument('','',null);<br />   //xmlDoc.onload=doAction();<br />   xmlDoc.loadXML(xmlText);<br />  }else return null;<br />  return xmlDoc;<br /> }<br /></p>
<img src ="http://www.blogjava.net/super/aggbug/83811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/super/" target="_blank">王卫华</a> 2006-11-27 16:02 <a href="http://www.blogjava.net/super/archive/2006/11/27/83811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>