??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲成av人在线观看,国产三级av在线,亚洲精品www http://www.aygfsteel.com/nighty/category/31702.html折腾的年?/description>zh-cn Thu, 28 Apr 2011 10:15:27 GMT Thu, 28 Apr 2011 10:15:27 GMT 60 扩展commons dbutils的JavaBean转换方式 http://www.aygfsteel.com/nighty/archive/2011/04/26/349050.html寒武U?/dc:creator>寒武U?/author>Tue, 26 Apr 2011 08:41:00 GMT http://www.aygfsteel.com/nighty/archive/2011/04/26/349050.html http://www.aygfsteel.com/nighty/comments/349050.html http://www.aygfsteel.com/nighty/archive/2011/04/26/349050.html#Feedback 0 http://www.aygfsteel.com/nighty/comments/commentRss/349050.html http://www.aygfsteel.com/nighty/services/trackbacks/349050.html 引言Q最q又用到dbutilsQ之前一直用Map映射的方式取出select的结果再手工做{换。有写过一文章说MapHandler方式的一个缺P关于commons dbutilslg的一个小~陷分析 Q用q种方式Q在目不大的情况下Q写一些Map到JavaBean的{换代码工作量不大Q但是在数据库表q多q且表中的字D过多的情况下,q种重复的setter感觉有点烦。于是又重新思考了BeanHandler和BeanListHandler的情况,dbutils底层映射用的反射Q性能上肯定有损失Q不q在大多数项目规模不是很大的情况下,q点损失可以忽略Q带来的代码减少却是比较可观?br />
问题在哪里?先看一D官方的CZ代码Q?br />
QueryRunner run = new QueryRunner(dataSource);
// Use the BeanHandler implementation to convert the first
// ResultSet row into a Person JavaBean.
ResultSetHandler < Person > h = new BeanHandler < Person > (Person. class );
// Execute the SQL statement with one replacement parameter and
// return the results in a new Person object generated by the BeanHandler.
Person p = run.query(
" SELECT * FROM Person WHERE name=? " , h, " John Doe " );
q里有个地方有约束,是要求CZ中的JavaBeancPerson中的字段定义要和数据库的字段定义一致。Java的命名习惯一般是骆峰写法Q例如userIdQ那么数据库中就必须定义为userIdQ而问题在于:有时候我们需要数据库中字D늚定义格式与JavaBean的命名不一P比如数据库定义ؓQuser_idQ而JavaBean则定义ؓuserId
看源代码可能有点Ҏ_在官方的example面的最下面果然有一D关于自定义BeanProcessor的指引。摘录出来:
BasicRowProcessor uses a BeanProcessor to convert ResultSet columns into JavaBean properties. You can subclass and override processing steps to handle datatype mapping specific to your application. The provided implementation delegates datatype conversion to the JDBC driver.
BeanProcessor maps columns to bean properties as documented in the BeanProcessor.toBean() javadoc. Column names must match the bean's property names case insensitively. For example, the firstname column would be stored in the bean by calling its setFirstName() method. However, many database column names include characters that either can't be used or are not typically used in Java method names. You can do one of the following to map these columns to bean properties:
1. Alias the column names in the SQL so they match the Java names: select social_sec# as socialSecurityNumber from person
2. Subclass BeanProcessor and override the mapColumnsToProperties() method to strip out the offending characters.
大概意思就是提供二U方式:一U就是最直接的,用as关键字把colName重命名,另一U方式就是承BeanProcessorc,重写mapColumnsToProperties()Ҏ?br />
那当然是W二U方式更加具有代表性。尝试了一下。代码如下:
1 public class CustomBeanProcessor extends BeanProcessor {
2
3 @Override
4 protected int [] mapColumnsToProperties(ResultSetMetaData rsmd,
5 PropertyDescriptor[] props) throws SQLException {
6 int cols = rsmd.getColumnCount();
7 int columnToProperty[] = new int [cols + 1 ];
8 Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);
9
10 for ( int col = 1 ; col <= cols; col ++ ) {
11 String columnName = rsmd.getColumnLabel(col);
12 if ( null == columnName || 0 == columnName.length()) {
13 columnName = rsmd.getColumnName(col);
14 }
15 columnName = colNameConvent(columnName); // 在这里进行数据库表columnName的特D处?/span>
16 for ( int i = 0 ; i < props.length; i ++ ) {
17
18 if (columnName.equalsIgnoreCase(props[i].getName())) {
19 columnToProperty[col] = i;
20 break ;
21 }
22 }
23 }
24 return columnToProperty;
25 }
26
27 /** */ /**
28 * 数据库列名重新约?br />
29 * @param columnName
30 * @return
31 */
32 private String colNameConvent(String columnName) {
33 String[] strs = columnName.split( " _ " );
34 String conventName = "" ;
35 for ( int i = 0 ; i < strs.length; i ++ ) {
36 conventName += StringUtils.capitalize(strs[i]);
37 }
38 StringUtils.uncapitalize(conventName);
39 return conventName;
40 }
41 }
注意mapColumnsToPropertiesҎ的逻辑是从父类的方法中直接复制出来的,然后在第15行那里变了个戏法Q这里的columnName是从数据库中读出来的,自定义一个privateҎ用于转换命名Q这里你可以添加自q命名U束。例如上面就是把 user_id 转化为Java的骆峰写法:userId
再深入一层思考,你可以在q里q行更多扩展Q以便让自己可以选择不同的命名{换方式。定义了q个Processor之后Q下面看看如何调用:
Connection conn = ConnectionManager.getInstance().getConnection();
QueryRunner qr = new QueryRunner();
CustomBeanProcessor convert = new CustomBeanProcessor();
RowProcessor rp = new BasicRowProcessor(convert);
BeanHandler < User > bh = new BeanHandler < User > (User. class , rp);
User u = qr.query(conn, sql, bh, params);
DbUtils.close(conn);
是不是非常灵z?如果是想q回Listl果的,把BeanHandler替换成BeanListHanderc,q可以再q一步封装这些操作,抽象到公共模块中去,让外部直接传入sql语句和Classp直接q回惌的结果,当然你得增加泛型的定义。同样D一个封装的例子Q?br />
1 protected < T > List < T > selectBeanList(Connection conn, String sql, Class < T > type,
2 Object[] params) throws Exception {
3 log.debug(" select sql:[ " + sql + " ] " );
4 QueryRunner qr = new QueryRunner();
5 CustomBeanProcessor convert = new CustomBeanProcessor();
6 RowProcessor rp = new BasicRowProcessor(convert);
7 ResultSetHandler< List < T >> bh = new BeanListHandler < T > (type, rp);
8 List< T > list = qr.query(conn, sql, bh, params);
9 return list;
10 }
至于Z么扩展这个方法就可以实现q个逻辑得去跟源代码看它的内部实现Q用了一些JavaBean的处理和反映的技巧来做的。具体就不说?br />
ȝQcommonslg都设计得非常好,可扩展性和实用性都非常高。虽然上面D例实C转换逻辑的替换,但是仍然需要开发h员在设计数据库的时候和写JavaBean旉要严格做好规范,避免产生不必要的问题。这斚wRuby On Railsq接内部实玎ͼ动态语a的优点特别能体现Q同时强制你在设计时必须用这U方式,典型的约定优于配|原则。当Ӟ在dbutils里你愿意二种字段名都一样也无可厚非?br />
~点QBeanProcessor是不支持兌查询的,所以上面的方式也只能局限于单表的{换,q点׃如myBatis和HibernateQ当然用q二个就引入了一些复杂性,如何权衡需要自p量,哪个用得好都一栗本人就不喜ƢmyBatis那种把SQL写到XML中的方式Q见q太复杂的SQL最l在XML里面变得面目全非Q如果是接手别h的代码,是很痛苦的,而且你无法避免只修改XML而不改JavaQ既然二者都要改Q那直接写Java里又有什么区别?单就是美。格式和注释写好一点同样很Ҏ理解Q?
]]>关于commons dbutilslg的一个小~陷分析 http://www.aygfsteel.com/nighty/archive/2011/02/12/344155.html寒武U?/dc:creator>寒武U?/author>Sat, 12 Feb 2011 09:33:00 GMT http://www.aygfsteel.com/nighty/archive/2011/02/12/344155.html http://www.aygfsteel.com/nighty/comments/344155.html http://www.aygfsteel.com/nighty/archive/2011/02/12/344155.html#Feedback 6 http://www.aygfsteel.com/nighty/comments/commentRss/344155.html http://www.aygfsteel.com/nighty/services/trackbacks/344155.html
鉴于前面没有旉了解Q就都粗略用了上面那种_暴的map.get("")来处理,最好的情况是让dbutilslg能自动识别到ascd的列名。于是有IZ׃门看了看它的源代码,发现最主要的一D代码如下:
1 public Map < String, Object > toMap(ResultSet rs) throws SQLException {
2 Map< String, Object > result = new CaseInsensitiveHashMap();
3 ResultSetMetaData rsmd = rs.getMetaData();
4 int cols = rsmd.getColumnCount();
5
6 for ( int i = 1 ; i <= cols; i ++ ) {
7 result.put(rsmd.getColumnName(i), rs.getObject(i));
8 }
9
10 return result;
11 }
CaseInsensitiveHashMap是dbutils自定义的一个MapQ忽略键大小写的K-V字典Q但是key使用的是ResultSetMetaData.getColumnName()Q我想问题大概出在这里,于是认真Mjava的api文档Q开发做久了Ҏ遗忘基础Q,果然Q原?strong>getColumnName()是:获取指定列的名称Q?/span>而as关键字之后,使列名称变成用于昄的意义,q个时候应该?strong>getColumnLabel()Q?span style="color: #339966">获取用于打印输出和显C的指定列的标题。徏议标题通常?SQL AS
子句来指定。如果未指定 SQL AS
Q则?getColumnLabel
q回的值将?getColumnName
Ҏq回的值相?/span>。自己手动试验了一下,果然如所料,问题出在这里?br />
所以呢Q如果想要dbutils在自动{换Map及MapList时能识别聚合函数的列名,那么最好的做法是重蝲q种方式Q懒一点的Q你干脆修改上面那D代码,让它判断是否使用了as关键字。个人暂时搞不清楚官方ؓ什么没有考虑q一步,有时间再思考一下!
]]> Apache Roller部v到MyEclipse上面 http://www.aygfsteel.com/nighty/archive/2009/11/22/303255.html寒武U?/dc:creator>寒武U?/author>Sun, 22 Nov 2009 13:04:00 GMT http://www.aygfsteel.com/nighty/archive/2009/11/22/303255.html http://www.aygfsteel.com/nighty/comments/303255.html http://www.aygfsteel.com/nighty/archive/2009/11/22/303255.html#Feedback 2 http://www.aygfsteel.com/nighty/comments/commentRss/303255.html http://www.aygfsteel.com/nighty/services/trackbacks/303255.html 阅读全文 ]]> httpClient3.1中文参数GETh的解x?/title> http://www.aygfsteel.com/nighty/archive/2008/07/16/215143.html寒武U?/dc:creator>寒武U?/author>Wed, 16 Jul 2008 02:31:00 GMT http://www.aygfsteel.com/nighty/archive/2008/07/16/215143.html http://www.aygfsteel.com/nighty/comments/215143.html http://www.aygfsteel.com/nighty/archive/2008/07/16/215143.html#Feedback 2 http://www.aygfsteel.com/nighty/comments/commentRss/215143.html http://www.aygfsteel.com/nighty/services/trackbacks/215143.html
httpClient的GetMethodcd入参数的Ҏ是如下:
跟踪一下httpClient的GetMethod的源代码Q承自HttpMethodBaseQ源码如下:
public void setQueryString(String queryString) {
this .queryString = queryString;
}
public void setQueryString(NameValuePair[] params) {
LOG.trace( " enter HttpMethodBase.setQueryString(NameValuePair[]) " );
queryString = EncodingUtil.formUrlEncode(params, " UTF-8 " );
}
EncodingUtil是httpClient定义的一个编码工LQ由于默认设|的是UTF-8Q所以对于一些系l可能就无法识别。可以在外部q样更改Q?br />
method.setQueryString(EncodingUtil.formUrlEncode(pair, "GB2312"));另外Q?span style="color: red">注意h头也要修改ؓ对应的一致编码方?/span>Qmethod.addRequestHeader("Content-type" , "text/html; charset=GB2312");如果q二个编码不一_׃引vq?br />
刚开始的时候尝试过都用一致的UTF-8Q但是发现还是ؕ码,q应该是服务器的原因。IE默认的就是采用操作系lWindows的中文编码去q行Encoder的,服务器原先基本上都ؓIE服务的,所以改为GB2312p正常识别得到?br />
另外Q上面提到的EncodingUtilq个工具是从apache的另一个组件codec包装而来的,而非SUN的URLEncoder。有兴趣的可以研M下源代码?
]]> httpclient3.1使用结 http://www.aygfsteel.com/nighty/archive/2008/06/11/207121.html寒武U?/dc:creator>寒武U?/author>Wed, 11 Jun 2008 07:18:00 GMT http://www.aygfsteel.com/nighty/archive/2008/06/11/207121.html http://www.aygfsteel.com/nighty/comments/207121.html http://www.aygfsteel.com/nighty/archive/2008/06/11/207121.html#Feedback 6 http://www.aygfsteel.com/nighty/comments/commentRss/207121.html http://www.aygfsteel.com/nighty/services/trackbacks/207121.html Jakarta的httpclient3.1是最新版本,目中需要用E序模拟览器的GET和POST动作。在使用q程中遇C问题?br />
1. 带附件的POST提交
最开始都是用MultipartPostMethodq个c,现在已经废弃q个cM。API说明Q?strong>Deprecated. Use MultipartRequestEntity
in conjunction with PostMethod
instead. 使用PostMethod可以实现的功能,没有必要再弄一个MultipartPostMethod了。下面是一D|单的CZQ?/p>
PostMethod post = new PostMethod();
NameValuePair[] pairs = new NameValuePair[ 2 ];
pairs[ 0 ] = new NameValuePair( " para1 " , " value1 " );
pairs[ 0 ] = new NameValuePair( " para2 " , " value2 " );
post.setRequestBody(pairs);
HttpClient client = new HttpClient();
try {
client.executeMethod(post);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
q是针对一般的form形式的提交,而且q个form里面不带附g的。如果带附gQ那么这U方法就不v作用Q附件上传的参数和普通参数无法一同在服务器获取到?font size="-1">org.apache.commons.httpclient.methods.multipart q个包就是ؓ处理文g上传q种多Ş式参数的情况的。最主要的类是PartQ代表一Upost objectQ,它有二个比较重要的子c:FilePart和StringPartQ一个是文g的参敎ͼ另一个就是普通的文本参数。它的典型用方法如下:
String url = " http://localhost:8080/HttpTest/Test " ;
PostMethod postMethod = new PostMethod(url);
StringPart sp = new StringPart( " TEXT " , " testValue " );
FilePart fp = new FilePart( " file " , " test.txt " , new File( " ./temp/test.txt " ));
MultipartRequestEntity mrp = new MultipartRequestEntity( new Part[] {sp, fp} , postMethod
.getParams());
postMethod.setRequestEntity(mrp);
// 执行postMethod
HttpClient httpClient = new HttpClient();
try {
httpClient.executeMethod(postMethod);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
在第二行PostMethod postMethod = new PostMethod();后面Q有需要用postMehtod.setRequestHeader("Content-type", "multipart/form-data"); Content-type的请求类型进行更攏V但是我在用过E没有加上这一句,查了一下httpCleint的默认Content-type是application/octet-stream。应该是没有影响的。对于MIMEcd的请求,httpclient全用MulitPartRequestEntityq行包装Q就是上面的用法?br />
2. 参数中文的处理问?br />
httpclient的默认编码都是ISO-8859-1Q那肯定无法支持中文参C。引用一下这文章:http://thinkbase.net/w/main/Wiki?HttpClient+POST+%E7%9A%84+UTF-8+%E7%BC%96%E7%A0%81%E9%97%AE%E9%A2%98 Q按照作者的说法Q就可以正常解决中文~码的问题。其中最关键的是修改EncodingUtilq个cȝ一个方法实现。另外,FilePart和StringPart的构造方法都有一个带~码指定的参敎ͼZ减少问题的出玎ͼ所有的都带上统一的编码,包括postMethod.getParams()。示例如下:
String url = " http://localhost:8080/HttpTest/Test " ;
PostMethod postMethod = new PostMethod(url);
StringPart sp = new StringPart( " TEXT " , " testValue " , " GB2312 " );
FilePart fp = new FilePart( " file " , " test.txt " , new File( " ./temp/test.txt " ), null , " GB2312 " );
postMethod.getParams().setContentCharset( " GB2312 " );
MultipartRequestEntity mrp = new MultipartRequestEntity( new Part[] {sp, fp} , postMethod
.getParams());
postMethod.setRequestEntity(mrp);
// 执行postMethod
HttpClient httpClient = new HttpClient();
try {
httpClient.executeMethod(postMethod);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
]]> 关于Java命o行交互方?/title> http://www.aygfsteel.com/nighty/archive/2008/05/23/202314.html寒武U?/dc:creator>寒武U?/author>Fri, 23 May 2008 01:41:00 GMT http://www.aygfsteel.com/nighty/archive/2008/05/23/202314.html http://www.aygfsteel.com/nighty/comments/202314.html http://www.aygfsteel.com/nighty/archive/2008/05/23/202314.html#Feedback 1 http://www.aygfsteel.com/nighty/comments/commentRss/202314.html http://www.aygfsteel.com/nighty/services/trackbacks/202314.html
命o行交互是传统的交互方式,如果E序有时候需要在Unix或是Linux{系l上q动Ӟ以这U方式出现的可能性就比较大。命令行包括
输入和回N题,一般是以行l束Q或是以某个l束Wؓl命令终止标识。System.out 和System.errq于标准的输出和错误输出,System.in用于标准的输入接受,一般情况下都是指键盘?br />
如果接受参数输入Q一般的E序l构如下Q?br />
BufferedReader in = new BufferedReader( new InputStreamReader(System.in));
System.out.println( " ==Please input password==Q?/span>" );
String pass = in.readLine();
输入的时候显C屏自动q行输入回显。这个时候如果遇到输入密码等敏感数据的时候,无法用*或是#q样的符可行回昑ֱ蔽,Ҏ暴露安全问题?br />
解决的可能想法:
1. 通过监听键盘事gQ对输入的回显进行截获取Q把回显q行屏蔽Q但是监听器如何知道何时是输入密码,何时是输入普通数据?比较难以控制Q而且q种监听应该是线E化的,可能会存在一些意想不到的问题?br />
2. 如果用纯Java难以实现Q那么是否可以用其它语a的功能进行补充,比如JNIQ或是Windows下面的Dos脚本QLinuxq_的Shell脚本来进行补充。不q这样就不太q_无关了?br />
3. 可能sun发现了这个不之处,?.6版本开始,增加了一个java.io.Consolec,代表与当?Java 虚拟机关联的Z字符的控制台讑֤Q这个Console是对原来System.inq种不的补充,提供了像readPassword ()
{这L实用ҎQ具体请参考API文档Q就是专门用于对敏感信息的读取。但是这是基于Java1.6的,如果有些场景受限Ӟ不能使用1.6Q那么还是无法解决上面的问题。后来查阅了一下Consolecȝ实现方式Q想直接把它的实现方式移植到1.4.xx上是比较隄Q因为用C一些高版本的新Ҏ。用Console要注意的是:虚拟机是否具有控制台取决于底层^収ͼq取决于调用虚拟机的方式。如果虚拟机从一个交互式命o行开始启动,且没有重定向标准输入和输出流Q那么其控制台将存在Qƈ且通常q接到键盘ƈ从虚拟机启动的地ҎC。如果虚拟机是自动启动的Q例如,由后C业调度程序启动)Q那么它通常没有控制台。如果你在Eclipse里面启动E序调用ConsoleQ那么通常是没有控制台Q还是得从外部的命o行方式才能调用得到?br />
M想一下,感觉应该q是从第2点出发,牺牲掉一炚w用性,q样才能满q种功能需求?
]]>
վ֩ģ壺
Ժ |
ԫ |
ɫ |
|
ɿ |
Ԫ |
|
ʡ |
ͼƬ |
|
|
|
ˮ |
|
|
|
|
˶ |
|
¡ |
|
|
̨ |
|
|
Ӽ |
Ž |
Զ |
|
|
ֱ |
˹ |
Ϫ |
ȷɽ |
|
|
˺ |
|
Զ |
|
̩ |