Sunday, August 26, 2007
js -- grab/drag/drop
var mousey = 0;
var grabx = 0;
var graby = 0;
var orix = 0;
var oriy = 0;
var elex = 0;
var eley = 0;
var algor = 0;
var dragobj = null;
function falsefunc() { return false; } // used to block cascading events
function init()
{
document.onmousemove = update; // update(event) implied on NS, update(null) implied on IE
update();
}
function getMouseXY(e) // works on IE6,FF,Moz,Opera7
{
if (!e) e = window.event; // works on IE, but not NS (we rely on NS passing us the event)
if (e)
{
if (e.pageX || e.pageY)
{ // this doesn't work on IE6!! (works on FF,Moz,Opera7)
mousex = e.pageX;
mousey = e.pageY;
algor = '[e.pageX]';
if (e.clientX || e.clientY) algor += ' [e.clientX] '
}
else if (e.clientX || e.clientY)
{ // works on IE6,FF,Moz,Opera7
mousex = e.clientX + document.body.scrollLeft;
mousey = e.clientY + document.body.scrollTop;
algor = '[e.clientX]';
if (e.pageX || e.pageY) algor += ' [e.pageX] '
}
}
}
function update(e)
{
getMouseXY(e); // NS is passing (event), while IE is passing (null)
}
function grab(context)
{
document.onmousedown = falsefunc; // in NS this prevents cascading of events, thus disabling text selection
dragobj = context;
dragobj.style.zIndex = 10; // move it to the top
document.onmousemove = drag;
document.onmouseup = drop;
grabx = mousex;
graby = mousey;
elex = orix = dragobj.offsetLeft;
eley = oriy = dragobj.offsetTop;
update();
}
function drag(e) // parameter passing is important for NS family
{
if (dragobj)
{
elex = orix + (mousex-grabx);
eley = oriy + (mousey-graby);
dragobj.style.position = "absolute";
dragobj.style.left = (elex).toString(10) + 'px';
dragobj.style.top = (eley).toString(10) + 'px';
}
update(e);
return false; // in IE this prevents cascading of events, thus text selection is disabled
}
function drop()
{
if (dragobj)
{
dragobj.style.zIndex = 0;
dragobj = null;
}
update();
document.onmousemove = update;
document.onmouseup = null;
document.onmousedown = null; // re-enables text selection on NS
}
Monday, August 20, 2007
Tomcat 的数据库连接池设置与应用
2.在server.xml中设置数据源,以MySQL数据库为例,如下:
在<globalnamingresources> <globalnamingresources>节点中加入,
<Resource
name="jdbc/DBPool"
type="javax.sql.DataSource"
password="root"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="2"
maxWait="5000"
username="root"
url="jdbc:mysql://127.0.0.1:3306/test"
maxActive="4"/>
type,”javax.sql.DataSource”;
password,数据库用户密码;
driveClassName,数据库驱动;
maxIdle,最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连
接将被标记为不可用,然后被释放。设为0表示无限制。
MaxActive,连接池的最大数据库连接数。设为0表示无限制。
maxWait ,最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示
无限制。
3.在你的web应用程序的web.xml(WEB-INF/web.xml)中设置数据源参考,如下:
在
子节点说明: description,描述信息;
res-ref-name,参考数据源名字,同上一步的属性name;
res-type,资源类型,”javax.sql.DataSource”;
res-auth,”Container”;
res-sharing-scope,”Shareable”;
4.在web应用程序的context.xml (META-INF)中设置数据源链接,如下:
在
属性说明:name,同第2步和第3步的属性name值,和子节点res-ref-name值;
type,同样取”javax.sql.DataSource”;
global,同name值。
至此,设置完成,下面是如何使用数据库连接池。
1.建立一个连接池类,DBPool.java,用来创建连接池,代码如下:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DBPool {
private static DataSource pool;
static {
Context env = null;
try {
env = (Context) new InitialContext().lookup("java:comp/env");
pool = (DataSource)env.lookup("jdbc/DBPool");
if(pool==null)
System.err.println("'DBPool' is an unknown DataSource");
} catch(NamingException ne) {
ne.printStackTrace();
}
}
public static DataSource getPool() {
return pool;
}
}
2. 在要用到数据库操作的类或jsp页面中,用DBPool.getPool().getConnection(),获得一个Connection对象,就可 以进行数据库操作,最后别忘了对Connection对象调用close()方法,注意:这里不会关闭这个Connection,而是将这个 Connection放回数据库连接池。
Monday, August 13, 2007
TD Maximum Colspan
1000? (right now it ignores 1000 and displays the TD as a cell with no
colspan)
Maybe it's a really, really large multiplication table. Or a really,
really big linear programming matrix.
Or, maybe he/she/it is trying to achieve pixel-perfect layout up to
(pulling number out of hat) 1024 pixels wide.
I'd be impressed to see a browser render that without choking a bit.
http://www.intraproducts.com/beta/usenet/1101cells.asp
Nooooo, thats not the spec. So, in the end i'm guessing the answer is
NO, IE does not support colspans of > 1000.
Sunday, August 12, 2007
Modify Classpath At Runtime
The system classloader (ClassLoader.getSystemClassLoader()) is a subclass of URLClassLoader. It can therefore be casted into a URLClassLoader and used as one.
URLClassLoader has a protected method addURL(URL url), which you can use to add files, jars, web addresses - any valid URL in fact.
Since the method is protected you need to use reflection to invoke it.
Here's some code for a class which adds a File or URL to the classpath:
import java.lang.reflect.*;
import java.io.*;
import java.net.*;
public class ClassPathHacker {
private static final Class[] parameters = new Class[]{URL.class};
public static void addFile(String s) throws IOException {
File f = new File(s);
addFile(f);
}//end method
public static void addFile(File f) throws IOException {
addURL(f.toURL());
}//end method
public static void addURL(URL u) throws IOException {
URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL",parameters);
method.setAccessible(true);
method.invoke(sysloader,new Object[]{ u });
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}//end try catch
}//end method
}//end class
Wednesday, August 8, 2007
jdbc handling of blob type
A Blob is a JDBC interface mapping for an SQL BLOB. A Blob is obtained by the getBlob() methods of a ResultSet or CallableStatement. A Blob has methods to get its number of bytes and to determine the starting position of another Blob or an array of bytes in the current Blob. These methods work without materializing the data. To materialize the data, you can use getBinaryStream() or getBytes() ( for part or all of the Blob ) and then construct usable objects from the returned stream or byte array.
For Blob storage use setBlob() from a PreparedStatement or updateObject from an updatable ResultSet. Again, this is where most discussions end, with the example retrieving a Blob from one row and putting it to another row in the same or a different table.
How does Blob data get there in the first place? Again, look at the Blob methods, this time getBinaryStream() and getBytes(): use PreparedStatement's setBinaryStream() or setBytes() methods to populate the Blob.
Html online editor
先解释一下在线编辑器的原理: 首先需要IE5.0以上版本的支持。因为IE5.0以上版本有一个编辑状态,可以在一个iframe里面输入文字。然后通过 "document.body.innerHTML"可以获取iframe里面的html代码,这个就是关键。那怎么才能让ifrmae处于编辑状态呢, 可以用:
function document.onreadystatechange()
{
HtmlEdit.document.designMode="On";
}
函数实现。剩下的问题就是就是取得焦点和选中的值:
| HtmlEdit.focus(); var sel = HtmlEdit.document.selection.createRange(); |
以上2句可以获取选中的值的html代码。
到 了这里,基本原理搞清楚了,然后我们可以用 insertHTML("str")方法将html字符替换掉选种的值。以下就给出一个简单的demo来演示只有加粗效果的在线编辑器。我这里用了一个 textarea来或得iframe里的html值,实际情况,可以将textarea的display设置成false,然后就可以将iframe的内 容提交.
函数实现。剩下的问题就是就是取得焦点和选中的值:
| HtmlEdit.focus(); var sel = HtmlEdit.document.selection.createRange(); |
以上2句可以获取选中的值的html代码。
到 了这里,基本原理搞清楚了,然后我们可以用 insertHTML("str")方法将html字符替换掉选种的值。以下就给出一个简单的demo来演示只有加粗效果的在线编辑器。我这里用了一个 textarea来或得iframe里的html值,实际情况,可以将textarea的display设置成false,然后就可以将iframe的内 容提交.
函数实现。剩下的问题就是就是取得焦点和选中的值:
| HtmlEdit.focus(); var sel = HtmlEdit.document.selection.createRange(); |
以上2句可以获取选中的值的html代码。
到 了这里,基本原理搞清楚了,然后我们可以用 insertHTML("str")方法将html字符替换掉选种的值。以下就给出一个简单的demo来演示只有加粗效果的在线编辑器。我这里用了一个 textarea来或得iframe里的html值,实际情况,可以将textarea的display设置成false,然后就可以将iframe的内 容提交.
http://www.cnbruce.com/blog/showlog.asp?log_id=1168
Monday, August 6, 2007
recommended JDBC coding pattern
close() any JDBC object as soon as it has played its part; garbage collection should not be relied upon. Forgetting to close() things properly results in spurious errors and misbehaviour. The above try-finally construct is a recommended code pattern to use with JDBC objects.Statement stmt = conn.createStatement();Data is retrieved from the database using a database query mechanism. The example below shows creating a statement and executing a query.
try {
stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
} finally {
//It's important to close the statement when you are done with it
stmt.close();
}
Statement stmt = conn.createStatement();
try {
ResultSet rs = stmt.executeQuery( "SELECT * FROM MyTable" );
try {
while ( rs.next() ) {
int numColumns = rs.getMetaData().getColumnCount();
for ( int i = 1 ; i <= numColumns ; i++ ) {
//Column numbers start at 1.
//Also there are many methods on the result set to return
// the column as a particular type. Refer to the Sun documentation
// for the list of valid conversions.
System.out.println( "COLUMN " + i + " = " + rs.getObject(i) );
}
}
} finally {
rs.close();
}
} finally {
stmt.close();
}
Connection Pooling
Connection pooling with MySQL Connector/J
http://dev.mysql.com/tech-resources/articles/connection_pooling_with_connectorj.html
Connection pooling is a technique of creating and managing a pool of connections that are ready for use by any thread that needs them.When the connection is "loaned out" from the pool, it is used exclusively by the thread that requested it. From a programming point of view, it is the same as if your thread called
DriverManager.getConnection() every time it needed a JDBC connection, however with connection pooling, your thread may end up using either a new, or already-existing connection.Luckily, Sun has standardized the concept of connection pooling in JDBC through the JDBC-2.0 "Optional" interfaces, and all major application servers have implementations of these APIs that work fine with MySQL Connector/J.
Generally, you configure a connection pool in your application server configuration files, and access it via the Java Naming and Directory Interface (JNDI).import java.sql.Connection;The most important thing to remember when using connection pooling is to make sure that no matter what happens in your code (exceptions, flow-of-control, etc), connections, and anything created by them (statements, result sets, etc) are closed, so that they may be re-used, otherwise they will be "stranded," which in the best case means that the MySQL server resources they represent (buffers, locks, sockets, etc) may be tied up for some time, or worst case, may be tied up forever.
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class MyServletJspOrEjb {
public void doSomething() throws Exception {
/*
* Create a JNDI Initial context to be able to
* lookup the DataSource
*
* In production-level code, this should be cached as
* an instance or static variable, as it can
* be quite expensive to create a JNDI context.
*
* Note: This code only works when you are using servlets
* or EJBs in a J2EE application server. If you are
* using connection pooling in standalone Java code, you
* will have to create/configure datasources using whatever
* mechanisms your particular connection pooling library
* provides.
*/
InitialContext ctx = new InitialContext();
/*
* Lookup the DataSource, which will be backed by a pool
* that the application server provides. DataSource instances
* are also a good candidate for caching as an instance
* variable, as JNDI lookups can be expensive as well.
*/
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");
/*
* The following code is what would actually be in your
* Servlet, JSP or EJB 'service' method...where you need
* to work with a JDBC connection.
*/
Connection conn = null;
Statement stmt = null;
try {
conn = ds.getConnection();
/*
* Now, use normal JDBC programming to work with
* MySQL, making sure to close each resource when you're
* finished with it, which allows the connection pool
* resources to be recovered as quickly as possible
*/
stmt = conn.createStatement();
stmt.execute("SOME SQL QUERY");
stmt.close();
stmt = null;
conn.close();
conn = null;
} finally {
/*
* close any jdbc instances here that weren't
* explicitly closed during normal code path, so
* that we don't 'leak' resources...
*/
if (stmt != null) {
try {
stmt.close();
} catch (sqlexception sqlex) {
// ignore -- as we can't do anything about it here
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (sqlexception sqlex) {
// ignore -- as we can't do anything about it here
}
conn = null;
}
}
}
}
Connection Pooling Configuration Documentation
Place a copy of mysql-connector-java-[version]-bin.jar in $CATALINA_HOME/common/lib/. Then, follow the instructions in the section MySQL DBCP Example of the Tomcat documentation.
Notice that Connector/J 3.0 and newer work with the same settings: http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-datasource-examples-howto.html
long time idle mysql connection
MySQL closes connections after 8 hours of inactivity. You either need to use a connection pool that handles stale connections or use the "autoReconnect" parameter.
Also, you should be catching SQLExceptions in your application and dealing with them, rather than propagating them all the way until your application exits, this is just good programming practice. MySQL Connector/J will set the SQLState (see java.sql.SQLException.getSQLState() in your APIDOCS) to "08S01" when it encounters network-connectivity issues during the processing of a query. Your application code should then attempt to re-connect to MySQL at this point.
The following (simplistic) example shows what code that can handle these exceptions might look like:
public void doBusinessOp() throws SQLException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
// How many times do you want to retry the transaction
// (or at least _getting_ a connection)?
int retryCount = 5;
boolean transactionCompleted = false;
do {
try {
conn = getConnection(); // assume getting this from a
// javax.sql.DataSource, or the
// java.sql.DriverManager
conn.setAutoCommit(false);
//
// Okay, at this point, the 'retry-ability' of the
// transaction really depends on your application logic,
// whether or not you're using autocommit (in this case
// not), and whether you're using transacational storage
// engines
//
// For this example, we'll assume that it's _not_ safe
// to retry the entire transaction, so we set retry
// count to 0 at this point
//
// If you were using exclusively transaction-safe tables,
// or your application could recover from a connection going
// bad in the middle of an operation, then you would not
// touch 'retryCount' here, and just let the loop repeat
// until retryCount == 0.
//
retryCount = 0;
stmt = conn.createStatement();
String query = "SELECT foo FROM bar ORDER BY baz";
rs = stmt.executeQuery(query);
while (rs.next()) {
}
rs.close();
rs = null;
stmt.close();
stmt = null;
conn.commit();
conn.close();
conn = null;
transactionCompleted = true;
} catch (SQLException sqlEx) {
//
// The two SQL states that are 'retry-able' are 08S01
// for a communications error, and 40001 for deadlock.
//
// Only retry if the error was due to a stale connection,
// communications problem or deadlock
//
String sqlState = sqlEx.getSQLState();
if ("08S01".equals(sqlState) || "40001".equals(sqlState)) {
retryCount--;
} else {
retryCount = 0;
}
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) {
// You'd probably want to log this . . .
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException sqlEx) {
// You'd probably want to log this as well . . .
}
}
if (conn != null) {
try {
//
// If we got here, and conn is not null, the
// transaction should be rolled back, as not
// all work has been done
try {
conn.rollback();
} finally {
conn.close();
}
} catch (SQLException sqlEx) {
//
// If we got an exception here, something
// pretty serious is going on, so we better
// pass it up the stack, rather than just
// logging it. . .
throw sqlEx;
}
}
}
} while (!transactionCompleted && (retryCount > 0));
}There really is no way to keep a connection alive indefitely, and I'm
not aware of compelling reasons to do so for many reasons. First, it
consumes resources that aren't needed if the connection is sitting idle,
and second, it increases the risk that network issues, or server
restarts will cause your application to crash.
It takes very little time (on the order of a few milliseconds) to create
a JDBC connection to MySQL, so you should set your connection pool to
only let connections stay idle for a few minutes.
Most of the high-volume applications I've seen that use Java with MySQL
don't let connections stay idle more than 10 minutes or so.
------------------------------------------------------------------------------
Mark,
Since years you recommend not to just use "autoReconnect=true" but to be
smarter. First hints are in
http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-p
roperties.html and
http://dev.mysql.com/doc/refman/5.0/en/connector-j-usagenotes-j2ee.html
A few questions:
1) you recommend to "deal with SQLExceptions", do you have any code-examples
how you recommend to do this - a while loop until I finally get a working
connection or a different exception?
In my setup, I use both ssl protected remote jdbc's and regular local jdbc's
and AFAICR, the exceptions I get are not necessarily identical?
You suggest this also http://lists.mysql.com/java/8119 - what would be a
generic approach to do this? I guess if I deal with the exceptions,
testOnBorrow=true no longer makes sense?
2) How do you rate the "testWhileIdle" strategy? If I do that, shouldn't I
add also "minIdle" to ensure that if an idle test fails, a new connection is
added to the pool? If this is configured nicely, do you still think it is
worthwhile to set testOnBorrow=true as long as my application doesn't have a
5*9 SLA?
Also, I use the Jakarta commons-dbcp with BasicDataSource and see that in
org.apache.commons.dbcp.datasources.InstanceKeyDataSource the
"testWhileIdle" keyword is dealt with. But who really does the testing? Is
that connector-j or dbcp?
3) The documentation also lists autoReconnectForPools. How does this fit
into the picture if I have tomcat with dbcp and JNDI resources?
http://lists.mysql.com/java/7774
Many thanks for any hints in advance!
Ralf
Friday, August 3, 2007
用JSP实现图形验证码
用JSP实现图形验证码
import java.io.*;
import java.util.*;
import com.sun.image.codec.jpeg.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.*;
import java.awt.image.*;
public class ValidateCode extends HttpServlet {
private Font mFont=new Font("宋体", Font.PLAIN,12);//设置字体
//处理post
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException {
doGet(request,response);
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException {
//取得一个1000-9999的随机数
String s="";
int intCount=0;
intCount=(new Random()).nextInt(9999);//
if(intCount<1000)intcount+=1000;>
s=intCount+"";
//保存入session,用于与用户的输入进行比较.
//注意比较完之后清除session.
HttpSession session=request.getSession (true);
session.setAttribute("validateCode",s);
response.setContentType("image/gif");
ServletOutputStream out=response.getOutputStream();
BufferedImage image=new BufferedImage(35,14,BufferedImage.TYPE_INT_RGB);
Graphics gra=image.getGraphics();
//设置背景色
gra.setColor(Color.yellow);
gra.fillRect(1,1,33,12);
//设置字体色
gra.setColor(Color.black);
gra.setFont(mFont);
//输出数字
char c;
for(int i=0;i<4;i++)>
c=s.charAt(i);
gra.drawString(c+"",i*7+4,11); //7为宽度,11为上下高度位置
}
JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(out);
encoder.encode(image);
out.close();
}
}
Use AWT Library in the tomcat or other containers
java.lang.InternalError: Can't connect to X11 window server
java.lang.InternalError: Can't connect to window server - not enough permissions.
java的图片处理包需要图形环境,而linux上没有启动图形环境,找不到图形环境的server(X11 window server using ':0.0' )所以会报这个错。而通过java -Djava.awt.headless=true 这个参数的指定就可以避免java 2d去找图形环境。
要么这样试试,应该也可以。在servlet里一开始写一句:
System.setProperty("java.awt.headless","true");
web服务器的java虚拟机必须加以个参数java.awt.headless=true
以tomcat为例
可以在/etc/profile或启动web服务的用户的.bash_profile中的CATALINA_OPTS变量中加入:
CATALINA_OPTS="... -Djava.awt.headless=true"