2013年马上就要过去了,总结一些近期工作中出现的一些问题
(1)int的包装类型比较时始终不相等
项目中比较id时,始终都不相等,预期是相等的,当时快搞疯了,搞了半天才明白:id的类型是interger,而integer是对象,不能直接使用==来比较

@test
public void test_integer(){
integer a=new integer(2);
integer b=new integer(2);
system.out.println(a==b);
system.out.println(a==(int)b);
system.out.println(a.intvalue()==b.intvalue());
}
运行结果:
注意下面的结果:
(2)启动web项目时报错:找不到缓存类ecache

<bean id="sessionfactory"
class="org.springframework.orm.hibernate3.localsessionfactorybean">
<property name="datasource" ref="datasource" />
<property name="packagestoscan">
<list>
<value>com.kingbase.domain</value>
</list>
</property>
<property name="hibernateproperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.mysqldialect
</prop>
<!-- <prop key="hibernate.dialect">
org.hibernate.dialect.postgresqldialect
</prop> -->
<!--<prop key="hibernate.max_fetch_depth">0</prop>
-->
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</bean>
(3)servlet中的成员变量是所有请求共用的
以下是一个普通的servlet:

package com.shop.jn.web.servlet;
import java.io.ioexception;
import java.io.printwriter;
import javax.servlet.servletexception;
import javax.servlet.http.httpservlet;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
public class testservlet extends httpservlet {
private static final long serialversionuid = 3853433476973310016l;
private int count=0;
/**
* constructor of the object.
*/
public testservlet() {
super();
* destruction of the servlet. <br>
public void destroy() {
super.destroy(); // just puts "destroy" string in log
public void doget(httpservletrequest request, httpservletresponse response)
throws servletexception, ioexception {
response.setcontenttype("text/html");
printwriter out = response.getwriter();
out.println("<!doctype html public \"-//w3c//dtd html 4.01 transitional//en\">");
out.println("<html>");
out.println(" <head><title>a servlet</title></head>");
out.println(" <body>");
out.print(" this is ");
out.print(this.getclass());
out.println(", using the get method");
out.println(" </body>");
out.println("</html>");
out.flush();
out.close();
count++;
system.out.println("count:"+count);
public void dopost(httpservletrequest request, httpservletresponse response)
out.println(", using the post method");
}
里面有一个成员变量count,初始值是0,每次使用浏览器访问(get方法)时会递增1,会打印count的值。
运行结果如下:
count:1
count:2
count:3
count:4
count:5
。。。
注意:在不同的电脑上访问,也是递增一,而不是重新从0开始计数,即使用的同一份count。
总结:尽管每次请求使用的是不同的线程(一般情况下)来处理,但是这些线程使用的都是同一个servlet对象,所以servlet中的成员变量不是线程安全的。如果非要在servlet中使用成员变量应该怎么办呢?
在做一个商品管理系统的时候,我有一个aop 类logintimesaop,需要拦截userservice 中的一个方法,目的是记录用户连续登录失败的次数,若连续登录失败3次,则锁定不允许再登录。
aop配置如下:

<aop:config>
<aop:pointcut id="userservicepointcut"
expression="execution(* com.shop.jn.service.userservice.login(..)) and args(..,user2)" />
<aop:aspect id="myaspect" ref="logintimesaop">
<aop:around pointcut-ref="userservicepointcut" method="around"
arg-names="school,user2" />
</aop:aspect>
</aop:config>
但是始终没有像预期的那样拦截,要拦截的方法如下:

@override
/****
* not allowed to be rewritten
* @return : [state,user object]
public object[] login(final actioncontext actioncontext,
final genericuser user) throws unsupportedencodingexception,
exception {
// logger.info("login(actioncontext actioncontext,user user)");
object[] results = new object[2];
if (user == null) {
results[0] = loginutil.login_result_username_null;
return results;
} else {
return login(user.getusername(), user.getpassword());
}
上述方法是在com.shop.jn.service.userservice的父类suserservice中。
最终找到了原因:因为我要拦截的方法不在userservice中,尽管是可以从父类suserservice继承的。
修改方法:
方式一:把父类也包含进去
<aop:pointcut id="userservicepointcut"
expression="(execution(* com.shop.jn.service.userservice.login(..)) or
execution( * com.common.service.impl.suserservice.login(..)) ) and args(..,user2)" />
<aop:aspect id="myaspect" ref="logintimesaop">
<!--<aop:before method="before3" arg-names="user2"pointcut-ref="userservicepointcut"
/> -->
<aop:around pointcut-ref="userservicepointcut"method="around"
arg-names="user2" />
</aop:aspect>
或者:
方式二:直接匹配父类,因为方法就在父类中
expression="execution(*com.common.service.impl.suserservice.login(..)) and args(..,user2)" />
(5)struts2 的form标签,会自动把当前的路径附加到表单提交的action的前面
商品管理系统有商品管理和超市管理,若没有登录直接进入就会跳转到登录页面。
后来我直接看页面源码才发现问题。
浏览器中的源码是:
怎么凭空多出了上述红框中的内容?
但是登录页面jsp源码如下:
如果我把登录jsp源码改为:
在浏览器中查看源码就是:

<form id="user_login" name="user_login" action="/shop_goods/supermarket/user/login.action" method="post">
结论就是:使用<s:form标签时,会自动把当前的路径附加到表单提交的action的前面
解决方法:
方式一:使用原生的form表单:

<form action="<%=basepath%>user/login" method="post" >
<table>
<tr><td>username:</td> <td><s:textfield name="user.username" value="admin" ></s:textfield> </td></tr>
<tr><td>password:</td> <td><s:textfield name="user.password" value="admin2" ></s:textfield> </td></tr>
<tr> <td colspan="2"><s:submit value="login" ></s:submit> </td></tr>
</table>
<form>
方式二:
使用s:url 标签,例如:
action='<s:url action="login" />'
欢迎访问 http://hw1287789687.iteye.com/blog/2053907