2013年工作中一些问题回顾和总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值