#
背景:
加密的cookie信息中帶有特殊字符(“=”),導(dǎo)致讀cookie的時(shí)候,特殊符號(hào)丟失,解密失敗
看了同事“關(guān)于cookie特殊字符”的說(shuō)明郵件,和網(wǎng)上對(duì)cookie特殊字符問題的解釋:
我們?cè)趯?shí)際使用Cookie過程中要注意一些問題:
1. Cookie的兼容性問題
Cookie的格式有2個(gè)不同的版本,第一個(gè)版本,我們稱為Cookie Version 0,是最初由Netscape公司制定的,也被幾乎所有的瀏覽器支持。而較新的版本,Cookie Version 1,則是根據(jù)RFC 2109文檔制定的。為了確保兼容性,JAVA規(guī)定,前面所提到的涉及Cookie的操作都是針對(duì)舊版本的Cookie進(jìn)行的。而新版本的Cookie目前還不被Javax.servlet.http.Cookie包所支持。
2. Cookie的內(nèi)容
同樣的Cookie的內(nèi)容的字符限制針對(duì)不同的Cookie版本也有不同。在Cookie Version 0中,某些特殊的字符,例如:空格,方括號(hào),圓括號(hào),等于號(hào)(=),逗號(hào),雙引號(hào),斜杠,問號(hào),@符號(hào),冒號(hào),分號(hào)都不能作為Cookie的內(nèi)容。這也就是為什么我們?cè)诶又性O(shè)定Cookie的內(nèi)容為“Test_Content”的原因。
雖然在Cookie Version 1規(guī)定中放寬了限制,可以使用這些字符,但是考慮到新版本的Cookie規(guī)范目前仍然沒有為所有的瀏覽器所支持,因而為保險(xiǎn)起見,我們應(yīng)該在Cookie的內(nèi)容中盡量避免使用這些字符。
摘自:
http://swingchen.bokee.com/6200015.html
類似這樣的解釋,搜索出來(lái)的結(jié)果,挺多。
但是,我去看了RFC2109(
http://www.faqs.org/rfcs/rfc2109.html),其說(shuō)明如下:

value中的token,是有一組非特殊字符,非空白字符。而它是在RFC 2068(
http://www.faqs.org/rfcs/rfc2068.html)中制定的 (是對(duì)Header的規(guī)范),請(qǐng)看:
也就是說(shuō),所謂的Cookie1,同樣有特殊字符的限制。
同樣,在Cookie2(RFC2965)中,也如此。
想想也是啊,如果沒有特殊字符的限制,解析Header的時(shí)候,還不亂套了?
看了RFC之后,我們?cè)賮?lái)看看Tomcat中的實(shí)現(xiàn)(6.0.29版本),請(qǐng)看:
org.apache.tomcat.util.http.Cookies
1.類注釋:
A collection of cookies - reusable and tuned for server side performance.
Based on RFC2965 ( and 2109 )
是基于RFC2965/RFC2109規(guī)范來(lái)實(shí)現(xiàn)的
2.特殊字符的定義
/*
List of Separator Characters (see isSeparator())
Excluding the '/' char violates the RFC, but
it looks like a lot of people put '/'
in unquoted values: '/': ; //47
'\t':9 ' ':32 '\"':34 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60
'=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
*/
public static final char SEPARATORS[] = { '\t', ' ', '\"', '(', ')', ',',
':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
根據(jù)規(guī)范,定義了特殊字符。除了“/”這個(gè)符號(hào)。因?yàn)榇蠖鄶?shù)人會(huì)直接使用“/”。
3.針對(duì)“=”特殊處理
/**
* If true, cookie values are allowed to contain an equals character without
* being quoted.
*/
public static final boolean ALLOW_EQUALS_IN_VALUE;
static {
ALLOW_EQUALS_IN_VALUE = Boolean.valueOf(System.getProperty(
"org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE",
"false")).booleanValue();
}
可以在catalina.properties中,添加這個(gè)配置項(xiàng) (或者啟動(dòng)過程中加上-D參數(shù)),使得cookie value中允許存在“=”符號(hào)。
所以本文開頭提到的問題,可以使用這個(gè)方法得到解決
4.解析過程
/**
* Parses a cookie header after the initial "Cookie:"
* [WS][$]token[WS]=[WS](token|QV)[;|,]
* RFC 2965
* JVK
*/
public final void processCookieHeader(byte bytes[], int off, int len){
//詳細(xì)代碼,省略
}
備注:
RFC沒有仔細(xì)看(時(shí)間有限,并且看E文挺累的),如理解有誤,請(qǐng)告知。
摘要: 會(huì)開車了,也慢慢不規(guī)矩起來(lái)了,于是乎,違章信息也慢慢多起來(lái)了,但是無(wú)法第一時(shí)間通知到自己。
雖說(shuō),有個(gè)網(wǎng)站:http://www.hzti.com/service/qry/violation_veh.aspx?pgid=&type=1&node=249
可以查詢非現(xiàn)場(chǎng)違章情況,
不過:
1.我是懶人,主動(dòng)去查詢的時(shí)候不太樂意做
2.車輛識(shí)別碼,永遠(yuǎn)記不住
3.每次輸驗(yàn)證...
閱讀全文
原文地址:
http://weblogs.java.net/blog/caroljmcdonald/archive/2009/09/17/some-java-concurrency-tips
大綱:
Prefer immutable objects/data
盡可能使用不變對(duì)象/數(shù)據(jù)
Threading risks for Web applications
注意web應(yīng)用的線程安全問題
Hold Locks for as short a time as possible
持有鎖的時(shí)間盡可能短
Prefer executors and tasks to threads
盡可能使用JDK并發(fā)工具包提供的Executor框架,進(jìn)行多線程操作
Prefer Concurrency utilities to wait and notify
盡可能使用JDK并發(fā)工具包提供的工具進(jìn)行同步(等待和通知)
- Concurrent Collections
- ConcurrentMap
- ConcurrentHashMap
- COncurrentLinkedQueue
- CopyOnWriteArrayList
- BlockingQueue Implementations
- ArrayBlockingQueue
- LinkedBlockingQueue
- PriorityBlockingQueue
Producer Consumer Pattern
了解生產(chǎn)者消費(fèi)者模式
Synchronizers
同步器
- Semaphore
- CountDownLatch
- CyclicBarrier
- Exchanger
Multithreaded Lazy Initialization is tricky
多線程環(huán)境下,lazy init是一件棘手的事情
Prefer Normal initialization
盡可能使用正常的初始化(盡可能不要使用lazy init)
摘要: java反射效率到底如何,花了點(diǎn)時(shí)間,做了一個(gè)簡(jiǎn)單的測(cè)試.供大家參考.
測(cè)試背景:
1. 測(cè)試簡(jiǎn)單Bean(int,Integer,String)的set方法
2. loop 1億次
3. 測(cè)試代碼盡可能避免對(duì)象的創(chuàng)建,復(fù)發(fā)方法的調(diào)用,僅僅測(cè)試set方法的耗時(shí)
測(cè)試結(jié)果:
場(chǎng)景
&...
閱讀全文
在說(shuō)另類思路之前,先說(shuō)下傳統(tǒng)的測(cè)試方法:
0.準(zhǔn)備一個(gè)干凈的測(cè)試數(shù)據(jù)庫(kù)環(huán)境
這個(gè)是前提
1.測(cè)試數(shù)據(jù)準(zhǔn)備
使用文本,excel,或者wiki等,準(zhǔn)備測(cè)試sql以及測(cè)試數(shù)據(jù)
利用dbfit,dbutil等工具將準(zhǔn)備的測(cè)試數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫(kù)中
2.執(zhí)行dao方法
執(zhí)行被測(cè)試的dao方法
3.測(cè)試結(jié)果斷言
利用dbfit,dbutil等工具,斷言測(cè)試結(jié)果數(shù)據(jù)和預(yù)計(jì)是否一致
4.所有數(shù)據(jù)回滾
其實(shí),對(duì)于這個(gè)流程來(lái)說(shuō),目前的dao測(cè)試框架,支持的已經(jīng)比較完美了
但是此類測(cè)試方法,也有明顯的缺點(diǎn)(或者不能叫缺點(diǎn),叫使用比較麻煩的地方)
如下:
1.背上了一個(gè)數(shù)據(jù)庫(kù)環(huán)境.
不輕量
這是一個(gè)共享環(huán)境,誰(shuí)也無(wú)法確保環(huán)境數(shù)據(jù)是否真正的干凈
2.測(cè)試數(shù)據(jù)準(zhǔn)備是一件麻煩的事情
新表,10幾個(gè)字段毫不為奇;老表,50幾個(gè)字段甚至百來(lái)個(gè)字段,也偶有可見;無(wú)論是使用文本,excel,wiki,準(zhǔn)備工作量,都是巨大的.
準(zhǔn)備的數(shù)據(jù),部分字段內(nèi)容可以是無(wú)意義的,部分字段內(nèi)容又是需要符合測(cè)試意圖(testcase設(shè)計(jì)目的),部分字段還是其他表的關(guān)聯(lián)字段.從而導(dǎo)致后續(xù)維護(hù)人員無(wú)法了解準(zhǔn)備數(shù)據(jù)意圖.
(實(shí)踐中,也出現(xiàn)過,一同事在維護(hù)他人單元測(cè)試時(shí),由于無(wú)法了解測(cè)試數(shù)據(jù)準(zhǔn)備意圖,寧可重新刪除,自己準(zhǔn)備一份)
3.預(yù)計(jì)結(jié)果數(shù)據(jù)準(zhǔn)備也是一件麻煩的事情
理由如上
所以,理論上是完美的測(cè)試方案,在實(shí)踐過程中,卻是一件麻煩的事情.導(dǎo)致DAO單元測(cè)試維護(hù)困難.
分析了現(xiàn)狀,我們?cè)賮?lái)分析下,IBatis下DAO,程序員主要做了哪些編碼:
1. 寫了一份sqlmap.xml配置文件
2. 通過
getSqlMapClientTemplate.doSomething($sqlID,$param), 執(zhí)行語(yǔ)句
(當(dāng)然,沒有使用spring的同學(xué),也是使用了類似sqlMapClient.doSomething($sqlID,$param)方法)
而步驟2其實(shí)是框架替我們做了的事情,按照MOCK的思想,其實(shí)這部分代碼可以被MOCK的,那么我們是否可以做如下假設(shè):
只要sqlmap.xml中配置信息(主要包括resultmap和statement)是正確的,那么執(zhí)行結(jié)果也應(yīng)該是正確的.
而我所謂的另類思路,就是基于這個(gè)假設(shè),得出的:
IBatis下,DAO單元測(cè)試,我們拋棄背負(fù)的數(shù)據(jù)庫(kù)環(huán)境,只要根據(jù)不同的條件,斷言不同的sql即可.
于是乎,封裝了一個(gè)IbatisSqlTester,可以根據(jù)sqlmap中的statement和傳入的條件參數(shù),生成sql語(yǔ)句.
那么,DAO單元測(cè)試就簡(jiǎn)單了,脫離下數(shù)據(jù)庫(kù)環(huán)境:
public class ScoreDAOTest extends TestCase {
@SpringBeanByName
private IbatisSqlTester ibatisSqlTester; //通過spring配置,需要注入sqlmapclient對(duì)象
@Test
public void testListTpScores() {
Map<String, Object> param = new HashMap<String, Object>(1);
param.put("memberIds", new String[] { "stone", "stone2083" });
SqlStatement sql = ibatisSqlTester.test("MS-LIST-SCORES", param);
// sql全部匹配
SqlAssert.isEqual("select * from score where member_id in ('stone','stone2083')", sql.toString());
// sql包含member_id,athena2002,stone關(guān)鍵詞
SqlAssert.keyWith(sql.toString(), "member_id", "stone", "stone2083");
// sql符合某個(gè) 正則
SqlAssert.regexWith(".* where member_id in .*", sql.toString());
//其中,SqlAssert也可以換 成want.string()中的方法.
}
}
優(yōu)勢(shì):
脫離了數(shù)據(jù)庫(kù)環(huán)境
脫離了表結(jié)構(gòu)數(shù)據(jù)準(zhǔn)備
脫離了預(yù)計(jì)結(jié)果數(shù)據(jù)準(zhǔn)備
讓單元測(cè)試變成sql的斷言,編寫相對(duì)更簡(jiǎn)單
缺點(diǎn):
row mapper過程無(wú)法被測(cè)試
最后,附上兩個(gè)核心的代碼類(還未完成),供大家參考:
SqlStatement.java
/**
* <pre>
* SqlStatement:Sql語(yǔ)句對(duì)象.
* 包含:
* 1.sql語(yǔ)句,類似 select * from offer where id = ? and member_id = ?
* 2.參數(shù)值,類似 [1,stone2083]
*
* toString方法,返回執(zhí)行的sql語(yǔ)句,如:
* select * from offer where id = '1' and member_id = 'stone2083'
* </pre>
*
* @author Stone.J 2010-8-9 下午02:55:36
*/
public class SqlStatement {
//sql
private String sql;
//sql參數(shù)
private Object[] param;
/**
* <pre>
* 輸出最終執(zhí)行的sql內(nèi)容.
* 將sql和param進(jìn)行merge,產(chǎn)生最終執(zhí)行的sql語(yǔ)句
* </pre>
*/
@Override
public String toString() {
return merge();
}
/**
* <pre>
* 將sql進(jìn)行格式化.
*
* 目前只是簡(jiǎn)單進(jìn)行格式化.去除前后空格,已經(jīng)重復(fù)空格
* TODO:請(qǐng)使用統(tǒng)一格式化標(biāo)準(zhǔn)規(guī),建議使用SqlFormater類,進(jìn)行處理
* </pre>
*
* @param sql
* @return
*/
protected String format(String sql) {
if (sql == null) {
return null;
}
return sql.toLowerCase().trim().replaceAll("\\s{1,}", " ");
}
/**
* <pre>
* 將sql和param進(jìn)行merge.
* TODO:請(qǐng)嚴(yán)格按照SQL標(biāo)準(zhǔn),進(jìn)行merge sql內(nèi)容
* </pre>
*/
protected String merge() {
if (param == null || param.length == 0) {
return this.sql;
}
String ret = sql;
for (Object p : param) {
ret = ret.replaceFirst("\\?", "'" + p.toString() + "'");
}
return ret;
}
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = format(sql);
}
public Object[] getParam() {
return param;
}
public void setParam(Object[] param) {
this.param = param;
}
}
IbatisSqlTester.java
/**
* <pre>
* IBtatis SQL 測(cè)試
* 一般IBatis DAO單元測(cè)試,主要就是在測(cè)試ibatis的配置文件.
* IbatisSqlTester將根據(jù)提供的Sql Map Id 和 對(duì)應(yīng)的參數(shù),返回 {@link SqlStatement}對(duì)象,提供最終執(zhí)行的sql語(yǔ)句
* 通過外部SqlAssert對(duì)象,將預(yù)計(jì)Sql和實(shí)際產(chǎn)生的Sql進(jìn)行對(duì)比,判斷是否正確
* </pre>
*
* @author Stone.J 2010-8-9 下午02:58:46
*/
public class IbatisSqlTester {
// sqlMapClient
private ExtendedSqlMapClient sqlMapClient;
/**
* 根據(jù)提供的SqlMap ID,得到 {@link SqlStatement}對(duì)象
*
* @param sqlId: sql map id
* @return @see {@link SqlStatement}
*/
public SqlStatement test(String sqlId) {
//得到MappedStatement對(duì)象
MappedStatement ms = sqlMapClient.getMappedStatement(sqlId);
if (ms == null) {
//TODO:建議封轉(zhuǎn)自己的異常對(duì)象
throw new RuntimeException("can't find MappedStatement.");
}
//按照Ibatis代碼,得到Sql和Param信息
RequestScope request = new RequestScope();
ms.initRequest(request);
Sql sql = ms.getSql();
String sqlValue = sql.getSql(request, null);
//組轉(zhuǎn)返回對(duì)象
SqlStatement ret = new SqlStatement();
ret.setSql(sqlValue);
return ret;
}
/**
* 根據(jù)提供的SqlMap ID和對(duì)應(yīng)的param信息,得到 {@link SqlStatement}對(duì)象
*
* @param sqlId: sql map id
* @param param: 參數(shù)內(nèi)容
* @return @see {@link SqlStatement}
*/
public SqlStatement test(String sqlId, Object param) {
//得到MappedStatement對(duì)象
MappedStatement ms = sqlMapClient.getMappedStatement(sqlId);
if (ms == null) {
//TODO:建議封轉(zhuǎn)自己的異常對(duì)象
throw new RuntimeException("can't find MappedStatement.");
}
//按照Ibatis代碼,得到Sql和Param信息
RequestScope request = new RequestScope();
ms.initRequest(request);
Sql sql = ms.getSql();
String sqlValue = sql.getSql(request, param);
Object[] sqlParam = sql.getParameterMap(request, param).getParameterObjectValues(request, param);
//組轉(zhuǎn)返回對(duì)象
SqlStatement ret = new SqlStatement();
ret.setSql(sqlValue);
ret.setParam(sqlParam);
return ret;
}
/**
* 設(shè)置SqlMapClient對(duì)象
*/
public void setSqlMapClient(ExtendedSqlMapClient sqlMapClient) {
this.sqlMapClient = sqlMapClient;
}
/**
* <pre>
* 不推薦使用
* 推薦使用: {@link IbatisSqlTester#setSqlMapClient(ExtendedSqlMapClient)}
* TODO:請(qǐng)去除這個(gè)方法,或者增加初始化的方式
* </pre>
*
* @param sqlMapConfig sqlMapConfig xml文件
*/
public void setSqlMapConfig(String sqlMapConfig) {
InputStream in = null;
try {
File file = ResourceUtils.getFile(sqlMapConfig);
in = new FileInputStream(file);
this.sqlMapClient = (ExtendedSqlMapClient) SqlMapClientBuilder.buildSqlMapClient(in);
} catch (Exception e) {
throw new RuntimeException("sqlMapConfig init error.", e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
}
}
最后的最后附上所有代碼(通過單元測(cè)試代碼,可以看如何使用).歡迎大家的討論.
sqltester
builder
很早之前,為了簡(jiǎn)化配置信息,自己寫了一坨代碼,基于classpath掃描類信息,加載.
其實(shí),在spring中,已經(jīng)提供了類似組件(后知后覺了...):
org.springframework.core.io.support.PathMatchingResourcePatternResolver 資源解析器(基于路徑的正則表達(dá)式)
org.springframework.core.type.classreading.MetadataReader ClassMeta信息解讀器
于是乎,代碼就非常簡(jiǎn)單了:
1 public class Test {
2
3 /* 資源路徑 */
4 private static final String PATH = "classpath*:com/alibaba/javalab/t*/**/*.class";
5 /* 資源解析器 */
6 private static final ResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver();
7 /* Meta信息Reader Factory.用于創(chuàng)建MetaReader */
8 private static final MetadataReaderFactory READER_FACTORY = new SimpleMetadataReaderFactory();
9
10 public static void main(String[] args) throws Exception {
11 //根據(jù)正則表達(dá)式,得到資源列表
12 Resource[] resources = RESOLVER.getResources(PATH);
13 for (Resource res : resources) {
14 //通過 MetadataReader得到ClassMeta信息,打印類名
15 MetadataReader meta = READER_FACTORY.getMetadataReader(res);
16 System.out.println(meta.getClassMetadata().getClassName());
17 }
18 }
19 }
輸出結(jié)果:
com.alibaba.javalab.tool.fetion.protocol.Config
com.alibaba.javalab.tool.fetion.protocol.Fetion
com.alibaba.javalab.tool.fetion.protocol.FetionHelper
com.alibaba.javalab.tool.fetion.protocol.LoginSession
com.alibaba.javalab.tool.trace.TimeTrace
...
挺好使的一個(gè)工具 :)
一直來(lái)只知道ThreadLocal,直到最近看slf4j MDC實(shí)現(xiàn)代碼的時(shí)候,才認(rèn)識(shí)了InheritableThreadLocal.
InheritableThreadLocal顧名思義,可繼承的ThreadLocal.
看類描述:
This class extends <tt>ThreadLocal</tt> to provide inheritance of values
* from parent thread to child thread: when a child thread is created, the
* child receives initial values for all inheritable thread-local variables
* for which the parent has values.
測(cè)試代碼:
1 public class Test {
2
3 public static void main(String[] args) {
4 //使用ThreadLocal,父子線程之間,不共享Value
5 final ThreadLocal<String> tl = new ThreadLocal<String>();
6 tl.set("ThreadLocal-VAL");
7 System.out.println("Main-1:" + tl.get());
8 new Thread() {
9 public void run() {
10 System.out.println("Child-1:" + tl.get());
11 };
12 }.start();
13
14 //使用InheritableThreadLocal,父線程Value可讓子線程共享
15 final ThreadLocal<String> itl = new InheritableThreadLocal<String>();
16 itl.set("InheritableThreadLocal-VAL");
17 System.out.println("Main-2:" + itl.get());
18 new Thread() {
19 public void run() {
20 System.out.println("Child-2:" + itl.get());
21 };
22 }.start();
23
24 }
25 }
輸出內(nèi)容:
Main-1:ThreadLocal-VAL
Main-2:InheritableThreadLocal-VAL
Child-1:null
Child-2:InheritableThreadLocal-VAL
......分隔符號(hào)......
順帶著簡(jiǎn)單說(shuō)下MDC.(Mapped Diagnostic Context). 中文直譯太惡心了,我理解的意思是,和環(huán)境相關(guān)的上下文信息.
比如在web應(yīng)用中,我們可以把用戶的ip,訪問url等放入到這個(gè)上下文中,log打印的時(shí)候,就能得到這個(gè)信息.
在slf4j BasicMDCAdapter實(shí)現(xiàn)中,就是用了InheritableThreadLocal
1 public class BasicMDCAdapter implements MDCAdapter {
2
3 private InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
4
5 //
.
6
7 }
背景:讓應(yīng)用在一個(gè)環(huán)境下,以多實(shí)例的方法運(yùn)行.
Log問題,可以通過Log4j占位符實(shí)現(xiàn)(見前文:
http://www.aygfsteel.com/stone2083/archive/2010/07/01/324935.html)
其他Java組件代碼依賴了本地環(huán)境資源,怎么解決呢?
對(duì)于使用Spring的組件來(lái)說(shuō),PropertyPlaceholderConfigurer能幫我們解決這一問題.
PropertyPlaceholderConfigurer除了支持配置的properties文件外,還支持系統(tǒng)屬性(System.getProperties()).當(dāng)然,它有三種模式:
1/** Never check system properties. */
2public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
3
4/**
5 * Check system properties if not resolvable in the specified properties.
6 * This is the default.
7 */
8public static final int SYSTEM_PROPERTIES_MODE_FALLBACK = 1;
9
10/**
11 * Check system properties first, before trying the specified properties.
12 * This allows system properties to override any other property source.
13 */
14public static final int SYSTEM_PROPERTIES_MODE_OVERRIDE = 2;
對(duì)于使用本地環(huán)境資源的bean來(lái)說(shuō),只要配置:
1 <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
2 <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
3 <property name="locations">
4 <list>
5 <value>classpath*:spring/env.properties</value> <!--無(wú)需配置node-->
6 </list>
7 </property>
8 </bean>
9
10 <bean id="javaBean" class="com.alibaba.javalab.spring.JavaBean">
11 <property name="lockFile" value="/home/stone/base/${node}/lock" />
12 </bean>
在啟動(dòng)腳本中,只要加入-Dnode=instanceX即可.
總結(jié):
PropertyPlaceholderConfigurer支持properties文件和系統(tǒng)屬性.并且存在三種覆蓋策略.
轉(zhuǎn)自:
http://blog.renren.com/blog/226112318/452978694
- 初次訪問發(fā)生在幾點(diǎn)幾分?
- 完全打開首頁(yè)花費(fèi)多少時(shí)間?
- 是否瀏覽完整個(gè)首頁(yè)后再去找login入口?
- 找login入口花了多少時(shí)間?
- 是否在服務(wù)器提示下找到入口?
- 在找到真正login頁(yè)面之前,是否誤入后臺(tái)login頁(yè)面?
- 是否使用XX助手找到入口?
- 輸錯(cuò)了幾次密碼后成功登陸?
- 在第一次成功登陸的時(shí)候,是否使用https(安全連接)?
- 登陸之前購(gòu)買了多少份https證書?
- 是否由于服務(wù)器帶寬太小導(dǎo)致登入很慢?
- 登陸成功后服務(wù)器是否發(fā)出提示音?
- 登陸之后產(chǎn)生了多少PV才最終下單?
- 服務(wù)器是否在初次下單后給出紅色回執(zhí)?
- 下單之后留在處于登陸狀態(tài)幾分鐘才離開?
- 整個(gè)訪問過程一共產(chǎn)生了幾個(gè)session?
- 平均session時(shí)長(zhǎng)是幾分鐘?
- 當(dāng)日訪問的cookie類型是cookie2.2還是3.1?
- 當(dāng)日一共下了多少單?
- 在之后的30日內(nèi)的活躍度類型(5次-18次屬于中度活躍度)
實(shí)踐經(jīng)驗(yàn):
1. 對(duì)于封閉式題目(回答是與否),比較沒勁:問問題的人描述了半天,回答者只回答一個(gè)是否者否.對(duì)于此類問題,要做改進(jìn)
2. 有些問題,都不好意思問出口
3. 千萬(wàn)要根據(jù)新人的性格,決定是否是否這套模板,切忌切忌
摘要: 背景:
大學(xué)里學(xué)java,老師口口聲聲,言之鑿鑿,告誡我們,Java千萬(wàn)別用異??刂茦I(yè)務(wù)流程,只有系統(tǒng)級(jí)別的問題,才能使用異常;
(當(dāng)時(shí),我們都不懂為什么不能用異常,只知道老師這么說(shuō),我們就這么做,考試才不會(huì)錯(cuò) :) )
公司里,有兩派.異常擁護(hù)者說(shuō),使用業(yè)務(wù)異常,代碼邏輯更清晰,更OOP;反之者說(shuō),使用異常,性能非常糟糕;
(當(dāng)然,我是擁護(hù)者)
論壇上,爭(zhēng)論得更多,仁者見仁智者見智,口...
閱讀全文