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
原因:项目使用的是hibernate 4的jar包,而配置文件中仍然使用hibernate3:
<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> </property> </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)
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 POST method");
out.println(" </BODY>");
out.println("</HTML>");
out.flush();
out.close();
}
}
里面有一个成员变量count,初始值是0,每次使用浏览器访问(Get方法)时会递增1,会打印count的值。
运行结果如下:
count:1
count:2
count:3
count:4
count:5
。。。
注意:在不同的电脑上访问,也是递增一,而不是重新从0开始计数,即使用的同一份count。
总结:尽管每次请求使用的是不同的线程(一般情况下)来处理,但是这些线程使用的都是同一个servlet对象,所以servlet中的成员变量不是线程安全的。如果非要在servlet中使用成员变量应该怎么办呢?
像struts2 一样使用ThreadLocal ,参考http://blog.csdn.net/cselmu9/article/details/9128397
(4)spring aop没有拦截我要拦截的方法
在做一个商品管理系统的时候,我有一个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继承的。
参考:http://hw1287789687.iteye.com/blog/1882540
修改方法:
方式一:把父类也包含进去
<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> |
或者:
方式二:直接匹配父类,因为方法就在父类中
<aop:pointcut id="userServicePointcut" expression="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> |
(5)struts2 的form标签,会自动把当前的路径附加到表单提交的action的前面
商品管理系统有商品管理和超市管理,若没有登录直接进入就会跳转到登录页面。
比如直接在浏览器中输入http://localhost:8084/shop_goods/supermarket/viewSupermarket.action ,会自动跳转到登录页面。但是登录时报错,而直接进入登录页面登录就没有问题。这个问题折磨了一天半。
后来我直接看页面源码才发现问题。
浏览器中的源码是:
怎么凭空多出了上述红框中的内容?
但是登录页面JSP源码如下:
如果我把登录JSP源码改为:
在浏览器中查看源码就是:
<form id="user_login" name="user_login" action="/shop_goods/supermarket/user/login.action" method="post">
本来登录要提交到 http://localhost:8084/shop_goods/user/login.action
结果它给我提交到了http://localhost:8084/shop_goods/supermarket/user/login.action
结论就是:使用<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