001 | packagecom.cucpay.tradeportal.util; |
002 |
003 | importjava.io.UnsupportedEncodingException; |
004 | importjava.lang.reflect.Field; |
005 | importjava.net.URLDecoder; |
006 | importjava.net.URLEncoder; |
007 | importjava.nio.charset.CharacterCodingException; |
008 | importjava.nio.charset.Charset; |
009 | importjava.security.MessageDigest; |
010 | importjava.security.NoSuchAlgorithmException; |
011 | importjava.text.SimpleDateFormat; |
012 | importjava.util.ArrayList; |
013 | importjava.util.Arrays; |
014 | importjava.util.Calendar; |
015 | importjava.util.Collections; |
016 | importjava.util.Date; |
017 | importjava.util.List; |
018 | importjava.util.Map; |
019 | importjava.util.UUID; |
020 |
021 | importorg.apache.commons.lang.StringUtils; |
022 | importorg.apache.mina.core.buffer.IoBuffer; |
023 |
024 | /** |
025 | * 交易前置系統專用工具類 |
026 | * @create Aug 15, 2012 12:16:49 PM |
027 | * @update Sep 27, 2012 3:07:09 PM |
028 | * @author 玄玉<http://blog.csdn/net/jadyer> |
029 | * @version v2.0 |
030 | * @history v1.7.2-->新增<code>getHexSign()</code>經過指定算法簽名字符串方法 |
031 | * @history v1.7.2-->新增<code>getString()</code>字節數組轉爲字符串方法 |
032 | * @history v1.7.3-->修改<code>getSysJournalNo()</code>實現細節爲<code>java.util.UUID.randomUUID()</code> |
033 | * @history v1.7.4-->新增<code>getHexSign()</code>根據指定的簽名密鑰和算法簽名Map<String,String> |
034 | * @history v1.7.5-->新增<code>getStringSimple()</code>獲取一個字符串的簡明效果,返回的字符串格式相似於"abcd***hijk" |
035 | * @history v2.0-->局部的StringBuffer一概StringBuilder之(本思路提示自坦克<captmjc@gmail.com>) |
036 | */ |
037 | publicclassTradePortalUtil { |
038 | privateTradePortalUtil(){} |
039 |
040 | /** |
041 | * 獲取系統流水號 |
043 | * @return 長度爲20的全數字 |
044 | */ |
045 | publicstaticString getSysJournalNo(){ |
046 | returngetSysJournalNo(20,true); |
047 | } |
048 |
049 |
050 | /** |
051 | * 獲取系統流水號 |
052 | * @param length 指定流水號長度 |
053 | * @param toNumber 指定流水號是否全由數字組成 |
054 | */ |
055 | publicstaticString getSysJournalNo(intlength,booleanisNumber){ |
056 | //replaceAll()以後返回的是一個由十六進制形式組成的且長度爲32的字符串 |
057 | String uuid = UUID.randomUUID().toString().replaceAll("-",""); |
058 | if(uuid.length() > length){ |
059 | uuid = uuid.substring(0, length); |
060 | }elseif(uuid.length() < length){ |
061 | for(inti=0; i<length-uuid.length(); i++){ |
062 | uuid = uuid + Math.round(Math.random()*9); |
063 | } |
064 | } |
065 | if(isNumber){ |
066 | returnuuid.replaceAll("a","1").replaceAll("b","2").replaceAll("c","3").replaceAll("d","4").replaceAll("e","5").replaceAll("f","6"); |
067 | }else{ |
068 | returnuuid; |
069 | } |
070 | } |
071 |
072 |
073 | /** |
074 | * 判斷輸入的字符串參數是否爲空 |
075 | * @return boolean 空則返回true,非空則flase |
076 | */ |
077 | publicstaticbooleanisEmpty(String input) { |
078 | returnnull==input ||0==input.length() ||0==input.replaceAll("\\s","").length(); |
079 | } |
080 |
081 |
082 | /** |
083 | * 判斷輸入的字節數組是否爲空 |
084 | * @return boolean 空則返回true,非空則flase |
085 | */ |
086 | publicstaticbooleanisEmpty(byte[] bytes){ |
087 | returnnull==bytes ||0==bytes.length; |
088 | } |
089 |
090 |
091 | /** |
092 | * 從org.apache.mina.core.buffer.IoBuffer中讀取字符串 |
093 | * @see 該方法默認以GBK解碼 |
094 | * @see 若想本身指定字符集,可使用<code>getStringFromIoBuffer(IoBuffer buffer, int size, String charset)</code>方法 |
095 | * @param size 所要讀取的字節數 |
096 | */ |
097 | publicstaticString getStringFromIoBuffer(IoBuffer buffer,intsize){ |
098 | returngetStringFromIoBuffer(buffer, size,"GBK"); |
099 | } |
100 |
101 |
102 | /** |
103 | * 從org.apache.mina.core.buffer.IoBuffer中讀取字符串 |
104 | * @param size 所要讀取的字節數 |
105 | * @param charset 解碼的字符集 |
106 | */ |
107 | publicstaticString getStringFromIoBuffer(IoBuffer buffer,intsize, String charset){ |
108 | String result =null; |
109 | try{ |
110 | result = buffer.getString(size, Charset.forName(charset).newDecoder()); |
111 | }catch(CharacterCodingException e) { |
112 | LogUtil.getLogger().error("字符解碼異常,自動切換第二種解碼方式,本次的堆棧信息以下", e); |
113 | try{ |
114 | result =newString(buffer.array(), charset); |
115 | }catch(UnsupportedEncodingException ee) { |
116 | LogUtil.getLogger().error("字符解碼異常,系統不支持該字符集["+ charset +"],本次的堆棧信息以下", ee); |
117 | } |
118 | } |
119 | returnresult; |
120 | } |
121 |
122 |
123 | /** |
124 | * 獲取實體類中的屬性 |
125 | * @see 本方法用到了反射,其適用於全部的屬性類型均爲byte[]的JavaBean |
126 | * @return String field11=value11 field22=value22 field33=value33 |
127 | */ |
128 | publicstaticString getStringFromObjectForByte(Object obj){ |
129 | StringBuilder sb =newStringBuilder();//局部的StringBuffer一概StringBuilder之 |
130 | sb.append(obj.getClass().getName()).append("@").append(obj.hashCode()).append("["); |
131 | for(Field field : obj.getClass().getDeclaredFields()){ |
132 | String methodName ="get"+ StringUtils.capitalize(field.getName());//構造getter方法 |
133 | Object fieldValue =null; |
134 | try{ |
135 | fieldValue = obj.getClass().getDeclaredMethod(methodName).invoke(obj);//執行getter方法,獲取其返回值 |
136 | }catch(Exception e){ |
137 | //一旦發生異常,便將屬性值置爲UnKnown,故此處不必一一捕獲全部異常 |
138 | sb.append("\n").append(field.getName()).append("=UnKnown"); |
139 | continue; |
140 | } |
141 | if(fieldValue ==null){ |
142 | sb.append("\n").append(field.getName()).append("=null"); |
143 | }else{ |
144 | sb.append("\n").append(field.getName()).append("=").append(newString((byte[])fieldValue)); |
145 | } |
146 | } |
147 | returnsb.append("\n]").toString(); |
148 | } |
149 |
150 |
151 | /** |
152 | * 獲取Map中的屬性 |
153 | * @see 因爲Map.toString()打印出來的參數值對,是橫着一排的...參數多的時候,不便於查看各參數值 |
154 | * @see 故此仿照commons-lang.jar中的ReflectionToStringBuilder.toString()編寫了本方法 |
155 | * @return String key11=value11 \n key22=value22 \n key33=value33 \n...... |
156 | */ |
157 | publicstaticString getStringFromMap(Map<String, String> map){ |
158 | StringBuilder sb =newStringBuilder(); |
159 | sb.append(map.getClass().getName()).append("@").append(map.hashCode()).append("["); |
160 | for(Map.Entry<String,String> entry : map.entrySet()){ |
161 | sb.append("\n").append(entry.getKey()).append("=").append(entry.getValue()); |
162 | } |
163 | returnsb.append("\n]").toString(); |
164 | } |
165 |
166 |
167 | /** |
168 | * 獲取Map中的屬性 |
169 | * @see 該方法的參數適用於打印Map<String, byte[]>的狀況 |
170 | * @return String key11=value11 \n key22=value22 \n key33=value33 \n...... |
171 | */ |
172 | publicstaticString getStringFromMapForByte(Map<String,byte[]> map){ |
173 | StringBuilder sb =newStringBuilder(); |
174 | sb.append(map.getClass().getName()).append("@").append(map.hashCode()).append("["); |
175 | for(Map.Entry<String,byte[]> entry : map.entrySet()){ |
176 | sb.append("\n").append(entry.getKey()).append("=").append(newString(entry.getValue())); |
177 | } |
178 | returnsb.append("\n]").toString(); |
179 | } |
180 |
181 |
182 | /** |
183 | * 獲取Map中的屬性 |
184 | * @see 該方法的參數適用於打印Map<String, Object>的狀況 |
185 | * @return String key11=value11 \n key22=value22 \n key33=value33 \n...... |
186 | */ |
187 | publicstaticString getStringFromMapForObject(Map<String, Object> map){ |
188 | StringBuilder sb =newStringBuilder(); |
189 | sb.append(map.getClass().getName()).append("@").append(map.hashCode()).append("["); |
190 | for(Map.Entry<String,Object> entry : map.entrySet()){ |
191 | sb.append("\n").append(entry.getKey()).append("=").append(entry.getValue().toString()); |
192 | } |
193 | returnsb.append("\n]").toString(); |
194 | } |
195 |
196 |
197 | /** |
198 | * 金額元轉分 |
199 | * @see 注意:該方法可處理貳仟萬之內的金額,且如有小數位,則不限小數位的長度 |
200 | * @see 注意:若是你的金額達到了貳仟萬以上,則不推薦使用該方法,不然計算出來的結果會使人大吃一驚 |
201 | * @param amount 金額的元進制字符串 |
202 | * @return String 金額的分進制字符串 |
203 | */ |
204 | publicstaticString moneyYuanToFen(String amount){ |
205 | if(isEmpty(amount)){ |
206 | returnamount; |
207 | } |
208 | //傳入的金額字符串表明的是一個整數 |
209 | if(-1== amount.indexOf(".")){ |
210 | returnInteger.parseInt(amount) *100+""; |
211 | } |
212 | //傳入的金額字符串裏面含小數點-->取小數點前面的字符串,並將之轉換成單位爲分的整數表示 |
213 | intmoney_fen = Integer.parseInt(amount.substring(0, amount.indexOf("."))) *100; |
214 | //取到小數點後面的字符串 |
215 | String pointBehind = (amount.substring(amount.indexOf(".") +1)); |
216 | //amount=12.3 |
217 | if(pointBehind.length() ==1){ |
218 | returnmoney_fen + Integer.parseInt(pointBehind)*10+""; |
219 | } |
220 | //小數點後面的第一位字符串的整數表示 |
221 | intpointString_1 = Integer.parseInt(pointBehind.substring(0,1)); |
222 | //小數點後面的第二位字符串的整數表示 |
223 | intpointString_2 = Integer.parseInt(pointBehind.substring(1,2)); |
224 | //amount==12.03,amount=12.00,amount=12.30 |
225 | if(pointString_1 ==0){ |
226 | returnmoney_fen + pointString_2 +""; |
227 | }else{ |
228 | returnmoney_fen + pointString_1*10+ pointString_2 +""; |
229 | } |
230 | } |
231 |
232 |
233 | /** |
234 | * 金額元轉分 |
235 | * @see 該方法會將金額中小數點後面的數值,四捨五入後只保留兩位....如12.345-->12.35 |
236 | * @see 注意:該方法可處理貳仟萬之內的金額 |
237 | * @see 注意:若是你的金額達到了貳仟萬以上,則很是不建議使用該方法,不然計算出來的結果會使人大吃一驚 |
238 | * @param amount 金額的元進制字符串 |
239 | * @return String 金額的分進制字符串 |
240 | */ |
241 | publicstaticString moneyYuanToFenByRound(String amount){ |
242 | if(isEmpty(amount)){ |
243 | returnamount; |
244 | } |
245 | if(-1== amount.indexOf(".")){ |
246 | returnInteger.parseInt(amount) *100+""; |
247 | } |
248 | intmoney_fen = Integer.parseInt(amount.substring(0, amount.indexOf("."))) *100; |
249 | String pointBehind = (amount.substring(amount.indexOf(".") +1)); |
250 | if(pointBehind.length() ==1){ |
251 | returnmoney_fen + Integer.parseInt(pointBehind)*10+""; |
252 | } |
253 | intpointString_1 = Integer.parseInt(pointBehind.substring(0,1)); |
254 | intpointString_2 = Integer.parseInt(pointBehind.substring(1,2)); |
255 | //下面這種方式用於處理pointBehind=245,286,295,298,995,998等須要四捨五入的狀況 |
256 | if(pointBehind.length() >2){ |
257 | intpointString_3 = Integer.parseInt(pointBehind.substring(2,3)); |
258 | if(pointString_3 >=5){ |
259 | if(pointString_2 ==9){ |
260 | if(pointString_1 ==9){ |
261 | money_fen = money_fen +100; |
262 | pointString_1 =0; |
263 | pointString_2 =0; |
264 | }else{ |
265 | pointString_1 = pointString_1 +1; |
266 | pointString_2 =0; |
267 | } |
268 | }else{ |
269 | pointString_2 = pointString_2 +1; |
270 | } |
271 | } |
272 | } |
273 | if(pointString_1 ==0){ |
274 | returnmoney_fen + pointString_2 +""; |
275 | }else{ |
276 | returnmoney_fen + pointString_1*10+ pointString_2 +""; |
277 | } |
278 | } |
279 |
280 |
281 | /** |
282 | * 金額分轉元 |
283 | * @see 注意:若是傳入的參數中含小數點,則直接原樣返回 |
284 | * @see 該方法返回的金額字符串格式爲<code>00.00</code>,其整數位有且至少有一個,小數位有且長度固定爲2 |
285 | * @param amount 金額的分進制字符串 |
286 | * @return String 金額的元進制字符串 |
287 | */ |
288 | publicstaticString moneyFenToYuan(String amount){ |
289 | if(isEmpty(amount)){ |
290 | returnamount; |
291 | } |
292 | if(amount.indexOf(".") > -1){ |
293 | returnamount; |
294 | } |
295 | if(amount.length() ==1){ |
296 | return"0.0"+ amount; |
297 | }elseif(amount.length() ==2){ |
298 | return"0."+ amount; |
299 | }else{ |
300 | returnamount.substring(0, amount.length()-2) +"."+ amount.substring(amount.length()-2); |
301 | } |
302 | } |
303 |
304 |
305 | /** |
306 | * 字節數組轉爲字符串 |
307 | * @see 該方法默認以ISO-8859-1轉碼 |
308 | * @see 若想本身指定字符集,可使用<code>getString(byte[] data, String charset)</code>方法 |
309 | */ |
310 | publicstaticString getString(byte[] data){ |
311 | returngetString(data,"ISO-8859-1"); |
312 | } |
313 |
314 |
315 | /** |
316 | * 字節數組轉爲字符串 |
317 | * @see 若是系統不支持所傳入的<code>charset</code>字符集,則按照系統默認字符集進行轉換 |
318 | */ |
319 | publicstaticString getString(byte[] data, String charset){ |
320 | if(isEmpty(data)){ |
321 | return""; |
322 | } |
323 | if(isEmpty(charset)){ |
324 | returnnewString(data); |
325 | } |
326 | try{ |
327 | returnnewString(data, charset); |
328 | }catch(UnsupportedEncodingException e) { |
329 | LogUtil.getLogger().error("將byte數組["+ data +"]轉爲String時發生異常:系統不支持該字符集["+ charset +"]"); |
330 | returnnewString(data); |
331 | } |
332 | } |
333 |
334 |
335 | /** |
336 | * 獲取一個字符串的簡明效果 |
337 | * @return String 返回的字符串格式相似於"abcd***hijk" |
338 | */ |
339 | publicstaticString getStringSimple(String data){ |
340 | returndata.substring(0,4) +"***"+ data.substring(data.length()-4); |
341 | } |
342 |
343 |
344 | /** |
345 | * 字符串轉爲字節數組 |
346 | * @see 該方法默認以ISO-8859-1轉碼 |
347 | * @see 若想本身指定字符集,可使用<code>getBytes(String str, String charset)</code>方法 |
348 | */ |
349 | publicstaticbyte[] getBytes(String data){ |
350 | returngetBytes(data,"ISO-8859-1"); |
351 | } |
352 |
353 |
354 | /** |
355 | * 字符串轉爲字節數組 |
356 | * @see 若是系統不支持所傳入的<code>charset</code>字符集,則按照系統默認字符集進行轉換 |
357 | */ |
358 | publicstaticbyte[] getBytes(String data, String charset){ |
359 | data = (data==null?"": data); |
360 | if(isEmpty(charset)){ |
361 | returndata.getBytes(); |
362 | } |
363 | try{ |
364 | returndata.getBytes(charset); |
365 | }catch(UnsupportedEncodingException e) { |
366 | LogUtil.getLogger().error("將字符串["+ data +"]轉爲byte[]時發生異常:系統不支持該字符集["+ charset +"]"); |
367 | returndata.getBytes(); |
368 | } |
369 | } |
370 |
371 |
372 | /** |
373 | * 根據指定的簽名密鑰和算法簽名Map<String,String> |
374 | * @see 方法內部首先會過濾Map<String,String>參數中的部分鍵值對 |
375 | * @see 過濾規則:移除鍵名爲"cert","hmac","signMsg"或者鍵值爲null或者鍵值長度爲零的鍵值對 |
376 | * @see 過濾結果:過濾完Map<String,String>後會產生一個字符串,其格式爲[key11=value11|key22=value22|key33=value33] |
378 | * @param param 待簽名的Map<String,String> |
379 | * @param charset 簽名時轉碼用到的字符集 |
380 | * @param algorithm 簽名時所使用的算法,從業務上看,目前其可傳入兩個值:MD5,SHA-1 |
381 | * @param signKey 簽名用到的密鑰 |
382 | * @return String algorithm digest as a lowerCase hex string |
383 | */ |
384 | publicstaticString getHexSign(Map<String, String> param, String charset, String algorithm, String signKey){ |
385 | StringBuilder sb =newStringBuilder(); |
386 | List<String> keys =newArrayList<String>(param.keySet()); |
387 | Collections.sort(keys); |
388 | for(inti=0; i<keys.size(); i++){ |
389 | String key = keys.get(i); |
390 | String value = param.get(key); |
391 | if(key.equalsIgnoreCase("cert") || key.equalsIgnoreCase("hmac") || key.equalsIgnoreCase("signMsg") || value==null|| value.length()==0){ |
392 | continue; |
393 | } |
394 | sb.append(key).append("=").append(value).append("|"); |
395 | } |
396 | sb.append("key=").append(signKey); |
397 | returngetHexSign(sb.toString(), charset, algorithm,true); |
398 | } |
399 |
400 |
401 | /** |
402 | * 經過指定算法簽名字符串 |
403 | * @see Calculates the algorithm digest and returns the value as a hex string |
404 | * @see If system dosen't support this <code>algorithm</code>, return "" not null |
406 | * @see 若系統不支持<code>charset</code>字符集,則按照系統默認字符集進行轉換 |
407 | * @see 若系統不支持<code>algorithm</code>算法,則直接返回""空字符串 |
408 | * @see 另外,commons-codec.jar提供的DigestUtils.md5Hex(String data)與本方法getHexSign(data, "UTF-8", "MD5", false)效果相同 |
409 | * @param data Data to digest |
410 | * @param charset 字符串轉碼爲byte[]時使用的字符集 |
411 | * @param algorithm 目前其有效值爲<code>MD5,SHA,SHA1,SHA-1,SHA-256,SHA-384,SHA-512</code> |
412 | * @param toLowerCase 指定是否返回小寫形式的十六進制字符串 |
413 | * @return String algorithm digest as a lowerCase hex string |
414 | */ |
415 | publicstaticString getHexSign(String data, String charset, String algorithm,booleantoLowerCase){ |
416 | char[] DIGITS_LOWER = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; |
417 | char[] DIGITS_UPPER = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; |
418 | //Used to build output as Hex |
419 | char[] DIGITS = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER; |
420 | //get byte[] from {@link TradePortalUtil#getBytes(String, String)} |
421 | byte[] dataBytes = getBytes(data, charset); |
422 | byte[] algorithmData =null; |
423 | try{ |
424 | //get an algorithm digest instance |
425 | algorithmData = MessageDigest.getInstance(algorithm).digest(dataBytes); |
426 | }catch(NoSuchAlgorithmException e) { |
427 | LogUtil.getLogger().error("簽名字符串["+ data +"]時發生異常:System doesn't support this algorithm["+ algorithm +"]"); |
428 | return""; |
429 | } |
430 | char[] respData =newchar[algorithmData.length <<1]; |
431 | //two characters form the hex value |
432 | for(inti=0,j=0; i<algorithmData.length; i++){ |
433 | respData[j++] = DIGITS[(0xF0& algorithmData[i]) >>>4]; |
434 | respData[j++] = DIGITS[0x0F& algorithmData[i]]; |
435 | } |
436 | returnnewString(respData); |
437 | } |
438 |
439 |
440 | /** |
441 | * 字符編碼 |
442 | * @see 該方法默認會以UTF-8編碼字符串 |
443 | * @see 若想本身指定字符集,可使用<code>encode(String chinese, String charset)</code>方法 |
444 | */ |
445 | publicstaticString encode(String chinese){ |
446 | returnencode(chinese,"UTF-8"); |
447 | } |
448 |
449 |
450 | /** |
451 | * 字符編碼 |
452 | * @see 該方法一般用於對中文進行編碼 |
453 | * @see 若系統不支持指定的編碼字符集,則直接將<code>chinese</code>原樣返回 |
454 | */ |
455 | publicstaticString encode(String chinese, String charset){ |
456 | chinese = (chinese==null?"": chinese); |
457 | try{ |
458 | returnURLEncoder.encode(chinese, charset); |
459 | }catch(UnsupportedEncodingException e) { |
460 | LogUtil.getLogger().error("編碼字符串["+ chinese +"]時發生異常:系統不支持該字符集["+ charset +"]"); |
461 | returnchinese; |
462 | } |
463 | } |
464 |
465 |
466 | /** |
467 | * 字符解碼 |
468 | * @see 該方法默認會以UTF-8解碼字符串 |
469 | * @see 若想本身指定字符集,可使用<code>decode(String chinese, String charset)</code>方法 |
470 | */ |
471 | publicstaticString decode(String chinese){ |
472 | returndecode(chinese,"UTF-8"); |
473 | } |
474 |
475 |
476 | /** |
477 | * 字符解碼 |
478 | * @see 該方法一般用於對中文進行解碼 |
479 | * @see 若系統不支持指定的解碼字符集,則直接將<code>chinese</code>原樣返回 |
480 | */ |
481 | publicstaticString decode(String chinese, String charset){ |
482 | chinese = (chinese==null?"": chinese); |
483 | try{ |
484 | returnURLDecoder.decode(chinese, charset); |
485 | }catch(UnsupportedEncodingException e) { |
486 | LogUtil.getLogger().error("解碼字符串["+ chinese +"]時發生異常:系統不支持該字符集["+ charset +"]"); |
487 | returnchinese; |
488 | } |
489 | } |
490 |
491 |
492 | /** |
493 | * 字符串右補空格 |
494 | * @see 該方法默認採用空格(其ASCII碼爲32)來右補字符 |
495 | * @see 若想本身指定所補字符,可使用<code>rightPadForByte(String str, int size, int padStrByASCII)</code>方法 |
496 | */ |
497 | publicstaticString rightPadForByte(String str,intsize){ |
498 | returnrightPadForByte(str, size,32); |
499 | } |
500 |
501 |
502 | /** |
503 | * 字符串右補字符 |
504 | * @see 若str對應的byte[]長度不小於size,則按照size截取str對應的byte[],而非原樣返回str |
505 | * @see 因此size參數很關鍵..事實上之因此這麼處理,是因爲支付處理系統接口文檔規定了字段的最大長度 |
506 | * @see 若對普通字符串進行右補字符,建議org.apache.commons.lang.StringUtils.rightPad(...) |
507 | * @param size 該參數指的不是字符串長度,而是字符串所對應的byte[]長度 |
508 | * @param padStrByASCII 該值爲所補字符的ASCII碼,如32表示空格,48表示0,64表示@等 |
509 | */ |
510 | publicstaticString rightPadForByte(String str,intsize,intpadStrByASCII){ |
511 | byte[] srcByte = str.getBytes(); |
512 | byte[] destByte =null; |
513 | if(srcByte.length >= size){ |
514 | //因爲size不大於原數組長度,故該方法此時會按照size自動截取,它會在數組右側填充'(byte)0'以使其具備指定的長度 |
515 | destByte = Arrays.copyOf(srcByte, size); |
516 | }else{ |
517 | destByte = Arrays.copyOf(srcByte, size); |
518 | Arrays.fill(destByte, srcByte.length, size, (byte)padStrByASCII); |
519 | } |
520 | returnnewString(destByte); |
521 | } |
522 |
523 |
524 | /** |
525 | * 字符串左補空格 |
526 | * @see 該方法默認採用空格(其ASCII碼爲32)來左補字符 |
527 | * @see 若想本身指定所補字符,可使用<code>leftPadForByte(String str, int size, int padStrByASCII)</code>方法 |
528 | */ |
529 | publicstaticString leftPadForByte(String str,intsize){ |
530 | returnleftPadForByte(str, size,32); |
531 | } |
532 |
533 |
534 | /** |
535 | * 字符串左補字符 |
536 | * @see 若str對應的byte[]長度不小於size,則按照size截取str對應的byte[],而非原樣返回str |
537 | * @see 因此size參數很關鍵..事實上之因此這麼處理,是因爲支付處理系統接口文檔規定了字段的最大長度 |
538 | * @param padStrByASCII 該值爲所補字符的ASCII碼,如32表示空格,48表示0,64表示@等 |
539 | */ |
540 | publicstaticString leftPadForByte(String str,intsize,intpadStrByASCII){ |
541 | byte[] srcByte = str.getBytes(); |
542 | byte[] destByte =newbyte[size]; |
543 | Arrays.fill(destByte, (byte)padStrByASCII); |
544 | if(srcByte.length >= size){ |
545 | System.arraycopy(srcByte,0, destByte,0, size); |
546 | }else{ |
547 | System.arraycopy(srcByte,0, destByte, size-srcByte.length, srcByte.length); |
548 | } |
549 | returnnewString(destByte); |
550 | } |
551 |
552 |
553 | /** |
554 | * 獲取前一天日期yyyyMMdd |
555 | * @see 經測試,針對閏年02月份或跨年等狀況,該代碼仍有效。測試代碼以下 |
556 | * @see calendar.set(Calendar.YEAR, 2013); |
557 | * @see calendar.set(Calendar.MONTH, 0); |
558 | * @see calendar.set(Calendar.DATE, 1); |
559 | * @see 測試時,將其放到<code>calendar.add(Calendar.DATE, -1);</code>前面便可 |
560 | * @return 返回的日期格式爲yyyyMMdd |
561 | */ |
562 | publicstaticString getYestoday(){ |
563 | Calendar calendar = Calendar.getInstance(); |
564 | calendar.add(Calendar.DATE, -1); |
565 | returnnewSimpleDateFormat("yyyyMMdd").format(calendar.getTime()); |
566 | } |
567 |
568 |
569 | /** |
570 | * 獲取當前的日期yyyyMMdd |
571 | */ |
572 | publicstaticString getCurrentDate(){ |
573 | returnnewSimpleDateFormat("yyyyMMdd").format(newDate()); |
574 | } |
575 |
576 |
577 | /** |
578 | * 獲取當前的時間yyyyMMddHHmmss |
579 | */ |
580 | publicstaticString getCurrentTime(){ |
581 | returnnewSimpleDateFormat("yyyyMMddHHmmss").format(newDate()); |
582 | } |
583 |
584 |
585 | /** |
586 | * HTML字符轉義 |
587 | * @see 對輸入參數中的敏感字符進行過濾替換,防止用戶利用JavaScript等方式輸入惡意代碼 |
588 | * @see String input = <img src='http://t1.baidu.com/it/fm=0&gp=0.jpg'/> |
589 | * @see HtmlUtils.htmlEscape(input); //from spring.jar |
590 | * @see StringEscapeUtils.escapeHtml(input); //from commons-lang.jar |
591 | * @see 儘管Spring和Apache都提供了字符轉義的方法,但Apache的StringEscapeUtils功能要更強大一些 |
592 | * @see StringEscapeUtils提供了對HTML,Java,JavaScript,SQL,XML等字符的轉義和反轉義 |
593 | * @see 但兩者在轉義HTML字符時,都不會對單引號和空格進行轉義,而本方法則提供了對它們的轉義 |
594 | * @return String 過濾後的字符串 |
595 | */ |
596 | publicstaticString htmlEscape(String input) { |
597 | if(isEmpty(input)){ |
598 | returninput; |
599 | } |
600 | input = input.replaceAll("&","&"); |
601 | input = input.replaceAll("<","<"); |
602 | input = input.replaceAll(">",">"); |
603 | input = input.replaceAll(" "," "); |
604 | input = input.replaceAll("'","'"); //IE暫不支持單引號的實體名稱,而支持單引號的實體編號,故單引號轉義成實體編號,其它字符轉義成實體名稱 |
605 | input = input.replaceAll("\"",""");//雙引號也須要轉義,因此加一個斜線對其進行轉義 |
606 | input = input.replaceAll("\n","<br/>"); //不能把\n的過濾放在前面,由於還要對<和>過濾,這樣就會致使<br/>失效了 |
607 | returninput; |
608 | } |
609 | } |