??xml version="1.0" encoding="utf-8" standalone="yes"?> Hibernate内嵌了对C3P0,Proxool,JNDI数据源等数据库连接池的支持。但当我们需要用除了这几个数据源外的其他数据源的时候就有问题了Q例如我们需要用Apache的开源连接池目DBCPQ或者说我们惌使用多数JDBC驱动E序中自带的XxxxDataSourceӞHibernate没有提供对q方面的支持。庆q的是Hibernate做ؓ一个强大的数据持久层组Ӟ它在实现数据库连接方面的扩展性也是非常强大的。本文将介绍两种如何在Hibernate目中用自定义数据源的Ҏ?/p>
本文假设你已l有Hibernate的开发经验?/p>
在开始之前应该先明确你的目中的具体情况Q也是认Hibernate内嵌的组件是否真的无法支持你的应用需要。例如C3P0或者Proxool已经可以满大部分数据库的需要,又或者你的数据源是在应用服务器中配置的,那么你也没有必要q行扩展Q你可以直接使用DatasourceConnectionProvider来让Hibernate使用你所定义的数据源?/p>
那么什么时候你需要扩展HibernateҎ据源的支持呢Q可能你永远也用不上Q但我一直在用。我用的原因可能不能成ؓ正当的理由,因ؓC3P0或者ProxoolL些小地方的不我不爽,个h更偏向于DBCPq接池。或许本文应该改名ؓ《让Hibernate支持DBCP数据源》,其实DBCP只不q是我的一个具体的例子Q本文具有更普遍的应用意义。下面我们具体介l两U不同的扩展思\?/p>
假设我们已经有了一个WEB目Q该目采用了Struts框架Q而且我们已经在Struts中配|了数据源,也有不少的代码是依赖q个数据源运行的。现在我们需要给目中加入对Hibernate的支持,但又不想MҎ的已l成功稳定运行的代码了。那我们该怎么办?如果同样在Hibernate配置一个数据源指到同一个数据库Q相信你也不乐意q样qԌ因ؓ一旦配|上有修攚w么Struts和Hibernate的配|都需要修改,q个也只是麻烦一点而已Q最要命的是没法让原有的代码和Hibernateq一个数据库q接Q因此事务处理也无从谈赗?/p>
说那么多理由Q无非就是ؓ了让Hibernate可以使用Struts中配|的数据源,而我们暂且不去考虑q是否是最好的解决Ҏ?/p>
在Hibernate中有一个UserSuppliedConnectionProviderc,其实q个cM么也不干Q你一旦让它干点啥吧,它还净出异常,搞得你很是恼火。在Hibernate中,q个cȝ含义是要求用戯己来提供数据库连接的获取ҎQ同时当然也要自p责关闭连接?/p>
Z使用Struts中配|的数据源,我们׃能直接调用SessionFactory.openSession()Ҏ来获取Session实例Q因Z如果没有在Hibernate中配|Q何的数据库连接,那Hibernate会默认让UserSuppliedConnectionProvidercL跟你捣ؕQ你会收到很多异怿息,反复提醒我们必须自己提供数据库连接!我们要做q是调用openSessionҎQ不同的是需要先从Struts的数据源中获取数据库q接Q然后传递该q接lopenSessionҎQ参?SessionFactory.openSession(Connection) ҎQ?/p>
需要提醒大家注意的是closeSessionҎQ在该方法中我们必须手工d闭session对应的数据库q接Q我们前面已l提CQUserSuppliedConnectionProvidercd是要求用戯己提供数据库q接已经q接的关闭。如果没有调用ssn.connection().close()ҎQ这会导致Struts的数据源的连接没有被释放?/p>
同理Q上面提到的Struts只是一个应用普遍的例子Q实际中你可以用Q何的外部q接池,你只需要将获取到的数据库连接传递给openSessionҎQƈ自行负责释放数据库连接即可。应该说q是一U最单的思\Q好处是对系l的变动最,兼容原来的代码?/p>
Hibernate本n是通过ConnectionProvider接口来实现管理数据库q接的。例如其自带的C3P0ConnectionProviderQProxoolConnectionProvider{?/p>
在这个思\中,我们希望可以直接在Hibernate的配|文件中配置数据库连接,也就是让Hibernate独揽数据库的理Q真正做到各司其职。ؓ了更了解该接口的使用Q你不妨阅读一下Hibernate提供的上面几个类的源码?/p>
接下来我们需要编写一个实CConnectionProvider接口的类Q要求这个类能支持Q何的W合DataSource接口规范的数据源Q同时在Hibernate的配|文件中q行参数的设定。首先我们假定我们的cd是DataSourceConnProviderQ那我们的配|信息在hibernate.cfg.xml中看h应该像下面一?/p>
在上面的配置信息中,connection.provider_class是Hibernate本n用来指定不同ConnectionProvider实现cR接下来我们规定了我们的扩展所使用的配|键值都是以dscp.开_同时我们使用dscp.datasource来指定具体实CDataSource接口的类名,例如如果使用DBCPq个q接池,那么q个cd应该是org.apache.commons.dbcp.BasicDataSource。对于其他以dscp.开头的且不是dscp.datasource的配|信息都会直接赋值给DataSource的实现类。例如上面的配置中,driverClassName、url、username、password{配|信息都是BasicDataSourcecȝ属性?/p>
下面是我们所实现的DataSourceConnProvidercȝ源码?/p>
在DataSourceConnProvidercMQconfigureҎ会在Hibernateq行初始化的q程中被调用Q我们根据配|的DataSourcecd创徏数据源实例,q将配置参数赋值给该实例后卛_成了数据源的初始化。接下来是实现了getConnection和closeConnectionҎ分别是获取数据库q接和关闭连接的Ҏ。方法close用来关闭整个数据源,该方法会在Hibernate释放时被调用?/p>
你也可以使用其他一些不同的数据源而不一定非是DBCP数据源。配|完毕后接下来的事情q单了Q直接调用SessionFactory.openSession()Ҏ获取Session实例Q直接调用session.close()释放该实例,无需再手工去关闭session所装的connection接口?/p>
相比较上面两U思\而言Q各有千U。如果你真的有必要扩展HibernateҎ据源的支持,如果你没有兼Ҏ代码q个问题需要考虑的话Q那我更們于第二种思\。因为它使得整个目的各个层ơ分工非常清晎ͼ而且除了ConnectionProvider cM外应用的代码也相对简单?/p>
//获取Session实例
public Session getSession(){
ServletContext contxt = ....
SessionFactory sessions = ....
DataSource ds = (DataSource)context.getAttribute(Globals.DATA_SOURCE_KEY);
final Connection conn = ds.getConnection();
return sessions.openSession(conn);
}
//释放Session
public void closeSession(Session ssn){
ssn.connection().close();
ssn.close();
}
回页?/font>
<!-- Connection Pool settings -->
<property name="connection.provider_class">
com.liusoft.dlog4j.db.DataSourceConnProvider</property>
<property name="dscp.datasource">org.apache.commons.dbcp.BasicDataSource</property>
<property name="dscp.driverClassName">sun.jdbc.odbc.JdbcOdbcDriver</property>
<property name="dscp.url">jdbc:odbc:dlog4j</property>
<property name="dscp.username">admin</property>
<property name="dscp.password"></property>
<property name="dscp.initialSize">1</property>
<property name="dscp.maxActive">200</property>
<property name="dscp.maxWait">2000</property>
<property name="dscp.defaultAutoCommit">false</property>
<property name="dscp.defaultReadOnly">false</property>
<property name="dscp.removeAbandoned">true</property>
<property name="dscp.removeAbandonedTimeout">120</property>
<!--
<property name="dscp.defaultTransactionIsolation">1</property>
-->
<property name="dscp.poolPreparedStatements">true</property>
<property name="dscp.maxOpenPreparedStatements">1000</property>
package com.liusoft.dlog4j.db;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.beanutils.BeanUtils;
import org.hibernate.HibernateException;
import org.hibernate.connection.ConnectionProvider;
import com.liusoft.dlog4j.Globals;
import com.liusoft.dlog4j.util.StringUtils;
/**
* 让Hibernate支持各种数据?
* @author Winter Lau
*/
public class DataSourceConnProvider implements ConnectionProvider {
private final static String BASE_KEY = "dscp.";
private final static String ENCODING_KEY = "dscp.encoding";
private final static String DATASOURCE_KEY = "dscp.datasource";
protected DataSource dataSource;
/* (non-Javadoc)
* @see org.hibernate.connection.ConnectionProvider#configure(java.util.Properties)
*/
public void configure(Properties props) throws HibernateException {
String dataSourceClass = null;
Properties new_props = new Properties();
Iterator keys = props.keySet().iterator();
while(keys.hasNext()){
String key = (String)keys.next();
if(DATASOURCE_KEY.equalsIgnoreCase(key)){
dataSourceClass = props.getProperty(key);
}
else if(key.startsWith(BASE_KEY)){
String value = props.getProperty(key);
value = StringUtils.replace(value, "{DLOG4J}", Globals.WEBAPP_PATH);
new_props.setProperty(key.substring(BASE_KEY.length()), value);
}
}
if(dataSourceClass == null)
throw new HibernateException("Property 'dscp.datasource' no defined.");
try {
dataSource = (DataSource)Class.forName(dataSourceClass).newInstance();
BeanUtils.populate(dataSource, new_props);
} catch (Exception e) {
throw new HibernateException(e);
}
}
/* (non-Javadoc)
* @see org.hibernate.connection.ConnectionProvider#getConnection()
*/
public Connection getConnection() throws SQLException {
final Connection conn = dataSource.getConnection();
if(useProxy && conn!=null){
return (new _Connection(conn,encoding)).getConnection();
}
return conn;
}
/* (non-Javadoc)
* @see org.hibernate.connection.ConnectionProvider#closeConnection(java.sql.Connection)
*/
public void closeConnection(Connection conn) throws SQLException {
if(conn!=null && !conn.isClosed())
conn.close();
}
/* (non-Javadoc)
* @see org.hibernate.connection.ConnectionProvider#close()
*/
public void close() throws HibernateException {
if(dataSource != null)
try {
Method mClose = dataSource.getClass().getMethod("close",null);
mClose.invoke(dataSource, null);
} catch (Exception e) {
throw new HibernateException(e);
}
dataSource = null;
}
/* (non-Javadoc)
* @see org.hibernate.connection.ConnectionProvider#supportsAggressiveRelease()
*/
public boolean supportsAggressiveRelease() {
return false;
}
}
]]>
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import com.zte.hibernate.domain.Dept;
import com.zte.hibernate.domain.Emp;
/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution. Follows the Thread Local Session
* pattern, see {@linkhttp://hibernate.org/42.html}.
*/
public class HibernateSessionFactory {
/**
* Location of hibernate.cfg.xml file.
* NOTICE: Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file. That
* is place the config file in a Java package - the default location
* is the default Java package.<br><br>
* Examples: <br>
* <code>CONFIG_FILE_LOCATION = "/hibernate.conf.xml".
* CONFIG_FILE_LOCATION = "/com/foo/bar/myhiberstuff.conf.xml".</code>
*/
private static String CONFIG_FILE_LOCATION = "/com/zte/hibernate/dao/hibernate.cfg.xml";
/** Holds a single instance of Session */
private static final ThreadLocal threadLocal = new ThreadLocal();
/** The single instance of hibernate configuration */
private static final Configuration cfg = new Configuration();
/** The single instance of hibernate SessionFactory */
private static org.hibernate.SessionFactory sessionFactory;
/**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session currentSession() throws HibernateException {
Session session = (Session) threadLocal.get();
Properties p = new Properties();
InputStream in;
try {
in = new FileInputStream("src/hibernate.properties");
p.load(in);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
try {
cfg.setProperties(p);
cfg.addClass(Dept.class);
cfg.addClass(Emp.class);
//cfg.configure(CONFIG_FILE_LOCATION);
sessionFactory = cfg.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
/**
* Default constructor.
*/
private HibernateSessionFactory() {
}
}
set hibernate.cglib.use_reflection_optimizer=false for more info
今天到
HibernateDBModel Error: exception setting property value with CGLIB
(set hibernate.cglib.use_reflection_optimizer=false for more info)
setter of com.belief.po.Good.setTuijian
解决办法
你的数据库里的某个字D늚gؓNULLQ而事情本不该q样的。解决的办法是把这个字D늚NULL值改为非NULL|是查找数据库,看看是否又字DؓnullQ改成非null卛_。(i use sqlserverQ?/p>
import java.sql.*; import java.io.*; import oracle.sql.*; public class WriteBlob { public static void main(String[] args) { try { DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","fankai","fankai"); conn.setAutoCommit(false); BLOB blob = null; PreparedStatement pstmt = conn.prepareStatement("insert into javatest(name,content) values(?,empty_blob())"); pstmt.setString(1,"fankai"); pstmt.executeUpdate(); pstmt.close(); pstmt = conn.prepareStatement("select content from javatest where name= ? for update"); pstmt.setString(1,"fankai"); ResultSet rset = pstmt.executeQuery(); if (rset.next()) blob = (BLOB) rset.getBlob(1); String fileName = "oraclejdbc.jar"; File f = new File(fileName); FileInputStream fin = new FileInputStream(f); System.out.println("file size = " + fin.available()); pstmt = conn.prepareStatement("update javatest set content=? where name=?"); OutputStream out = blob.getBinaryOutputStream(); int count = -1, total = 0; byte[] data = new byte[(int)fin.available()]; fin.read(data); out.write(data); /* byte[] data = new byte[blob.getBufferSize()]; 另一U实现方?节省内存 while ((count = fin.read(data)) != -1) { total += count; out.write(data, 0, count); } */ fin.close(); out.close(); pstmt.setBlob(1,blob); pstmt.setString(2,"fankai"); pstmt.executeUpdate(); pstmt.close(); conn.commit(); conn.close(); } catch (SQLException e) { System.err.println(e.getMessage()); e.printStackTrace(); } catch (IOException e) { System.err.println(e.getMessage()); } } } |
into javatest(name,content) values(?,empty_blob()); |
select content from javatest where name= ? for update; |
java.sql.Blob oracle.sql.BLOB |
package com.fankai; import java.sql.Blob; public class Cat { private String id; private String name; private char sex; private float weight; private Blob image; public Cat() { } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public float getWeight() { return weight; } public void setWeight(float weight) { this.weight = weight; } public Blob getImage() { return image; } public void setImage(Blob image) { this.image = image;} } |
Q?xml version="1.0"?Q?br />Q?DOCTYPE hibernate-mapping SYSTEM "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"Q?br /> Qhibernate-mappingQ?br />Qclass name="com.fankai.Cat" table="cat"Q?br />Q?--jcs-cache usage="read-only"/--Q?br />Qid name="id" unsaved-value="null"Q?br />Qgenerator class="uuid.hex"/Q?br />Q?idQ?br />Qproperty name="name" length="16" not-null="true"/Q?br />Qproperty name="sex" length="1" not-null="true"/Q?br />Qproperty name="weight" /Q?br />Qproperty name="image" /Q?br />Q?classQ?br />Q?hibernate-mappingQ?/td> |
package com.fankai; import java.sql.Blob; import net.sf.hibernate.*; import oracle.sql.*; import java.io.*; public class TestCatHibernate { public static void testBlob() { Session s = null; byte[] buffer = new byte[1]; buffer[0] = 1; try { SessionFactory sf = HibernateSessionFactory.getSessionFactory(); s = sf.openSession(); Transaction tx = s.beginTransaction(); Cat c = new Cat(); c.setName("Robbin"); c.setImage(Hibernate.createBlob(buffer)); s.save(c); s.flush(); s.refresh(c, LockMode.UPGRADE); BLOB blob = (BLOB) c.getImage(); OutputStream out = blob.getBinaryOutputStream(); String fileName = "oraclejdbc.jar"; File f = new File(fileName); FileInputStream fin = new FileInputStream(f); int count = -1, total = 0; byte[] data = new byte[(int)fin.available()]; fin.read(data); out.write(data); fin.close(); out.close(); s.flush(); tx.commit(); } catch (Exception e) { System.out.println(e.getMessage()); } finally { if (s != null) try { s.close(); } catch (Exception e) {} } } } |
MD5Q意长度的"字节?变换成一?28bit的大整数Qƈ且它是一个不可逆的字符串变换算法,换句话说是Q即使你看到源程序和法描述Q也无法一个MD5的值变换回原始的字W串Q从数学原理上说Q是因ؓ原始的字W串有无I多个,q有点象不存在反函数的数学函数?/font>
MD5的典型应用是对一DMessage(字节?产生fingerprint(指纹)Q以防止?改"。D个例子,你将一D话写在一个叫readme.txt文g中,q对q个readme.txt产生一个MD5的值ƈ记录在案Q然后你可以传播q个文gl别人,别h如果修改了文件中的Q何内容,你对q个文g重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5q可以防止文件作者的"抵赖"Q这是所谓的数字{应用?/font>
MD5q广泛用于加密和解密技术上Q在很多操作pȝ中,用户的密码是以MD5|或类似的其它法Q的方式保存的,用户Login的时候,pȝ是把用户输入的密码计成MD5|然后再去和系l中保存的MD5D行比较,而系lƈ?知道"用户的密码是什么?/font>
一些黑客破莯U密码的Ҏ是一U被UCؓ"跑字?的方法。有两种Ҏ得到字典Q一U是日常搜集的用做密码的字符串表Q另一U是用排列组合方法生成的Q先用MD5E序计算些字兔R的MD5|然后再用目标的MD5值在q个字典中检索?/font>
即假设密码的最大长度ؓ8Q同时密码只能是字母和数字,?6+26+10=62个字W,排列l合出的字典的项数则是P(62,1)+P(62,2)....+P(62,8)Q那也已l是一个很天文的数字了Q存储这个字典就需要TBU的盘l,而且q种Ҏq有一个前提,是能获得目标̎L密码MD5值的情况下才可以?/font>
在很多电子商务和C应用中,理用户的Account是一U最常用的基本功能,管很多Application Server提供了这些基本组Ӟ但很多应用开发者ؓ了管理的更大的灵zL还是喜Ƣ采用关pL据库来管理用P懒惰的做法是用户的密码往往使用明文或简单的变换后直接保存在数据库中Q因此这些用L密码对Y件开发者或pȝ理员来说可以说毫无保密可言Q本文的目的是介lMD5的Java Bean的实玎ͼ同时l出用MD5来处理用LAccount密码的例子,q种Ҏ使得理员和E序设计者都无法看到用户的密码,管他们可以初始化它们。但重要的一Ҏ对于用户密码讄习惯的保?/font>
MD加密法的JAVA描述为:
import java.security.*;
import java.security.spec.*;
class Md5{
public final static String MD5(String s){
char hexDigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
try {
byte[] strTemp = s.getBytes();
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(strTemp);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
}
catch (Exception e){
return null;
}
}
public static void main(String[] args){
System.out.print(MD5.Md5("XX"));
}
private static final int PORT = 9999;
private ByteBuffer buffer = ByteBuffer.allocate(10240);
private ProxyUtil proxyUtil = new ProxyUtil();
private static String remoteHost = "";
private static int remotePort = 80;
private Logger log = ZXLogger.getLogger(ProxyServer.class.getName());
//private Log log = LogFactory.getLog(ProxyServer.class);
public ProxyServer()
{
//PropertyConfigurator.configure("src/log4j.properties");
}
/**
* Ҏ名称Qstart <p>
* Ҏ功能Q运行代理服务器 <p>
* 参数说明Q?lt;p>
* q回Qvoid <p>
* 作者:李明 <p>
* 日期Q?006q??3?<p>
*/
public void runServer()
{
ServerSocket sSocket = null;
ServerSocketChannel ssc = null;
// 代理服务器监听开?/font>
Selector selector = null;
try
{
ssc = ServerSocketChannel.open();
sSocket = ssc.socket();
sSocket.bind(new InetSocketAddress(PORT));
selector = Selector.open();
System.err.println("Listening Port is " + PORT);
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
}
catch(ClosedChannelException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
catch(IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
try
{
while(true)
{
int n = selector.select();
if(n == 0)
{
continue; // nothing to do
}
Set set = selector.selectedKeys();
Iterator iter = set.iterator();
while(iter.hasNext())
{
SelectionKey key = (SelectionKey)iter.next();
if(key.isAcceptable())
{
ServerSocketChannel svrSocketChannel = (ServerSocketChannel)key.channel();
SocketChannel clientChannel = null;
try
{
clientChannel = svrSocketChannel.accept();
}
catch(IOException e)
{
// TODO Auto-generated catch block
if(clientChannel != null)
{
clientChannel.close();
}
if(key != null)
{
key.cancel();
}
}
send(clientChannel);
}
iter.remove();
log.info("************SEND END*************");
}
}
}
catch(IOException e)
{
// TODO Auto-generated catch block
log.info("ServerSocketChannelMq代发生核心异常\r\n" + e.getMessage());
e.printStackTrace();
}
}
/**
* Ҏ名称Qsend <p>
* Ҏ功能Q发送给客户信息 <p>
* 参数说明QSocketChannel, String <p>
* q回Qvoid <p>
* 作者:李明 <p>
* 日期Q?006q??3?<p>
*
* @param channel
* @param key
* @throws IOException
*/
public void send(SocketChannel clientChannel)
{
SocketChannel remoteSvrChannel = null;
buffer.clear();
int count;
log.info("************SEND START*************");
try
{
while((count = clientChannel.read(buffer)) > 0)
{
buffer.flip();
byte[] bytebuffer = new byte[count];
buffer.get(bytebuffer, 0, count);
ByteBuffer bufferWrite = ByteBuffer.wrap(bytebuffer);
byte[] b = new byte[bufferWrite.limit()];
bufferWrite.get(b);
String context = new String(b);
// 打印客户h代理服务器信?br /> log.info(context);
// 解析客户信息Q得到远E主机和端口?br /> proxyUtil.setUrl(context);
setRemoteHost(proxyUtil.getHost());
setRemotePort(proxyUtil.getPort());
log.info("Remote Host " + getRemoteHost());
log.info("Remote Port " + getRemotePort());
if(remoteSvrChannel == null)
{
InetSocketAddress inet = new InetSocketAddress(getRemoteHost(), getRemotePort());
try
{
remoteSvrChannel = SocketChannel.open(inet);
// remoteSvrChannel.configureBlocking(false);
// Socket remoteSvr = remoteSvrChannel.socket();
// remoteSvr.setSoTimeout(1000);
bufferWrite.flip();
remoteSvrChannel.write(bufferWrite);
buffer.clear();
int n;
while((n = remoteSvrChannel.read(buffer)) > 0)
{
log.info("n=" + n);
buffer.flip();
log.info("buffer.limit=" + buffer.limit());
clientChannel.write(buffer);
}
}
catch(java.nio.channels.UnresolvedAddressException ex)
{
log.info("L地址讉K无效\r\n" + ex.getMessage());
}
catch(IOException e)
{
// TODO Auto-generated catch block
try
{
if(remoteSvrChannel != null)
{
remoteSvrChannel.close();
}
}
catch(IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
}
catch(IOException e1)
{
// TODO Auto-generated catch block
try
{
if(clientChannel != null)
{
clientChannel.close();
}
}
catch(IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
finally
{
try
{
if(remoteSvrChannel != null)
{
remoteSvrChannel.close();
}
if(clientChannel != null)
{
clientChannel.close();
}
}
catch(IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 打印q程服务器返回给客户端信?br />// buffer.flip();
// byte[] b2 = new byte[buffer.limit()];
// buffer.get(b2);
// log.info(new String(b2));
// 关闭q程和客Lq接
}
public static String getRemoteHost()
{
return remoteHost;
}
public static void setRemoteHost(String remoteHost)
{
ProxyServer.remoteHost = remoteHost;
}
public static int getRemotePort()
{
return remotePort;
}
public static void setRemotePort(int remotePort)
{
ProxyServer.remotePort = remotePort;
}
public ByteBuffer getBuffer()
{
return buffer;
}
public void setBuffer(ByteBuffer buffer)
{
this.buffer = buffer;
}
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
ProxyServer p = new ProxyServer();
p.runServer();
}
}
while(true)
{
Socket client = null, server = null;
try
{
// {待客户q接
client = ss.accept();
log.info("*******Client logon*******");
log.info(client);
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
// q接真实的服务器,如果不能q接成功,向客户发送错误信?断开本次q接
// q且l箋{待q接.
try
{
server = new Socket(host, remoteport);
}
catch(IOException e)
{
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n");
out.flush();
client.close();
continue;
}
// 得到q接服务器的输入输出?
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
// 构徏一个单独线E读客户hq传l服务器,此线Eؓ异步.
Thread t = new Thread()
{
public void run()
{
int bytesRead;
String context = null;
try
{
while((bytesRead = streamFromClient.read(request)) != -1)
{
streamToServer.write(request, 0, bytesRead);
context = new String(request).trim();
streamToServer.flush();
}
// 打印客户览器发来的信息
log.info("#################S##############");
log.info(context);
log.info("#################E##############");
// 解析发来的信?获取h的主机地址和端?
proxyUtil.setUrl(context);
host = proxyUtil.getHost();
remoteport = proxyUtil.getPort();
log.info("host : '" + host + "'" + " port : '" + remoteport + "'");
}
catch(IOException e)
{
// e.printStackTrace();
}
// 关闭h服务器连?屏蔽无意义的异常,减少代理服务器负?
try
{
streamToServer.close();
}
catch(IOException e)
{
// e.printStackTrace();
}
}
};
// 开启客L到服务器hU程
t.start();
// L务器的请?成功后返回信息给客户?
int bytesRead;
try
{
while((bytesRead = streamFromServer.read(reply)) != -1)
{
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
}
catch(IOException e)
{
// e.printStackTrace();
}
// 关闭客户q接.
streamToClient.close();
}
catch(IOException e)
{
System.err.println(e);
}
finally
{
try
{
if(server != null)
{
server.close();
}
if(client != null)
{
client.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
System.out.println(redirect.lastIndexOf("></HEAD>"));
System.out.println(redirect.substring(redirect.indexOf("URL") + 4, redirect.lastIndexOf("></HEAD>") - 1));
redirect = redirect.substring(redirect.indexOf("URL") + 4, redirect.lastIndexOf("></HEAD>") - 1);
GetMethod getMethod = new GetMethod(" httpClient.executeMethod(getMethod);
buff = getMethod.getResponseBodyAsString();
}
catch(HttpException e)
{
// 发生致命的异常,可能是协议不Ҏ者返回的内容有问?br /> System.out.println("Please check your provided http address!");
e.printStackTrace();
}
catch(IOException e)
{
// 发生|络异常
e.printStackTrace();
}
finally
{
// 释放q接
postMethod.releaseConnection();
}
return buff;
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=678615
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=678260
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.ejb.EJBException;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class TextMDBBean
implements MessageDrivenBean, MessageListener {
private MessageDrivenContext ctx = null;
private QueueConnection conn;
private QueueSession session;
public TextMDBBean() {
System.out.println("TextMDB.ctor, this=" + hashCode());
}
public void setMessageDrivenContext(MessageDrivenContext ctx) {
this.ctx = ctx;
System.out.println("TextMDB.setMessageDrivenContext, this=" +
hashCode());
}
public void ejbCreate() {
System.out.println("TextMDB.ejbCreate, this=" + hashCode());
try {
setupPTP();
}
catch (Exception e) {
throw new EJBException("Failed to init TextMDB", e);
}
}
public void ejbRemove() {
System.out.println("TextMDB.ejbRemove, this=" + hashCode());
ctx = null;
try {
if (session != null) {
session.close();
}
if (conn != null) {
conn.close();
}
}
catch (JMSException e) {
e.printStackTrace();
}
}
public void onMessage(Message msg) {
System.out.println("TextMDB.onMessage, this=" + hashCode());
try {
TextMessage tm = (TextMessage) msg;
String text = tm.getText() + "processed by: " + hashCode();
Queue dest = (Queue) msg.getJMSReplyTo();
sendReply(text, dest);
}
catch (Throwable t) {
t.printStackTrace();
}
}
private void setupPTP() throws JMSException, NamingException {
InitialContext iniCtx = new InitialContext();
Object tmp = iniCtx.lookup("java:comp/env/jms/QCF");
QueueConnectionFactory qcf = (QueueConnectionFactory) tmp;
conn = qcf.createQueueConnection();
session = conn.createQueueSession(false,
QueueSession.AUTO_ACKNOWLEDGE);
conn.start();
}
private void sendReply(String text, Queue dest) throws JMSException {
System.out.println("TextMDB.sendReply, this=" +
hashCode() + ", dest=" + dest);
QueueSender sender = session.createSender(dest);
TextMessage tm = session.createTextMessage(text);
sender.send(tm);
sender.close();
}
}
<jboss>
<enterprise-beans>
<message-driven>
<ejb-name>TextMDB</ejb-name>
<destination-jndi-name>queue/B</destination-jndi-name>
<resource-ref>
<res-ref-name>jms/QCF</res-ref-name>
<jndi-name>ConnectionFactory</jndi-name>
</resource-ref>
</message-driven>
</enterprise-beans>
</jboss>
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import EDU.oswego.cs.dl.util.concurrent.CountDown;
/**
* A complete JMS client example program that sends N TextMessages to a Queue B
* and asynchronously receives the messages as modified by TextMDB from Queue A.
*
* @author Scott.Stark@jboss.org
* @version $Revision: 1.9 $
*/
public class SendRecvClient {
static final int N = 10;
static CountDown done = new CountDown(N);
QueueConnection conn;
QueueSession session;
Queue queA;
Queue queB;
public static class ExListener implements MessageListener {
public void onMessage(Message msg) {
done.release();
TextMessage tm = (TextMessage) msg;
try {
System.out.println("onMessage, recv text=" + tm.getText());
} catch (Throwable t) {
t.printStackTrace();
}
}
}
public void setupPTP() throws JMSException, NamingException {
InitialContext iniCtx = InitContext.getInitContext();
Object tmp = iniCtx.lookup("ConnectionFactory");
QueueConnectionFactory qcf = (QueueConnectionFactory) tmp;
conn = qcf.createQueueConnection();
queA = (Queue) iniCtx.lookup("queue/A");
queB = (Queue) iniCtx.lookup("queue/B");
session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
conn.start();
}
public void sendRecvAsync(String textBase) throws JMSException,
NamingException, InterruptedException {
System.out.println("Begin sendRecvAsync");
// Setup the PTP connection, session
setupPTP();
// Set the async listener for queA
QueueReceiver recv = session.createReceiver(queA);
recv.setMessageListener(new ExListener());
// Send a few text msgs to queB
QueueSender send = session.createSender(queB);
for (int m = 0; m < 10; m++) {
TextMessage tm = session.createTextMessage(textBase + "#" + m);
tm.setJMSReplyTo(queA);
send.send(tm);
System.out.println("sendRecvAsync, sent text=" + tm.getText());
}
System.out.println("End sendRecvAsync");
}
public void stop() throws JMSException {
conn.stop();
session.close();
conn.close();
}
public static void main(String args[]) throws Exception {
System.out.println("Begin SendRecvClient,now="
+ System.currentTimeMillis());
SendRecvClient client = new SendRecvClient();
client.sendRecvAsync("A text msg");
client.done.acquire();
client.stop();
System.exit(0);
System.out.println("End SendRecvClient");
}
}