|
2005年11月13日
有个输家,就一定有个赢家。我是输家,但我四周望了一圈,却没看到半个赢家,我想,赢家应该也是我了,你说呢?
vi命令是unix下常用而重要命令,可在全屏幕方式下编辑一个或多个文件。若在vi执行时 没有指定一个文件,那么vi命令会自动产生一个无名的空的工作文件。若指定的文件不存在, 那么就按指定的文件名创建一个新的文件。若对文件的修改不保存的话,v i命令并不改变原 来文件的内容。
注意:vi命令并不锁住所编辑的文件,因此多个用户可能在同时编辑一个文件,那么最后 保存的文件版本将被保留。 下面是vi命令使用的一些选项及含义: -c sub-command 在对指定的文件编辑前,先执行指定的命令 sub-command . -r filename 恢复指定的文件filename . -R 将指定的文件以只读的方式放入编辑器中,这样不会保存对文件的任何修 改。 -y number 将编辑窗口的大小设为number行。 下面是vi编辑所处的三种模式: .命令模式 进入vi时所处的模式。在此模式下用户可输入各种子命令对进行*作,如删除行、 粘贴行、移向下一个字、移向不同行等。 .文本输入模式 在此模式下可以修改一行的内容并增添新行。在命令模式下键入a 、i 或 c键可进入文本输入模式,按Escape键可返回命令模式。 .命令项模式 在此模式下,可以通过子命令输入更多的参数。如:w子命令要求输入一文 件名,"/"子命令要求输入一个查找项。用户使用Escape键返回命令模式。 下面是自命令模式下执行的,在同一行上移动的自命令:
h 将光标左移一格。 l 将光标右移一格。 j 将光标下移一格。 k 将光标上移一格。 w 将光标移到下一个小字的前面。 W 将光标移到下一个大字的前面。 b 将光标移到前一个小字的前面。 B 将光标移到前一个大字的前面。 e 将光标移到下一个小字的后面。 E 将光标移到前一个大字的后面。 fc 把光标移到同一行的下一个c字符处。 Fc 把光标移到同一行的前一个c字符处。 tc 把光标移到同一行的下一个字符c的前一格。 Tc 把光标移到同一行的前一个字符c的后一格。 number| 把光标移到递number列上。 下面是命令模式下在行间移动的子命令: +或Enter 把光标移至下一行第一个非空白字符。 - 把光标移至上一行第一个非空白字符。 0 把光标移到当前行的第一个字符处。 $ 把光标移到当前行的最后一个字符处。 H 把光标移到屏幕最顶端一行。 L 把光标移到屏幕最底端一行。 M 把光标移到屏幕中间。 下面是命令模式下改变屏幕显示的子命令: z- 把当前行作为屏幕的最后一行,并重新显示屏幕。 z. 把当前行作为屏幕的中间一行,并重新显示屏幕。 Ctrl+l 重新显示屏幕当前内容。 /pattern/z- 寻找pattern的下一个位置,并把所在行设为屏幕的最后一行。 下面是在命令模式下用来显示页面的子命令: Ctrl + f向后滚一页。 Ctrl + d向后滚半页。 Ctrl + b向前滚一页。 Ctrl + u向前滚半页。 Ctrl + e屏幕向下滚一行。 Ctrl + y屏幕项上滚一行。 下面是在命令模式下用来查找字符串所使用的子命令: /pattern 向后寻找指定的pattern ,若遇到文件尾,则从头再开始。 ?pattern 向前寻找指定的pattern ,若遇到文件头,则从尾再开始。 n 在上次指定的方向上,再次执行上次定义的查找。 N 在上次指定的方向的相反方向上,再次执行上次定义的查找。 /pattern/+number 将光标停在包含pattern的行后面第number行上。 /pattern/-number 将光标停在包含pattern的行前面第number行上。 % 移到匹配的"()"或"{}"上。 下面是在文本输入模式下用来输入文本的子命令(用户可在任何时候按Escape返回到命令模式): a 在光标之后开始输入文本。 A在行尾开始输入文本。 i在光标之前开始输入文本。 I在行首第一个非空白字符前输入文本。 o在光标所在行后插入一空行。 O在光标所在行前插入一空行。 下面是在命令模式下改变文本所使用的子命令(用户可在任何的时候按Escape键返回到命令模式): cc或S 修改一整行。 C 改变一行光标位置以后的部分。 cw 改变光标所在单词。 dd删除当前行。 D 删除光标所在行光标后面的内容。 dw删除光标所在的单词。 J 把下一行内容加到本行行尾。 rc把光符所在字符替换成c . R 覆盖本行内容。 u恢复上一次的修改。 x删除光标所在的字符。 ~ 改变光标所在出字符的大小写。 . 重复上一个*作。 <<把当前行移到左边。 >>把当前行移到右边。 下面是用于文件中拷贝文本的字命令: p 将缓冲区内容取到光标所在行的下面一行。 P 将缓冲区内容取到光标所在行的上面一行。 "bd 将文本删除至有名缓冲区b . "bp 张贴有名缓冲区b中内容。 yy把当前行放入缓冲区。 Y 把当前行放入缓冲区。 Yw把光标所在的单词放入缓冲区。 下面是用于保存文件的子命令: :w 回写修改后的文件。 :w filename 当filename不存在时,把修改后的文件存为文件filename ,当文件filename 存在时,报错。 !w filename 如果文件filename存在时,把修改后的文件保存为文件filename . 下面列出了在vi编辑的多个文件之间切换所用的子命令: :n开始编辑vi激活的文件列表中的下一个文件。 :n filenames 指定将被编辑的新的文件列表。 下面列出了用于在当前文件和另外一个文件间切换的子命令: :e filename 使用filename激活vi (在vi中装入另一个文件filename)。 e!重新装入当前文件,若当前文件有改动,则丢弃以前的改动。 :e+filename 使用filename激活vi ,并从文件尾部开始编辑。 :e+number filename 使用filename激活vi ,并在第number行开始编辑。 :e# 开始编辑另外一个文件。 下面是在本文件中加入其他文件代码所使用的子命令: :r filename读取filename文件,并将其内容加到当前文件后。 :r ! command执行command文件,并将其输出加到当前文件后。 下面是vi中其他的子命令: ctrl+g 取得正在编辑文件的有关信息。 :sh启动sh ,从sh中返回可用exit或ctrl+d . :! Command 执行命令command . !!重新执行上次的:! Command子命令。 :q退出vi ,若用户对编辑的文件有所修改,系统不会让用户使用q命令退出。 :q!退出vi而不管是否对文件有改动。 ZZ或:wq 保存对文件的修改并退出vi . 用户可在一个特殊的文件.exrc中定义特殊的vi命令。在vi中使用这些命令时,必须在该 命令前加上一个冒号( :) 。
log4j虽然总的来说是比较容易使用的,但是要是想比较精通的操纵它还是有很多地方值得探讨的。 这几天有空,把项目中大家用到的log4j实现的功能分了一下类,大致分为下面三类: <1>所有的日志信息都输出到log.log. <2>对于一些特殊的日志(如启动时候的日志),输出到log/startup/startup.log. <3>对于某些特殊包下面的日志,如com.aspire包下面的error信息都输出到error.log 有了这几个功能,相信对于大部分的系统都是够用的了,下面这个例子就是实现了这几个功能: (至于其他的一些配置,如格式这些的就不说明,有很多这种资料) *********** log4j 配置文件 ************ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" threshold="debug">
<appender name="file" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="log.log"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value=" %d{ISO8601} [%c]- %m%n"/> </layout> </appender>
<appender name="error" class="org.apache.log4j.RollingFileAppender"> <param name="File" value="error.log"/> <param name="MaxBackupIndex" value="300"/> <param name="Encoding" value="GB2312"/> <param name="MaxFileSize" value="20MB"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{ISO8601} %p [%c] - [%m]%n"/> </layout> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <!-- 过滤,只记录error信息--> <param name="LevelMin" value="error"/> <param name="LevelMax" value="error"/> <param name="acceptOnMatch" value="true"/> </filter> </appender> <appender name="startup" class="com.aspire.TimeSizeRollingFileAppender"> <!--该类使自己从FileAppender派生,可以自己控制输出文件的路径 --> <param name="File" value="log/startup/startup.log" /> <param name="Encoding" value="GBK" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%m %d{ISO8601}- %m%n %p %l%n" /> </layout> </appender>
<logger name="biz.startup"> <!--Logger logger = Logger.getLogger("biz.startup") 可以这样来调用本logger--> <level value="debug" /> <appender-ref ref="startup" /> </logger>
<logger name="com.aspire" additivity="false"> <!--Log log = LogFactory.getLog(TestLog4j.class) 此时如果TestLog4j 位于com.aspire包下面,那么使用本logger --> <level value="debug"/> <appender-ref ref="error"/> </logger> <root> <level value="info"/> <!-- 默认输出到log.log--> <appender-ref ref="file"/> </root> </log4j:configuration>
*********** log4j 配置文件结束 ************
********** 派生的TimeSizeRollingFileAppender类***** package com.aspire;
import org.apache.log4j.FileAppender; import org.apache.log4j.spi.ErrorCode; import java.io.File; import java.io.IOException;
public class TimeSizeRollingFileAppender extends FileAppender implements ErrorCode {
private final static String FS = System.getProperty("file.separator"); public TimeSizeRollingFileAppender() { } public void setFile(String file) { String val = file.trim(); File domain = new File("."); try { fileName = domain.getCanonicalPath() + FS + val; } catch (IOException ex) { ex.printStackTrace(); } } }
********** TimeSizeRollingFileAppender 类结束 ******
************ 调用示例 TestLog4j类 ************** package com.aspire;
import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import org.apache.commons.logging.LogFactory; import org.apache.log4j.xml.DOMConfigurator; import org.apache.commons.logging.Log;
public class TestLog4j { private Logger logger = Logger.getLogger("biz.startup"); private Log log = LogFactory.getLog(TestLog4j.class);
public static void config(){ DOMConfigurator.configure("conf\\log4jConf.xml"); } public void Test(){ /** * error > warn > info > debug */ logger.error("*****error*****"); logger.debug("****debug*****"); logger.warn("*****warn******"); logger.info("*****info******"); log.error("中华之崛起!"); } public static void main(String [] argv){ TestLog4j t = new TestLog4j(); TestLog4j.config(); t.Test(); } }
*************** TestLog4j end ***********
很多时候,创建对象的时候,只是在某些属性值上有区别,而大部分都很相似,但是这样的对象的初始化相对来说比较复杂,而且 需要耗费较长的时间或资源,这种情况下,我们可以考虑使用Prototype模式。我觉得这种模式实用于这样的情况:如果该类的用户对于该 类的对象是怎么创建的,对类的内部结构这些都不关心的情况,并且该类的创建过程比较费时或资源时,可以考虑使用该模式。下面是该模式的 一个例子:
Prototype 类
package com.moonsoft;
import java.lang.Cloneable; public class Prototype implements Cloneable { public String myname; Prototype(){ System.out.println("start:"+System.currentTimeMillis()); for( int i=0; i< 9999999; i++){ } System.out.println("end:"+System.currentTimeMillis()); } public Object clone(){ Object o = null; try{ o = super.clone(); } catch(CloneNotSupportedException ex){ ex.printStackTrace(); } return o; } public void whoami(){ System.out.println(myname); } }
测试类
package com.moonsoft;
public class Test { public static void main(String [] argv){ Prototype p = new Prototype(); p.whoami(); p.myname = "loucy"; Prototype p1 = (Prototype)p.clone(); p1.whoami(); } }
如果一直为jsp的缓存问题困扰的话,可以试试在jsp中加入以下几句话:
<head> <meta http-equiv="Cache-Control" content="max-age=0" forua="true" /> <meta http-equiv="Cache-Control" content="no-cache" forua="true"/> <meta http-equiv="Cache-Control" content="must-revalidate" forua="true" /> </head>
max-age=30 就表示缓存的最长存在时间是30s,no-cache表示无缓存,must-revalidate表示每次访问必须重新验证是否有更新!
马上就要开始转到新的项目组,做一个全新的项目了,对于HTTP协议需要一定的了解,所以周末自己用Java写了一个简单的web服务器试试,只能实现简单的html文件浏览。
主要包括三个类:WebServer(监听浏览器请求),SocketThread(处理浏览器请求的进程),StringUtil(实现一些公共的操作),下面是三个类的代码.
----WebServer---- import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;
public class WebServer { public static void main(String[] argv) throws IOException { ServerSocket servSocket = new ServerSocket(StringUtil.LISTENING_PORT); try { while (true) { Socket socket = servSocket.accept(); new SocketThread(socket).start(); } } finally { servSocket.close(); } } }
---SocketThread------
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.Writer; import java.net.Socket;
public class SocketThread extends Thread { private Socket socket = null;
public SocketThread(Socket s) { this.socket = s; }
public void run() { try { if (socket == null) { throw new Exception("==>SOCKET为空<=="); } BufferedReader reader = new BufferedReader(new InputStreamReader( socket.getInputStream())); String fileName = ""; while (true) { String str = reader.readLine(); if (str == null || str.length() <= 0) { break; } //System.out.println("===>"+str); if (StringUtil.isGetRequestInfo(str)) { fileName = StringUtil.getFileName(str); break; } } //System.out.println("===>客户机IP==>"+socket.getInetAddress().toString()); //System.out.println("===>客户机端口==>"+socket.getPort()); /* BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); */ PrintStream outputStream = new PrintStream(socket.getOutputStream()); File file = new File(StringUtil.WEBPATH + fileName); if (file.exists()) { //如果文件存在 StringUtil.sendHttpHead(outputStream, file); StringUtil.sendFile(outputStream, file); outputStream.flush(); } else { //文件没找到,返回404页面 StringUtil.send404Page(outputStream); outputStream.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { try { socket.close(); } catch (Exception e) { } } }
}
---StringUtil-----
import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.PrintStream;
/** * @author xiaoliang */ public class StringUtil {
// 服务器监听的端口 public static final int LISTENING_PORT = 8080;
// 服务器文件的位置 public static final String WEBPATH = "E:";
/** * 判断该字符串是不是浏览器发送过来的请求头信息 * @param str * @return */ public static boolean isGetRequestInfo(String str) { if (str == null || str.length() <= 0) return false; boolean isGetStr = true; if (str.indexOf("GET") != 0) { isGetStr = false; } if (str.indexOf("HTTP/") <= 0) { isGetStr = false; } return isGetStr; }
/** * 获得请求信息中的文件名,默认为index.html * * @param str * @return */ public static String getFileName(String str) { String fileName = "index.html", s; int httpIndex = str.lastIndexOf("HTTP/"); s = str.substring(3, httpIndex); s = s.trim(); if (s != null && s.length() > 0 && s.indexOf(".") > 0) { fileName = s; } return fileName; }
/** * 发送文件到客户端 * * @param out * @param file */ public static void sendFile(PrintStream out, File file) { try { DataInputStream in = new DataInputStream(new FileInputStream(file)); int length = (int) file.length(); byte[] buffer = new byte[length]; in.readFully(buffer); out.write(buffer, 0, length); in.close(); } catch (Exception e) { e.printStackTrace(); } }
/** * 发送返回的头部信息 * @param out */ public static void sendHttpHead(PrintStream outputStream, File file) { try { outputStream.println("HTTP/1.0200OK"); outputStream.println("Content_Type:text/htm1"); outputStream.println("Content_Length:" + file.length()); outputStream.println("Server:moon webserver 1.0"); outputStream.println(""); } catch (Exception e) { e.printStackTrace(); } }
/** * 返回404页面 * @param out */ public static void send404Page(PrintStream out) { try { out.println("HTTP /1.0 404 no found"); out.println("Content_type:text/html"); out.println(""); out.println("Error404:file not found!"); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] argv) { String str = "GET /11.html HTTP/1.1"; str = StringUtil.getFileName(str); System.out.println("==>" + str + "<=="); File file = new File(StringUtil.WEBPATH + str); if (file.exists()) { System.out.println("exists"); } else { System.out.println("not exists"); } }
}
FileUpload 组件使用注意: 1> 首先创建一个HTML页面。注意,凡是要上载文件的表单都必须设置enctype属性,且属性的值必须是multipart/form-data,同时请求方法必须是POST. <form name="myform" action="fileuploaddemo.jsp" method="post" enctype="multipart/form-data"> 2>commons-fileupload-1.1.jar和commons-io-1.1.jar 两个包都要引入, 因为在parseRequest(request)的类有关继承于DiskFileItem类。
3>示例 //检查表单是否正确 boolean isMultipart = FileUpload.isMultipartContent(request); DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); //文件最大,设为-1表示不受限制 upload.setSizeMax(4096); //解析请求,把解析的结果放在一个List里面 List items = upload.parseRequest(request); //缓存大小,设为-1表示不受限制 factory.setSizeThreshold(4096); //设置临时目录 factory.setRepository(new File("D:\\temp")); Iterator iter = items.iterator(); while( iter.hasNext() ){ FileItem item = (FileItem)iter.next(); //检查是一个普通的表单域还是File组件 if( !item.isFormField() ){ System.out.println("FileName:==>"+item.getName()); System.out.println("FieldName:==>"+item.getFieldName()); System.out.println("Size:==>"+item.getSize()); //item.getName 返回的是完整的文件名,如:E:\\xx\11.doc //所以这里用一个fullFile来取文件名 File fullFile = new File(item.getName()); File uploadedFile = new File("D:\\ftp\\",fullFile.getName()); item.write(uploadedFile); } }
从一个表users中查询记录,如果是写成 select i from users as i where i.name=?1则编译EJB的时候会报错,但是如果把users 首字母大写就OK了。 select i from Users as i where i.name=?1
在EJB容器中,SessionBean主要有两种:无状态(stateless)和有状态(stateful)。 1、无状态EJB,类似Servlet,它只提供一个引用(Bean instance),被所有客户端使用,不保留某个客户的单独信息。 例如:在某无状态EJB中,有一个数据成员(变量) i_count (整型,用于访问计数,初始值为0,访问一次累加1),它是公共的。某客户端访问后,值累加为1。另一个客户端访问时是已经变化了的值为1。
2、有状态EJB,类似数据库的Connect链接,也类似线程守护,它提供引用池(Bean instance pool),每个客户端会有单独的信息。 例如:在某有状态EJB中,有一个数据成员(变量) i_count (整型,用于访问计数,初始值为0,访问一次累加1),它对每个客户端来说是隔离的。某客户端访问后,值累加为1。另一个客户端访问时还是原来的值为0。
这里提到的数据成员(变量) i_count ,在EJB规范中称作:conversational state 。对它的要求也很多的,例如类型为 Serializable objects。还有,还要在ejbActivate(),ejbPassivate(),ejbRemove()等生命周期约定的方法中处理。详见EJB规范吧。
我的感想:在看第一遍书时,还一点感觉都没有,根本就看不明白SessionBean中的session与Servlet容器中的session有什么区别。 动手编程后,才感觉到EJB只是比Servlet更规范,更重量而已。真正的区别就是接口协议一个是基于HTTP,一个是基于RMI/IIOP。Servlet与无状态的SessionBean在Session上是一样的控制。Servlet中的Session对象与有状态的SessionBean是一样的控制。 对于应用,例如有一个购物车,要记录正在采购的物品信息,没有EJB时,我们一般是存在Servlet容器中的session中。有了EJB,则可以存储在有状态的SessionBean中,并且该次有状态的sessionBean的instance还得保存在Servlet的session中。这样的好处是:至少可以减轻Servlet容器的负载。
转自: http://zengabo.blogchina.com/blog/527365.html
1.将ibatis 的jar 包添加到工程中
2.先新建一个xml文件 SqlMap.xml,在这个文件中定义使用了哪些ibatis资源文件 <?xml version="1.0" encoding="gb2312"?> <!DOCTYPE sql-map-config PUBLIC "-//iBATIS.com//DTD SQL Map Config 1.0//EN" "http://www.ibatis.com/dtd/sql-map-config.dtd"> <sql-map-config> <sql-map resource="com/montersoft/ibatis/common/monter.xml"/> </sql-map-config>
3.定义资源文件monter.xml <?xml version="1.0" encoding="gb2312"?> <!DOCTYPE sql-map PUBLIC "-//iBATIS.com//DTD SQL Map 1.0//EN" "http://www.ibatis.com/dtd/sql-map.dtd"> <sql-map name="monter"> <result-map name="monterInfo" class="java.util.HashMap"> <property name="id" column="id" type="VARCHAR"/> <property name="name" column="name" type="VARCHAR"/> <property name="age" column="age" type="NUMBERIC"/> </result-map> <dynamic-mapped-statement name="monter_getByPk" result-map="monterInfo"> select id,name,age from monter where id = #id# </dynamic-mapped-statement> </sql-map>
**注意dynamic-mapped-statement的name 必须唯一
4.定义一个公共类来生成SqlMap package com.montersoft.ibatis.common; import java.io.Reader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.ibatis.common.resources.Resources; import com.ibatis.db.sqlmap.SqlMap; import com.ibatis.db.sqlmap.XmlSqlMapBuilder; public class SqlMapUtil { private static Log loger = LogFactory.getLog(SqlMapUtil.class); public static SqlMap sqlMap ; public static SqlMap loadSqlMap(){ Reader reader = null; try{ reader = Resources.getResourceAsReader("com/montersoft/ibatis/common/SqlMap.xml"); return XmlSqlMapBuilder.buildSqlMap(reader); } catch(Exception e){ loger.error("there is a error=>"+e.getMessage()); } return null; } public static SqlMap getSqlMap(){ if( sqlMap == null ) sqlMap = loadSqlMap(); return sqlMap; } } 5.再新建DAO,Vo, public interface IVO { } public class MonterVo implements IVO{ public String id ; public String name; public int age; ...省去 get ,set 方法 } public class MonterDao { public IVO getBkPK(Connection conn,IVO vo) throws Exception{ try{ Object map = SqlMapUtil.getSqlMap(). getMappedStatement("monter_getByPk").executeQueryForObject(conn,vo); return copyMap2Vo(map); } catch(Exception e){ throw new Exception(e.getMessage()); } } private IVO copyMap2Vo(Object map){ MonterVo vo = new MonterVo(); try{ BeanUtils.copyProperties(vo,map); } catch(Exception e){ e.printStackTrace(); } return vo; } }
6.至此就建立了一个简单的ibatis示例.
通过weblogic的数据源获得数据库连接的方法:
package com.moonsoft.datasource;
import javax.naming.NamingException; import java.util.Hashtable; import javax.naming.InitialContext; import java.sql.Connection; import javax.sql.DataSource; import java.sql.SQLException; import java.sql.PreparedStatement; import java.sql.ResultSet;
public class TestDataSource {
public static String WEB_URL = "t3://localhost:9000"; public static String DATA_SOURCE = "JDBCDS"; public static String weblogic_context_factory = "weblogic.jndi.WLInitialContextFactory"; public TestDataSource() { } public static Object lookUp() throws NamingException { Hashtable env = new Hashtable(); env.put(InitialContext.INITIAL_CONTEXT_FACTORY, weblogic_context_factory); env.put(InitialContext.PROVIDER_URL, WEB_URL); InitialContext tempContext = new InitialContext(env); return tempContext.lookup(DATA_SOURCE); } public static Connection getConnection() throws SQLException { Connection conn = null; try { DataSource ds = (DataSource) lookUp(); if (ds == null) { throw new SQLException("查询到空数据源!"); } conn = ds.getConnection(); } catch (NamingException ex) { ex.printStackTrace(); } return conn; } public static void releaseConnection(Connection conn, PreparedStatement sta, ResultSet rs) { try { if (rs != null) { rs.close(); } if (sta != null) sta.close(); if (conn != null) conn.close(); } catch (Exception ex) { ex.printStackTrace(); } } public static void testSearch() { Connection conn = null; PreparedStatement sta = null; ResultSet rs = null; try { conn = getConnection(); String sql = "select * from admin_config where config_name like ?"; sta = conn.prepareStatement(sql); sta.setString(1,"%Sms%"); rs = sta.executeQuery(); if (rs != null) { while (rs.next()) { System.out.println(rs.getString(1)); } } } catch (Exception ex) { ex.printStackTrace(); } finally { releaseConnection(conn,sta,rs); } } public static void main(String [] argv){ testSearch(); } }
如果是在需求还没确定或者是在两个类实现相近功能时候,会大量使用下面的方式: --抽象类,注意其中的newInstance方法的实现 package com.moonsoft.design; public abstract class Moon { public static Moon newInstance(String classStr){ Class re; try { re = Class.forName(classStr); return (Moon)re.newInstance(); } catch (Exception ex) { ex.printStackTrace(); } return null; } public abstract void println(); } --从Moon类派生出来的一个字类,提供println方法的一种实现方式 package com.moonsoft.design; public class Moon1 extends Moon { public void println(){ System.out.println("I am moon1"); } public void myprintln(){ System.out.println("I am moon1 myprintln"); } } --从Moon类派生出来的另一个字类,提供println方法的另一种实现方式 package com.moonsoft.design; public class Moon2 extends Moon { public void println(){ System.out.println("I am moon2!"); } } --调用 Moon moon = Moon.newInstance("com.moonsoft.design.Moon1"); moon.println(); 或 Moon moon = Moon.newInstance("com.moonsoft.design.Moon2"); moon.println();
如要在JSP页面上有一个链接,Url值是通过参数输入的,用JSP标签的实现步骤(当然实际中不会用标签来完成这么简单的功能):
<一>.先从javax.servlet.jsp.tagext.BodyTagSupport派生一个新的类,并重载它的doStartTag()方法.如果是想要传入参数的话,则还要在Bean中加入想要的变量,如这里要传入一个url值,所以添加一个参数:linkUrl. 最后代码如下:
package com.moonsoft.jsptag; import javax.servlet.jsp.tagext.BodyTagSupport; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.JspException; public class UrlLinkTag extends BodyTagSupport { private String linkUrl; public UrlLinkTag() { } public String getLinkUrl() { return linkUrl; } public void setLinkUrl(String linkUrl) { this.linkUrl = linkUrl; } public int doStartTag() throws JspException{ try { this.pageContext .getOut().print("<a href=\'"+linkUrl+"\' >"+linkUrl+"</a>"); } catch (Exception ex) { ex.printStackTrace(); } return 0; } }
<二>新建一个tld文件,内容如下: <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>buttons</shortname> <uri>http://www.borland.com/jbuilder/internetbeans.tld</uri> <info> JSP tag extensions for InternetBeans Express </info> <tag> <name>urllink</name> <tagclass>com.moonsoft.jsptag.UrlLinkTag</tagclass> <bodycontent>jsp</bodycontent> <attribute> <name>linkUrl</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib> <三>在web.xml中引入这个taglib,在其中加入:
<taglib> <taglib-uri>/moon</taglib-uri> <taglib-location>/WEB-INF/classes/com/moonsoft/jsptag/UrlLinkTag.tld</taglib-location> </taglib>
<四>在jsp中引入这个标签 <%@ taglib uri="/moon" prefix="mylinkurl" %> 这里uri是和web.xml中配置的taglib-uri对应的,prefix值只是在本jsp页面作为标示用.
下面就可以在jsp中使用这个标签了:
<mylinkurl:urllink linkUrl="http://www.baidu.com" />
这里面的mylinkurl为在本jsp页面中设置的prefix值,urllink为tld文件中tag name,linkUrl为输入的参数
这样就在jsp页面上加入了一个: <a href='http://www.baidu.com' >http://www.baidu.com</a>链接
现在正在做的项目中涉及大量的Excel文件导出导入操作,都是使用Java Excel来操作。
Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。下面我写了一个简单的例子,展示基本的读取,新建,更新(包括常见格式的设置:字体,颜色,背景,合并单元格),拷贝操作,有这些其实已经基本足够应付大部分问题了。下面是例的源代码:
import java.io.*; import java.util.Date;
import jxl.*; import jxl.format.Colour; import jxl.format.UnderlineStyle; import jxl.read.biff.BiffException; import jxl.write.*; import jxl.format.UnderlineStyle; import jxl.format.CellFormat;;
public class OperateExcel { /** * Read data from a excel file */ public static void readExcel(String excelFileName){ Workbook rwb = null; try{ InputStream stream = new FileInputStream(excelFileName); rwb = Workbook.getWorkbook(stream); Sheet sheet = rwb.getSheet(0); Cell cell = null; int columns = sheet.getColumns(); int rows = sheet.getRows(); for( int i=0 ; i< rows ; i++ ) for( int j=0 ; j< columns ; j++){ //attention: The first parameter is column,the second parameter is row. cell = sheet.getCell(j,i); String str00 = cell.getContents(); if( cell.getType() == CellType.LABEL ) str00 += " LAEBL"; else if( cell.getType() == CellType.NUMBER) str00 += " number"; else if( cell.getType() == CellType.DATE) str00 += " date"; System.out.println("00==>"+str00); } stream.close(); } catch(IOException e){ e.printStackTrace(); } catch(BiffException e){ e.printStackTrace(); } finally{ rwb.close(); } } /** * create a new excelFile * @param excelFileName create name */ public static void createExcelFile(String excelFileName){ try{ WritableWorkbook wwb = Workbook.createWorkbook(new File(excelFileName)); WritableSheet ws = wwb.createSheet("sheet1",0); //also,The first parameter is column,the second parameter is row. // add normal label data Label label00 = new Label(0,0,"Label00"); ws.addCell(label00); //add font formating data WritableFont wf = new WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD , true); WritableCellFormat wff = new WritableCellFormat(wf); Label label10 = new Label(1,0,"Label10",wff); ws.addCell(label10); //add color font formating data WritableFont wf_color = new WritableFont(WritableFont.ARIAL,10,WritableFont.NO_BOLD,false,UnderlineStyle.DOUBLE_ACCOUNTING,Colour.RED); WritableCellFormat wff_color = new WritableCellFormat(wf_color); wff_color.setBackground(Colour.GRAY_25); //set background coloe to gray Label label20 = new Label(2,0,"Label20",wff_color); ws.addCell(label20); //合并单元格 WritableFont wf_merge = new WritableFont(WritableFont.ARIAL,10,WritableFont.NO_BOLD,false,UnderlineStyle.DOUBLE_ACCOUNTING,Colour.GREEN); WritableCellFormat wff_merge = new WritableCellFormat(wf_merge); wff_merge.setBackground(Colour.BLACK); Label label30 = new Label(3,0,"Label30",wff_merge); ws.addCell(label30); Label label40 = new Label(4,0,"Label40"); ws.addCell(label40); Label label50 = new Label(5,0,"Label50"); ws.addCell(label50); //合并 (0,3) (4,0) //attention : 如果合并后面的列不为空,那么就把后面格的内容清空,格式也是按前一个单元格的格式 ws.mergeCells(3,0,4,0); //添加Number格式数据 jxl.write.Number labelN = new jxl.write.Number(0, 1, 3.1415926); ws.addCell(labelN); //添加带有formatting的Number对象 jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##"); jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf); jxl.write.Number labelNF = new jxl.write.Number(1, 1, 3.1415926, wcfN); ws.addCell(labelNF); //添加Boolean对象 jxl.write.Boolean labelBoolean = new jxl.write.Boolean(2,1,false); ws.addCell(labelBoolean); //添加DateTime对象 DateTime labelDT = new DateTime(3,1,new Date()); ws.addCell(labelDT); //添加带有格式的DataTime数据 DateFormat dtf = new DateFormat("yyyy-MM-dd hh:mm:ss"); WritableCellFormat wcfDt = new WritableCellFormat(dtf); wcfDt.setBackground(Colour.YELLOW); DateTime labelDT_format = new DateTime(4,1,new java.util.Date(),wcfDt); ws.addCell(labelDT_format); ws.mergeCells(4,1,5,1); //比较长,用两列来显示 wwb.write(); wwb.close(); } catch(IOException e){ e.printStackTrace(); } catch(WriteException e){ e.printStackTrace(); } } /** * 如何更新Excel文件 * @param fileName */ public static void updateExcel(String fileName){ try{ jxl.Workbook rw = jxl.Workbook.getWorkbook(new File(fileName)); WritableWorkbook wwb = Workbook.createWorkbook(new File(fileName),rw); //这里其实执行的是一次copy操作,把文件先读到内存中,修改后再保存覆盖原来的文件来实现update操作 WritableSheet ws = wwb.getSheet(0); WritableCell wc = ws.getWritableCell(0,0); if( wc.getType() == CellType.LABEL){ Label l = (Label)wc; l.setString(wc.getContents()+"_new"); } wwb.write(); wwb.close(); } catch(IOException e){ e.printStackTrace(); } catch(WriteException e){ e.printStackTrace(); } catch(BiffException e){ e.printStackTrace(); } } /** * 如何copy Excel文件 * @param fileName */ public static void copyExcel(String sourFileName,String destFileName){ try{ jxl.Workbook rw = jxl.Workbook.getWorkbook(new File(sourFileName)); WritableWorkbook wwb = Workbook.createWorkbook(new File(destFileName),rw); wwb.write(); wwb.close(); } catch(IOException e){ e.printStackTrace(); } catch(WriteException e){ e.printStackTrace(); } catch(BiffException e){ e.printStackTrace(); } } public static void main(String [] argv){ //OperateExcel.readExcel("E:\\test.xls"); //OperateExcel.createExcelFile("E:\\test1.xls"); //OperateExcel.updateExcel("E:\\test.xls"); OperateExcel.copyExcel("E:\\test.xls","E:\\moon.xls"); }
}
在编程中可能回碰到一些到实际运行时才指定要调用的方法的需要,最典型的是Struct的DispatchAction类, 它能根据用户页面请求参数的不同来调用不同的方法来处理用户请求。我下面写了一个简单的例子来简单演示其 实现方法:
package learn; import java.lang.NoSuchMethodException; import java.lang.reflect.Method; import java.util.Date; public class TestMethod{ protected Class clazz = this.getClass(); protected Class[] no_parameter = {}; //方法无参数 protected Class[] string_parameter = {String.class}; //以String 为参数 protected Class[] int_parameter = {int.class}; //以int为参数 protected Class[] multi_parameter = {String.class,Date.class}; //多个参数,第一个为String,第二二个为Date public void method1(){ System.out.println("method1"); } public void method2(String str){ System.out.println("method2=>"+str); } public void method3(int i){ System.out.println("method2=>"+i); } public void method4(String str,Date date){ System.out.println("method4=>"+str+"==="+date.toLocaleString()); } public void execute(String methodName,int type,java.util.List list) throws Exception{ try { Method m = getMethod(methodName,type); int size = (list != null )? list.size():0; Object o [] = new Object[size]; for( int i =0 ; i< size ; i++ ) o[i] = list.get(i); //准备参数 m.invoke(this,o); } catch (Exception ex) { ex.printStackTrace(); throw new Exception(ex.getMessage()); } } private Method getMethod(String name,int type)throws NoSuchMethodException{ Method m = null; switch(type){ case 1: m = clazz.getMethod(name,no_parameter); break; case 2: m = clazz.getMethod(name,string_parameter); break; case 3: m = clazz.getMethod(name,int_parameter); break; case 4: m = clazz.getMethod(name,multi_parameter); break; default: m = clazz.getMethod(name,no_parameter); } return m; } public static void main(String [] argv){ TestMethod testMethod = new TestMethod(); try{ java.util.List list = new java.util.ArrayList(); testMethod.execute("method1", 1, list); list.add("http://www.blogjava.net/minmoon"); testMethod.execute("method2", 2, list); list.clear(); list.add("mailTo:xiaoliang@aspire-tech.com"); list.add(new Date()); testMethod.execute("method4",4,list); } catch(Exception e){ e.printStackTrace(); } } }
其中几个关键的地方说明一下: clazz.getMethod(name,multi_parameter); 其中multi_parameter是要根据实际方法的参数来定义的。 m.invoke(this,o); o是要传入方法的参数列表。
原型模式定义: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.
Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
如何使用? 因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单.
以勺子为例:
public abstract class AbstractSpoon implements Cloneable { String spoonName;
public void setSpoonName(String spoonName) {this.spoonName = spoonName;} public String getSpoonName() {return this.spoonName;}
public Object clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException exception) { System.err.println("AbstractSpoon is not Cloneable"); } return object; } }
|
有个具体实现(ConcretePrototype):
public class SoupSpoon extends AbstractSpoon { public SoupSpoon() { setSpoonName("Soup Spoon"); } }
|
调用Prototype模式很简单:
AbstractSpoon spoon = new SoupSpoon(); AbstractSpoon spoon2 = spoon.clone();
当然也可以结合工厂模式来创建AbstractSpoon实例。
在Java中Prototype模式变成clone()方法的使用,由于Java的纯洁的面向对象特性,使得在Java中使用设计模式变得很自然,两者已经几乎是浑然一体了。这反映在很多模式上,如Interator遍历模式。
原文出处:http://www.jdon.com/designpatterns/prototype.htm
看看写的很好,就拿来引用一下,不用自己写的那么累^_^.
Factory method,工厂方法模式,定义一个用于创建对象的接口,让字类决定实例化哪一个类。也就是使一个类的实例化延迟到其子类,提供一种方法使对象创建变得多态。 下面是我写的一个例子,如有两种工人,car worker和bus worker,所生成的产品分别是car 和 bus,我按照Factory method 的实现如下:
--先定义car 和 bus 的父类,都是一种产品 package Factory; public class Product { public void whoami(){ System.out.println("I am a product!"); } }
--Car 类 package Factory; public class Car extends Product { public Car() { } public void whoami(){ System.out.println("I am a car!"); } } --Bus 类 package Factory; public class Bus extends Product { public Bus() { } public void whoami(){ System.out.println("I am a bus!"); } } --定义CarWorker和BusWorker的父类 worker package Factory; public abstract class Worker { private Product theProduct; public abstract Product createProduct(); public void work(){ theProduct = createProduct(); } public void showMessage(){ this.theProduct.whoami(); } } --Carworker package Factory; public class CarWorker extends Worker { public Product createProduct(){ return new Car(); } } --BusWorker package Factory; public class BusWorker extends Worker { public Product createProduct(){ return new Bus(); } } --下面看看具体的调用 package Factory; public class TestAll {
public static void main(String [] argv){ Worker worker = new CarWorker(); worker.work(); worker.showMessage(); Worker worker1 = new BusWorker(); worker1.work(); worker1.showMessage(); } } 可以看到虽然这样实现有一些麻烦,如新加一种产品时,就必须从Product类创建一个子类,但是这样做的 好处也是显而易见的,会给你系统带来更大的可扩展性和尽量少的修改量,再添加一种产品一种工人的时候,对以前的代码是不必做任何修改的。
<个人观点,仅作参考>
Singleton模式为单态模式或者叫孤子模式,保证一个类只有一个实例,并提供一个访问它的全局访问点。 Singleton模式的使用范围比较广泛,对于一些类来说,只有一个实例是很重要的。比如,你要论坛中
的帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能synchronize的安全自动加
1,如果你要把这个数字永久保存到数据库,你可以在不修改单态接口的情况下方便的做到。 下面是一个简单的示例程序: package Singleton; public class TestSingleton { private static TestSingleton testSingleton = null; protected int count = 0; public static synchronized TestSingleton getInstance(){ if( testSingleton == null) testSingleton = new TestSingleton(); return testSingleton; } public void addCount(){ count ++; } public void showCount(){ System.out.println("count :"+count); } } 我们还可以在这个基础上做一个扩展,如从上面例子中的TestSingleton类扩展出多个子类,在
getInstance方法中控制要使用的是哪个子类,具体实现代码如下:
-----TestSingleton.java package Singleton; public class TestSingleton { private static TestSingleton testSingleton = null; protected int count = 0; public static synchronized TestSingleton getInstance(){ if( testSingleton == null) testSingleton = new SubTestSingleton (); return testSingleton; } public void addCount(){ count ++; } public void showCount(){ System.out.println("TestSingleton count :"+count); } }
-----SubTestSingleton.java public class SubTestSingleton extends TestSingleton{ public void showCount(){ System.out.println("SubTestSingleton count :"+count); } }
<以上为个人见解,欢迎大家评论!>
最近对面向对象的设计的23种经典的设计模式做了一个研究,接下来的Blog中我会按我的理解做个简单介绍并提供我写的示例代码,欢迎大家的评论,共同提高.
|