| Denny's profileJava DreamsBlogLists | Help |
|
|
November 15 HttpURLConnection 访问页面时发生403问题。工作中发现一个问题。当我用HttpURLConnection去连接读取一个网站时,老是会发生这个403错误。这个引起了IOException,但是我用firefox访问这个网站时就没问题。 google后知道了答案。原来如果用java代码HttpURLConnection去连的话 http header 中的User-Agent就为空,解决方法就是在连接之前先设置这个属性。 URL myUrl = new URL(searchURL); 那台Server上要这么做, 可能是要组织一些网络机器人的访问(不过感觉不是很有用,用上面的方法就能破了)。 其实实现感觉也很简单, 加上一个Filter,判断如果request.getHeader("User-agent")为空的话,然后再response一个403 status就行。 November 07 晕,inputstream for get image from internet.需要网站的favicon保存到数据库中。思路很简单连接internet,然后得到图片的bytes保存到数据库的blob字段就行。但是我却在取到图片的bytes上面浪费了许多时间。 开始的代码如下 boolean fetched = false; URL url = null; try { url = new URL("http://" + channel.getSite().getHost() + "/favicon.ico"); HttpURLConnection httpURL = (HttpURLConnection) url.openConnection(); //httpURL.setConnectTimeout(60*1000); httpURL.connect(); if (httpURL.getResponseCode()==200){ InputStream is = httpURL.getInputStream(); int length = is.available(); byte[] bytes = new byte[length]; is.read(bytes, 0, length); Blob blob = Hibernate.createBlob(bytes); ((Image)image).setLocalSmallImage(blob); logger.debug("Image URL:[" + url + "] has been fetched."); logger.debug("read image size:" + length); fetched = true; } } catch (Exception e) { //ignored } if (!fetched) logger.debug("Fail to fetch Image URL:[" + url + "] "); 在本地上设置断点调试发现一切正常。 但是发不到服务器上却发现数据更本没有保存到进去,或者只保存进去一部分。奇怪!然后log了bytes的长度(logger.debug("read image size:" + length);)。发现这时候的长度为0。上面的代码肯定是有问题。 因为网络延时之类的这里的available根本就不准确。其实这里我们应该像读取一个文件,然后在把他写入另一个文件的操作是一样的。需要先用过inputstream read出bytes, 然后再通过outputstream把bytes输出。 但是这里我们不需要写到文件之类的datasource中。我们需要的只是bytes。我们可以方便的使用ByteArrayOutputStream来存储我们的bytes。 public static byte[] getAllBytes(InputStream in) throws Exception { int chunkSize = 4096; byte[] b = new byte[chunkSize]; int borb = -1; ByteArrayOutputStream fos = new ByteArrayOutputStream(); while ((borb = in.read(b)) != -1) { fos.write(b, 0, borb); } return fos.toByteArray(); } August 17 RSS Feed autodiscovery.使用一些浏览器的浏览某个页面时会提示你这个页面有那些Rss源。她时怎样做的呢?? 不过是在HTML里的<HEAD>部分里加一行代码,类似: <link REL="alternate" type="application/rss+xml" title="Default RSS1.0 feed" href="http://www.zhangyining.net/weblog/rss/rss.pl"/> 这行代码的作用就是告诉访问该页面的客户端程序(浏览器,RSS Reader,或者是RSS聚合 器)该页面提供RSS Feed以及该Feed的地址,这样,客户端程序可以直接反馈给用户提示用 户可以订阅的内容(例子:桌面或者基于浏览器的RSS Reader),或者自动聚合内容(例子 :RSS搜索引擎)。 Ok。 我用java实现这一功能。代码如下。。需要nekohtml-0.9.5.jar 和 xercesImple-2.6.2.jar /** * This function is Feed Autodiscovery, You just need passing the url, It would * return the feeds. * * Rule, gets the elements "<linke />", check the type attribute whether is rss-xml type, * if true, get the href attribute. * * @param url the page url that need to discovery * @return Feed list */ public static List<String> discoveryFeedList(String url){ List<String> rt = new ArrayList<String>(); if (StringUtils.isBlank(url)){ return rt; } DOMParser parser = new DOMParser(); try { parser.parse(url); }catch(Exception e){ // ignore the exception; just return empty value; return rt; } NodeList list = parser.getDocument().getElementsByTagName("link"); for(int i=0; i<list.getLength(); i++){ Node node = list.item(i); String rssurl = getRssUrl(node, url); if (StringUtils.isNotBlank(rssurl)){ rt.add(rssurl); } } return rt; } /** * dig rss url. * @param node * @return URL, if not found, return null. */ private static String getRssUrl(Node node, String url){ if (node == null || node.getAttributes().getLength() == 0){ return null; } // Map<attriName, attriValue> Map<String, String> attriMap = new HashMap<String, String>(); for(int i=0; i<node.getAttributes().getLength(); i++){ attriMap.put(node.getAttributes().item(i).getNodeName(), node .getAttributes().item(i).getNodeValue()); } String type = attriMap.get("type"); if (!StringUtils.isBlank(type) && (type.equalsIgnoreCase("application/rss+xml") || type.equalsIgnoreCase("application/atom+xml"))) { String href = attriMap.get("href"); if (!StringUtils.isBlank(href) && href.toLowerCase().startsWith("http")){ return href; }else{ return url.trim().endsWith("/") ? url + href : url + "/" + href; } } return null; } July 29 google hosting, host your code base.现在你只需要拥有一个gmail帐号, 便能host 你的项目, 象在sf上一样, 使用的是subversion. http://code.google.com/hosting/ July 13 还真的不知道,java里面可以 break [lable], continue [lable]outer: for(int i=0;i<2;i++){ inner:for(int j=0;j<2;j++){ if (j==1) break outer; System.out.println("i:" + i + " j:" + j); } } 上面那个代码,当j=1时,然后break outer。 这时候就会跳出高层的for(outer)。这里也可以改成continue outer; 这时候会i+1后从高层循环继续开始。 这是java的基础,但是我觉得大部分人还是不知道有这个东西的。 以前我跳出高层循环是设置一个boolean变量。 呵呵! while 语句同样适用。 http://dusu.mireene.com/java/flow.html June 04 透视java读书笔记(一)
使用反编译器能够把没有经过特殊处理的class文件还原成几乎和源码一样的java文件. 因为在class文件中几乎包括了一切可以用于调试的信息, 行号, 成员变量, 参数类型和参数名称 etc, 但是应该不包括javadoc和注释, 正应为这样你才能用现代的IDE方便的调试你的程序. 定位行, 单步执行, 审查值 etc. 如果我们在编译源码的时候加上-g:none选项, 反编译的代码就会损失一些清晰度. 例如方法参数名称和局部变量的名称等等.
2. 在java字节码中, 混淆是保护知识产权的最佳途径, 混淆执行如下一些或全部变换: 去除调试信息, 名称的处理, 编码字符串, 改变控制流程, 插入讹用的代码, 删除未使用的代码和优化代码. 混淆带来了维护的困难, 这可以通过配置混淆程序将其减到最小. 混淆的代码仍旧可读, 除非使用了控制流程的混淆和字符串编码.
当变量或方法没有用可视性关键字(public protected private)声明时, 就是package visible的. 假如一个包中的某个类有个package visible的属性, 但是他又没有提供getter方法给你, 你又想获得这个属性的值, 那我们可以在这个包中加一个助手方法. 为这个package visible的属性提供一个getter方法. 不过当那个包是系统包时, 可能会发生SecurityException. 我们下面会讨论这个.
这里要注意的是, 如果设置了安全管理器(大多数应用服务程序和中间产品通常都是这样), 那么我们还需要多做一些工作, 要不就会发生RumtimePermission发生. 为了让我们的代码能和已安装的安全管理器协同工作, 必须准予通过反射访问声明的成员以及禁止访问检查的许可, 这通过添加准予code base这两种许可java政策文件的方式来实现: grant { permission java.lang.RuntimePermission “accessDeclaredMembers”; permission java.lang.reflect.ReflectPermission “suppressAccessChecks”; }; 在java command中加上 -Djava.security.manager –Djava.security.policy=../conf/java.policy April 18 public static final long MONTH_IN_MILLIS = 30*24*60*60*1000public static final long MONTH_IN_MILLIS = 30*24*60*60*1000; 一看就明白这个是定义一月大概的微妙数. 当我在计算两个月之间大概的月的个数时, 总是发现他返回一个负数, 奇怪, 后面调试发现 MONTH_IN_MILLIS = -1702967296. 呵呵, 原来overflow了. public static final long MONTH_IN_MILLIS = (30l)*24*60*60*1000;改成这样就ok了. March 31 Clustering using Tomcat在Without Ejb第四章中有段对EJB的分布化和可扩展性的讨论: 在人们中间有一个广为传播的信念: 分布式应用系统是高度可扩展的.这种观点认为,可以使用4个web容器, 8个ejb容器所有的业务都通过web层远程调用.这样就可以得到非常好的扩展行. 然后作者在下文中批判了这种观点.每次远程方法调用造成的性能代价太过高昂,以至于在理论上还有什么 收益的化,早也被网络传输或对象编组中的损失给大大超过了. 作者建议的是对整个应用系统进行集群式部署. 然后在运用硬件负载均衡或web容器的负载均衡来分流访问. 集群是个诱惑的名字. 今天花了一上午了解了如何在Tomcat中实现集群. 还不错, 当在Tomcat官方网站上看了集群的文章时, 感觉并不是很难, Tomcat5.X已经把集群内嵌了. 配置也瞒简单的, Tomcat是用多波包(multicast)的方式去发现其他的节点,其他节点回返回IP 和 端口, 以提供session的复制. 所以放在session里面的对象一定要实现序列化, 当在一定的时间内没有收到某个节点返回值时, 那个节点就判定死了. 还有就是要怎样实现load balancing , 你要怎样分发请求(request)到集群节点(Node)去, 这里也有许多方法, 我看的是用Servlet Filter去做这件事的(参考下面网站的例子). 集群能给我们带来很多好存, 性能的可扩展性, 可以关掉几台Node, 而系统不受影响. 今天在Javalobby看到一个关于集群的一个trick. 假如在一台node中的session中存有一个List对象. 如果你是这样使用的话, List l = (List)session.getAttribute("list"); l.add("Denny"); 这个session不会引发session复制. 所有你还需要把这个List set回session中. If you have an ArrayList in the session representing shopping cart objects and if you just call getAttribute() to retrieve the ArrayList and then add or change something without calling the setAttribute(……………) then the container may not know that you have added or changed something in the ArrayList. So the session will not be replicated. ok 就讲这么多了. 官方指南 http://tomcat.apache.org/tomcat-5.5-doc/cluster-howto.html 下面的这个不错, 带了一个例子, 自己实现了两个load balancing的算法. 用的是Filter Clustering and Load Balancing in Tomcat 5, Part 1http://www.onjava.com/pub/a/onjava/2004/03/31/clustering.html?page=1Clustering and Load Balancing in Tomcat 5, Part 2http://www.onjava.com/pub/a/onjava/2004/04/14/clustering.html?page=1March 29 Essential Skills for Agile Development感谢小刚提供这本给我, 非常不错. http://www.agileskills2.org/ESAD.pdf February 28 在eclipse里使用Embeded tomcat进行web项目开发和调试1) 从http://apache.justdn.org/tomcat/tomcat-5/v5.5.15/bin/apache-tomcat-5.5.15-embed.zip 下载Tomcat的Embeded版本。
2) 在eclipse里建一个java project(Tomcat Startup)。然后把从1)下载的tomcat解压到这个Tomcat Startup project中把Tomcat Startup/lib下所有的lib加到eclipse的Liberaries。(把Tomcat Startup/lib下所有的lib加到eclipse的Liberaries。)。如下图所示:
import java.io.File; import org.apache.catalina.Context; public class EmbeddedTomcat { private String path = null; } /** this.path = path; /** return path; /** // Create an embedded server // Create an engine // Create a default virtual host // Create the ROOT context // Assemble and install a default HTTP connector /** public static void main(String args[]) { try { EmbeddedTomcat tomcat = new EmbeddedTomcat(); e.printStackTrace(); 对其中tomcat 基础的介绍请看http://www.onjava.com/lpt/a/1547。在我的这个启动类中向tomcat中添加两个context, 一个tomcat root context, 另一个是在我的eclipse里面的一个web project。 // Create the ROOT context 假如要能认出eclipse的java project是一个web project, 你需要把你的web project的context做成发布时一样就行(本例中的context时score), 然后在eclipse中改变build path:如下图:
4) 优点: 使用这种方式启动tomcat非常快, 而且更干净, 占用更少的memory。 相比下比 Myeclipse插件快很多(本人用的最多的也是Myeclipse的app server deployment 和 jsp xml editor)。而且myeclipse是在你每次保存文件时把这个文件考到对应的webapps下你的project下面。 使用这种方式还少了拷贝文件。 5) 在实际操作时当我浏览score时, 发生了找不到一些lib的错误。 一个log4j还有一个是commons-el.jar(在TOMCAT_HOME/common\lib里面这里的tomcat不是emebed版本的),把这两个lib考到Tomcat Startup/lib文件夹下, 然后再把他们add到eclipse的Liberaries中。 February 01 解决sourceforge连不上的问题.sourceforge这几天都连不上, 不知道是不是国内封杀了.
please try this. http://anonymouse.org/
or http://prdownloads.sourceforge.net/ + project name. example: I want to download hibernate try this .. http://prdownloads.sourceforge.net/hibernate January 18 Tomcat类装载的问题.昨天发布一个web application的时候发现一个奇怪的问题, 明明jar包里面有的类说找不到, 真是奇怪. 不过要下班了. 明天再说吧. java.lang.NoClassDefFoundError: com/netsboss/util/dbobject/GeneralEntity 添加一些: 这个是自定义的classloader, 他在构着函数里面没有传他的parent classloader(tomcat Webapp classloader)进去, 所以他的parent classloader是systemclassloader, 具体代码看java.lang.ClassLoader. /** /** package com.netsboss.util.proxy; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.util.HashMap; import org.apache.log4j.Category; public class ProxyClassLoader extends ClassLoader {private static Category log = Category.getInstance(ProxyClassLoader.class); private HashMap classes = new HashMap(); private boolean saveToClassPath = false; public ProxyClassLoader(boolean saveToClassPath){this.saveToClassPath = saveToClassPath; } /** * @see ClassLoader#findClass(String) */ protected Class findClass(String name) throws ClassNotFoundException {Class find = super.findClass(name); if(find != null) return find; find = (Class)classes.get(name); if(find != null) return find; else throw new ClassNotFoundException(name); } public void defineClass(byte classfile[], String classname){Class clazz = defineClass(classname, classfile,0, classfile.length); classes.put(classname,clazz); if(saveToClassPath){saveToClassPath(classfile, classname); } } /** * return a class which implements all the interfaces or inherit from one of class * currently, just return null. */ public Class search(Class interfaces[]){return null; } private void saveToClassPath(byte classfile[], String classname){String filename = classname + ".class"; URL url = getClass().getProtectionDomain().getCodeSource().getLocation(); if( "file".equals(url.getProtocol()) && (url.getHost() == null || url.getHost().equals("")) ){String dir = null; try{File classpath = new File(dir); if(classpath.isDirectory() == false){ log.info("Classpath error for ProxyClassLoader:" + dir + " not a directory");return; } File file = new File(classpath, filename); try {FileOutputStream os = new FileOutputStream(file); os.write(classfile); os.close(); } catch(IOException ex){} } } } 参考这篇文章 http://www.cjsdn.net/post/view?bid=29&id=162060&sty=1&tpg=1&age=0 January 04 Usefull swing component-Auto complete combobox.Record this component. do some deeply research on it, if I have time. it will make you be familiar with Swing componect structure. December 22 Java Nt Service.在FSI项目中, 客户说要把JNDIServer, CalcManager做成Windows Service. 这个想法不错. 一开机就能自动运行. 以后也不用一个一个去启动JNDIServer, CalcManager了.
网上找到了http://javaservice.objectweb.org/ 一个制作javaService的工具. download, 里面有一些sample 和 document.
FSI中使用了
set JAVA_DLL="C:\Program Files\Java\jdk1.5.0_03\jre\bin\server\jvm.dll"
set SERVICE_NAME=CalcService set START_CLASS=com.fsillc.remote.server.CalculatorServiceImpl set CP="C:\AFTPrograms\FSI_JNDI.542\fsillc.jar" set WORK_DIR="C:\AFTPrograms\FSI_JNDI.542" JavaService.exe -install %SERVICE_NAME% %JAVA_DLL% -Djava.class.path=%CP% -Xmx756M -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3999,suspend=n -start %START_CLASS% -method main -out %WORK_DIR%\CalcServer.log -err %WORK_DIR%\CalcServerErr.log -current %WORK_DIR% November 29 A common log sample.# Log4j configuration file. # Available levels are DEBUG, INFO, WARN, ERROR, FATAL #
log4j.appender.Z=org.apache.log4j.RollingFileAppender log4j.appender.W=org.apache.log4j.RollingFileAppender
November 07 Java 平台调试架构( Java Platform Debugger Architecture , JPDA )一直以为java调试是IDE一方的事,以为调试都是IDE自己实现的。知道看了篇文章后才知道不是这样子。http://www.eclipsezone.com/eclipse/forums/t53459.html
我们要调试一个java程序,我们需要在运行参数前加上
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044 这些参数的具体意义看。http://java.sun.com/products/jpda/doc/conninv.html#Invocation
如:java -classpath E:\Eclipse_WorkSpace\Eclipse_Work\Test\classes;E:\Eclipse_WorkSpace\Eclipse_Work\Test\lib\log4j-1.2.8.jar;E:\Eclipse_WorkSpace\Eclipse_Work\config\lib\msbase.jar;E:\Eclipse_WorkSpace\Eclipse_Work\config\lib\mssqlserver.jar;E:\Eclipse_WorkSpace\Eclipse_Work\config\lib\msutil.jar;E:\Eclipse_WorkSpace\Eclipse_Work\Test\lib\fscontext.jar;E:\Eclipse_WorkSpace\Eclipse_Work\Test\lib\providerutil.jar -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,suspend=y,address=localhost:1516 com.dengyin.rmi.HelloWorld
JPDA 是一套组成构建调试应用程序框架的 API 。幸运的是,我们大多数人不需要自己考虑创建调试应用程序的事,因为这些是与主要的 IDE 捆绑在一起提供的。调试在这些新的 IDE 中是一个相当简单和轻松的过程。
当我们用eclipse去调试一个java程序的时,确实也是这样。
当我们不是用eclipse运行java程序时,我们可以用eclipse的remote debug去调试, 只要我们知道这个java程序的源代码和java程序debug的端口。
我们需要在运行的java程序参数上加上-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044 类似的参数。然后用eclipse去调试就行了。 具体请看http://www.eclipsezone.com/eclipse/forums/t53459.html
November 01 Read/Write Lockpublic class SomeContainer {
private Set<Element> elements;
private ReadWriteLock globalLock;
private Lock readLock;
private Lock writeLock;
SomeContainer() {
elements = new HashSet<Element>();
globalLock = new ReentrantReadWriteLock();
readLock = globalLock.readLock();
writeLock = globalLock.writeLock();
}
public void addElement(Element elem) {
writeLock.lock();
try {
elements.add(elem);
}
finally {
writeLock.unlock();
}
}
public void processElements(ElementProcessor processor) {
readLock.lock();
try {
Iterator<Element> iter = elements.iterator();
while(iter.hasNext()) {
Element element = iter.next();
processor.processElement(element);
}
finally {
readLock.unlock();
}
// ...
}
interface ElementProcessor {
void processElement(Element element);
}
So, in the example above, the first line in
October 13 Runtime.getRuntime().addShutdownHook(new ShutdownThread()) Hook方法。在看公司的代码时,发现一段奇妙的代码。
情景:
1) CalcManager 用command line运行。他能够产生Calculator Process。
2) Calculator Process Sevice进程, 以Window 进程的形式存在。
需求:
CalcManager 能够管理他生长的Calc Process。 也就是说CalcManagerShutdown的时候Calc Process也要能自动Shutdown。
如果我们提供一个exit的button在GUI上面的话 上面实现起来非常顺, 在exit 的action上先Shutdown这些Calc Process 然后在 System.exit(0), 但是假如用户不小心在Command 窗口上按了Ctrl + c的话或者在Task Manager上killCalcManager进程的话,那么 Kill Calc Process这个机会就没有。
Java提供了这个问题的解决方案public void addShutdownHook(Thread hook)。 当java虚拟机推出的时候回调用hook Thread里面的run方法,也就是运行那个hook线程。 Hook经常被叫着钩子方法。
其实这种应用也不少。 想Ms Word 在编辑时 都会Open一个临时文件,不知道大家有没有注意。我们可以试试通过Task Manager去Kill Word的进程, 这时这个临时文件应该也会被Clean掉的。
Runtime.getRuntime().addShutdownHook(new ShutdownThread()) Hook方法。在看公司的代码时,发现一段奇妙的代码。
情景:
1) CalcManager 用command line运行。他能够产生Calculator Process。
2) Calculator Process Sevice进程, 以Window 进程的形式存在。
需求:
CalcManager 能够管理他生长的Calc Process。 也就是说CalcManagerShutdown的时候Calc Process也要能自动Shutdown。
如果我们提供一个exit的button在GUI上面的话 上面实现起来非常顺, 在exit 的action上先Shutdown这些Calc Process 然后在 System.exit(0), 但是假如用户不小心在Command 窗口上按了Ctrl + c的话或者在Task Manager上killCalcManager进程的话,那么 Kill Calc Process这个机会就没有。
Java提供了这个问题的解决方案public void addShutdownHook(Thread hook)。 当java虚拟机推出的时候回调用hook Thread里面的run方法,也就是运行那个hook线程。 Hook经常被叫着钩子方法。
其实这种应用也不少。 想Ms Word 在编辑时 都会Open一个临时文件,不知道大家有没有注意。我们可以试试通过Task Manager去Kill Word的进程, 这时这个临时文件应该也会被Clean掉的。
|
|
|