Struts2和SpringMVC整合方案(一):session回话管理

背景:项目中使用的框架是Struts2,为了开发效率等因素,添加SpringMVC支持。

问题解析:

Struts2获取session方法:通过Action上下文ActionContext获取;

Action上下文ActionContext详细介绍:http://blog.csdn.net/john2522/article/details/7436599

SpringMVC如何兼容Struts2,如何统一获取session取值,如何保证SpringMVC和Struts2取到的session唯一。

解决方法:

解决此类问题需要先找两个框架共性,即http请求都是基于servlet线程实现的,单次请求,从开始到业务处理结束,其实都是在一个线程中实现。

web请求图如下图:

所以问题解决的方法就是从请求线程入手,只要能保证每次请求的HttpServletRequest、HttpServletResponse取到的值一样即可。

故很容易想到使用ThreadLocal线程变量,为保证SpringMVC取到的session唯一,在SpringMVC请求和Struts2请求都加上一层过滤器(基于请求url正则匹配:SpringMVC为**.do格式,Struts2为**.action格式),将取到的含有session的请求HttpServletRequest放到置空的线程变量中,每次请求结束将线程变量置空。进而实现SpringMVC和Struts2兼容。

相关代码如下:

TheadLocal管理类:

public class ThreadLocalManager
{

	/** The Constant requestLocal. */
	private static final ThreadLocal<HttpServletRequest> REQUEST_LOCAL = new ThreadLocal<HttpServletRequest>();
	/** The Constant responseLocal. */
	private static final ThreadLocal<HttpServletResponse> RESPONSE_LOCAL = new ThreadLocal<HttpServletResponse>();

	/**
	 * set httpServletRequst
	 * @param request
	 */
	public static void setHttpServletRequest(HttpServletRequest request)
	{
		REQUEST_LOCAL.set(request);
	}

	public static HttpServletRequest getHttpServletRequest()
	{

		return REQUEST_LOCAL.get();
	}

	/**
	 * set httpServletResponse
	 * @param request
	 */
	public static void setHttpServletResponse(HttpServletResponse response)
	{

		RESPONSE_LOCAL.set(response);
	}

	/**
	 * get httpServletResponse
	 * @return
	 */
	public static HttpServletResponse getHttpServletResponse()
	{

		return RESPONSE_LOCAL.get();
	}

	/**
	 * 清理需要清理的threadlocal
	 */
	public static void clearAllThreadLocalIfNeeded()
	{
		RESPONSE_LOCAL.remove();
		REQUEST_LOCAL.remove();
	}
}

SpringMVC拦截器:

1、在请求线程开始前线程变量为空,设置线程变量值;

2、处理相关业务;

3、结束设置线程变量为空。

public class SpringMvcFilter extends DispatcherServlet
{
	private static final long serialVersionUID = -307292166973012590L;

	protected static Logger logger = LoggerFactory.getLogger(SpringMvcFilter.class);

	@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception
	{
		logger.info("mvc....");
		// threadlocal 清理,防止异常中断导致的脏数据
		ThreadLocalManager.clearAllThreadLocalIfNeeded();

		logger.info("------------start-------------");
		// 主要为了适配老代码里很多地方调用struts2filter里的静态方法,防止service取不到值
		ThreadLocalManager.setHttpServletRequest(request);
		ThreadLocalManager.setHttpServletResponse(response);

		long startTime = System.currentTimeMillis();

		try
		{
			HttpSession session = request.getSession();
			if (null == session.getAttribute("user"))
			{
				logger.warn("未取到用户session url:{}", request.getRequestURL());
				if (request.getHeader("x-requested-with") != null
						&& request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest"))
				{
					responseJson(response, "未取到用户session!");
					return;
				}
				try
				{
					response.sendRedirect("/index.action");
					return;
				}
				catch (IOException e1)
				{
					e1.printStackTrace();
				}
				return;
			}
			super.doService(request, response);
		}
		catch (Exception e)
		{
			logger.info(e.getMessage());
		}
		finally
		{
			logger.info("------------end-------------");
			ThreadLocalManager.clearAllThreadLocalIfNeeded();

			long endTime = System.currentTimeMillis();

			logger.info("SpringMvcFilter request:[url]:" + request.getRequestURI() + ",[cost]:" + (endTime - startTime));

		}
	}

	private static void responseJson(HttpServletResponse response, String content)
	{
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/json;charset=UTF-8");
		response.setHeader("Cache-Control", "no-cache");
		PrintWriter pw = null;
		try
		{
			pw = response.getWriter();
			pw.write(content);
			pw.flush();
		}
		catch (IOException e)
		{
			logger.error("响应结果失败", e);
		}
		finally
		{
			if (pw != null)
			{
				pw.close();
			}
		}
	}
}

同理Struts2拦截器类:

public class Struts2Filter extends StrutsPrepareAndExecuteFilter
{
	/** 日志. */
	protected static Logger logger = LoggerFactory.getLogger(Struts2Filter.class);

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
		ServletException
	{
		logger.info("struts2....");
		// 清理threadlocal,防止数据错乱
		ThreadLocalManager.clearAllThreadLocalIfNeeded();
		logger.info("------------start-------------");

		request.setCharacterEncoding("UTF-8");

		HttpServletRequest httpReq = (HttpServletRequest) request;
		HttpServletResponse httpRsp = (HttpServletResponse) response;

		ThreadLocalManager.setHttpServletRequest(httpReq);
		ThreadLocalManager.setHttpServletResponse(httpRsp);

		try
		{
			long startTime = System.currentTimeMillis();
			super.doFilter(httpReq, httpRsp, chain);
		}
		finally
		{
			logger.info("------------end-------------");
			ThreadLocalManager.clearAllThreadLocalIfNeeded();
		}
	}

	/**
	 * 获取当前线程的response.
	 * 
	 * @return the responseLocal
	 */
	public static HttpServletResponse getResponse()
	{
		return ThreadLocalManager.getHttpServletResponse();
		// return (HttpServletResponse) RESPONSE_LOCAL.get();
	}

	public static HttpSession getSession(boolean create)
	{
		HttpServletRequest req = ThreadLocalManager.getHttpServletRequest();
		if (req != null)
		{
			return req.getSession(create);
		}
		else
		{
			logger.info("未取到request");
		}
		return null;
	}

}

在web.xml中配置拦截器:

<filter>
	<filter-name>struts2</filter-name>
	<filter-class>
		com.**.**.core.filter.Struts2Filter
	</filter-class>
</filter>
<filter-mapping>
	<filter-name>struts2</filter-name>
	<url-pattern>*.action</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>FORWARD</dispatcher>
</filter-mapping>

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <!-- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>-->
    	<servlet-class>com.**.**.core.filter.SpringMvcFilter</servlet-class>  
    <init-param>
        <param-name>contextConfigLocation</param-name>
		<param-value>classpath*:META-INF/spring/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

 

转载于:https://my.oschina.net/wangchuandui/blog/1530162

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值