📄 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构造原则:
* 1.url第一个参数以'-'连接,其他均以查询参数构造。SEO 搜索规则下,'-'连字符不宜超过2个,因此只尝试静态化第一个参数。
* 2.由于第一个参数针对 append() 的第一次调用,或 map 的 iterator 第一个 next() 值。Action 与页面“定位”没有直接关系,故均以查询参数构造。
* ..a:因此在设置参数map时,须注意该参数应对“页面定位”有帮助,如:bbs的主题列表的"forumID"、用户信息的"uuserID"
* 3.第一个参数不得包含 '/' 字符,若包含则以动态参数构造,此时意味者所有参数都是查询方式构造的。原因如下:
* ..若参数字符name or value包含 '/' 或 '-,则该参数以动态url方式构造,原因:
* ..a:'/':tomcat 6.x 会报错:"HTTP 400 - 错误请求"
* ..b:'-'或其他参数分隔连接。避免构造的性能损失
* ..另:若第一个参数值是null,则该参数也会以“查询参数”方式构造。因为此时在静态化参数已经无意义。
* 4.确实需要静态参数连接的,可直接调用 append(XXX,YYY,staic)
* 5.map参数全部强制构造为查询参数
* 6.其他参见{@link Link}说明
*/
/* encode 静态变量 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 静态变量 end */
final static String UCI = "uci";//unique component id
final static char sp = '-';
final static char sl = '/'; //静态参数若包含此字符,tomcat 6.x下会出现错误:"HTTP 400 - 错误请求"
final static String spx = "%2d"; // 参数值中'-'的url形式
final static String qa = "&"; //查询参数将,是否需要设置为"&" 呢 ?
private AbstractComponent co = null;
private String pageName = null;
private boolean append = false; //是否'-'方式构造了静态化参数
StringBuffer buf = new StringBuffer();
private boolean staticParamAppend = false; //第一次静态url参数是否已经构造。注:第一次构造调用即为true(无论构造成功与否),其他参数的"页面定位"意义不明确。
private String anchor = null;
private Map params = null;
private int len = -1; //保存静态参数url base 的长的,便于 Link 对象化操作(如:clone(),getURL(),toString())后也能append()
private StringBuffer qbuf = new StringBuffer(0); //保存动态查询参数 e.g: a=XXX&b=YYY
private int qBufLen = -1; //保存动态查询参数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);//静态参数添加失败则以动态参数添加
}
}
}
if (b) {
encodeURLParamQueryString(param, value);
}
return this;
}
/* 编码静态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;
}
/* 编码查询参数 */
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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -