?? linkimpl.java
字號:
// Copyright 2005-2007 onetsoft.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.onetsoft.fastjsp;
import com.onetsoft.fastjsp.util.StringUtils;
import java.io.CharArrayWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.BitSet;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
/**
* @author <a href="mailto:hgw@onetsoft.com">hgw</a>
*/
class LinkImpl implements Link, Lifecycle {
/**
* URL構(gòu)造原則:
* 1.url第一個參數(shù)以'-'連接,其他均以查詢參數(shù)構(gòu)造。SEO 搜索規(guī)則下,'-'連字符不宜超過2個,因此只嘗試靜態(tài)化第一個參數(shù)。
* 2.由于第一個參數(shù)針對 append() 的第一次調(diào)用,或 map 的 iterator 第一個 next() 值。Action 與頁面“定位”沒有直接關(guān)系,故均以查詢參數(shù)構(gòu)造。
* ..a:因此在設(shè)置參數(shù)map時,須注意該參數(shù)應(yīng)對“頁面定位”有幫助,如:bbs的主題列表的"forumID"、用戶信息的"uuserID"
* 3.第一個參數(shù)不得包含 '/' 字符,若包含則以動態(tài)參數(shù)構(gòu)造,此時意味者所有參數(shù)都是查詢方式構(gòu)造的。原因如下:
* ..若參數(shù)字符name or value包含 '/' 或 '-,則該參數(shù)以動態(tài)url方式構(gòu)造,原因:
* ..a:'/':tomcat 6.x 會報錯:"HTTP 400 - 錯誤請求"
* ..b:'-'或其他參數(shù)分隔連接。避免構(gòu)造的性能損失
* ..另:若第一個參數(shù)值是null,則該參數(shù)也會以“查詢參數(shù)”方式構(gòu)造。因為此時在靜態(tài)化參數(shù)已經(jīng)無意義。
* 4.確實需要靜態(tài)參數(shù)連接的,可直接調(diào)用 append(XXX,YYY,staic)
* 5.map參數(shù)全部強制構(gòu)造為查詢參數(shù)
* 6.其他參見{@link Link}說明
*/
/* encode 靜態(tài)變量 begin */
static BitSet dontNeedEncoding;
static final int caseDiff = ('a' - 'A');
static {
dontNeedEncoding = new BitSet(256);
int i;
for (i = 'a'; i <= 'z'; i++) {
dontNeedEncoding.set(i);
}
for (i = 'A'; i <= 'Z'; i++) {
dontNeedEncoding.set(i);
}
for (i = '0'; i <= '9'; i++) {
dontNeedEncoding.set(i);
}
dontNeedEncoding.set(' '); /* encoding a space to a + is done
* in the encode() method */
dontNeedEncoding.set('-');
dontNeedEncoding.set('_');
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');
}
/* encode 靜態(tài)變量 end */
final static String UCI = "uci";//unique component id
final static char sp = '-';
final static char sl = '/'; //靜態(tài)參數(shù)若包含此字符,tomcat 6.x下會出現(xiàn)錯誤:"HTTP 400 - 錯誤請求"
final static String spx = "%2d"; // 參數(shù)值中'-'的url形式
final static String qa = "&"; //查詢參數(shù)將,是否需要設(shè)置為"&" 呢 ?
private AbstractComponent co = null;
private String pageName = null;
private boolean append = false; //是否'-'方式構(gòu)造了靜態(tài)化參數(shù)
StringBuffer buf = new StringBuffer();
private boolean staticParamAppend = false; //第一次靜態(tài)url參數(shù)是否已經(jīng)構(gòu)造。注:第一次構(gòu)造調(diào)用即為true(無論構(gòu)造成功與否),其他參數(shù)的"頁面定位"意義不明確。
private String anchor = null;
private Map params = null;
private int len = -1; //保存靜態(tài)參數(shù)url base 的長的,便于 Link 對象化操作(如:clone(),getURL(),toString())后也能append()
private StringBuffer qbuf = new StringBuffer(0); //保存動態(tài)查詢參數(shù) e.g: a=XXX&b=YYY
private int qBufLen = -1; //保存動態(tài)查詢參數(shù)url base 的長的,便于 Link 對象化操作(如:clone(),getURL(),toString())后也能append()
private CharArrayWriter charArrayWriter = new CharArrayWriter();
public LinkImpl() {
}
public LinkImpl setComponent(AbstractComponent co) {
this.co = co;
return this;
}
public LinkImpl setPageName(String pageName) {
this.pageName = pageName;
return this;
}
public void init() {
co.service.servicer.stateURL.encodeBeforeUrlBuild(this);
}
public void recycle() {
co = null;
pageName = null;
append = false;
staticParamAppend = false;
anchor = null;
if (params != null)
params.clear();
len = -1;
charArrayWriter.reset();
buf.delete(0, buf.length());
qbuf.delete(0, qbuf.length());
qBufLen = -1;
}
public Object clone() {
LinkImpl o = new LinkImpl();
o.co = co;
o.pageName = pageName;
o.append = append;
o.buf = new StringBuffer(buf.toString());
o.qbuf = new StringBuffer(qbuf.toString());
o.staticParamAppend = staticParamAppend;
o.anchor = anchor;
if (params != null)
o.params = new TreeMap(params);
o.len = len;
return o;
}
private void ensuedAppend() {
if (append) {
buf.append(sp);
} else {
buf.append(pageName).append('/');
append = true;
}
}
private void ensureBuffers() {
if (len != -1) {
buf.delete(len, buf.length());
len = -1;
}
if (qBufLen != -1) {
qbuf.delete(qBufLen, qbuf.length());
qBufLen = -1;
}
}
private Link appends(String param, String value, int paramPerfered) {
ensureBuffers();
if (value == null || value.length() == 0) {
encodeURLParamQueryString(param, value);
return this;
}
if (!(paramPerfered==Link.STATIC && encodeURLParamStatic(param, value))) {
encodeURLParamQueryString(param, value);
}
return this;
}
private Link appendq(String param, String value, boolean forceQueryString, boolean resetBufer) {
if (resetBufer)
ensureBuffers();
boolean b = true;
if (!forceQueryString) {
if (!staticParamAppend) {
staticParamAppend = true;
if (value != null && value.length() > 0) {
b = !encodeURLParamStatic(param, value);//靜態(tài)參數(shù)添加失敗則以動態(tài)參數(shù)添加
}
}
}
if (b) {
encodeURLParamQueryString(param, value);
}
return this;
}
/* 編碼靜態(tài)URL */
private boolean encodeURLParamStatic(String param, String value) {
if (value.indexOf(sl) != -1) return false;
ensuedAppend();
buf.append(param).append(sp);
encodeURLParam(buf, value, co.service.servicer.module.charset, true);
return true;
}
/* 編碼查詢參數(shù) */
private void encodeURLParamQueryString(String param, String value) {
/*存在特殊字符 */
if (qbuf.length() > 0) {
qbuf.append(qa);
}
qbuf.append(param).append('=');
if (value == null || value.length() == 0) {
qbuf.append(StringUtils.EMPTY);
} else {
encodeURLParam(qbuf, value, co.service.servicer.module.charset, false);
}
/* try {
if (value != null)
value = URLEncoder.encode(value, co.service.servicer.module.encoding);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (value != null)
qbuf.append(value);
else
qbuf.append(StringUtils.EMPTY);*/
}
public Link append(String param, String value) {
ensureBuffers();
return appendq(param, value, false, true);
}
public Link append(String param, String value, int paramPerfered) {
return appends(param, value, paramPerfered);
}
public Link append(String param, long value) {
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -