springmvc拦截器对于流对象传输的拦截

lisongchuang 2013-09-12

      当前的项目中存在下面一种场景:web应用的某个功能中,jsp中加载的某个插件需要将数据提交给web服务端。插件中通过ObjectOutputStream向web端传输数据,但springmvc的拦截器会提前读取该流对象,那么配置指定的Action就无法再读取到该Stream的内容,会导致如下异常:

java.io.EOFException
	at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
	at java.io.ObjectInputStream.readObject0(Unknown Source)
	at java.io.ObjectInputStream.readObject(Unknown Source)

由于整个项目的controler层用的springmvc框架,所以目前的解决办法是编写一个独立的servlet来单独针对该数据的接收。

因为采用注解的方式将配置service并交给spring管理,而需要编写的servlet需要注入这些service,所以这边采用代理的方式实现:

第一步:编写代理类HttpServletProxy

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.common.Logger;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * @description
 * @author minux
 * @date 2013-9-2 下午2:16:22
 */
public class HttpServletProxy extends HttpServlet {

	private static final long serialVersionUID = -2934353313384038254L;

	public static Logger logger = Logger.getLogger(HttpServletProxy.class);

	private String targetServlet;
	private HttpServlet proxy;

	public void init() throws ServletException {
		this.targetServlet = getInitParameter("targetServlet");
		getServletBean();
		proxy.init(getServletConfig());
		logger.info(targetServlet
				+ " was inited by HttpServletProxy  successfully......");

	}

	private void getServletBean() {
		WebApplicationContext wac = WebApplicationContextUtils
				.getRequiredWebApplicationContext(getServletContext());
		this.proxy = (HttpServlet) wac.getBean(targetServlet);

	}

	public void service(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException, RuntimeException {
		proxy.service(request, response);
	}
}

第二步:在web.xml中配置改代理servlet

<servlet>
		<servlet-name>ComplexWebLoadTestServletProxy</servlet-name>
		<servlet-class>cn.hxcomm.web.controller.HttpServletProxy</servlet-class>
		<init-param>
			<param-name>targetServlet</param-name>
			<param-value>complexWebLoadTestServlet</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>ComplexWebLoadTestServletProxy</servlet-name>
		<url-pattern>/complexWebLoadTestServlet.do</url-pattern>
	</servlet-mapping>

第三步:编写真正实现功能的ComplexWebLoadTestServlet并注解注入

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Timestamp;
import java.util.Calendar;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.common.Logger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.hxcomm.common.domain.ComplexWebLoadTestDetail;
import cn.hxcomm.web.service.ComplexWebLoadTestService;

/**
 * @description
 * @author minux
 * @date 2013-8-30 下午3:44:02
 */
@Service("complexWebLoadTestServlet")
public class ComplexWebLoadTestServlet extends HttpServlet {

	private static final long serialVersionUID = -371252886055302137L;

	public static Logger logger = Logger
			.getLogger(ComplexWebLoadTestServlet.class);

	@Autowired
	private ComplexWebLoadTestService complexWebLoadTestService;

	public ComplexWebLoadTestServlet() {
		super();
	}

	public void init() throws ServletException {
		super.init();
	}

	public void service(HttpServletRequest requeset,
			HttpServletResponse response) throws ServletException, IOException,
			RuntimeException {
		this.doWork(requeset, response);
	}

	private void doWork(HttpServletRequest request, HttpServletResponse response) {
			}

}

这样基本就可以实现绕开拦截器提前读取stream的情况。

当然servlet注入service的也有其他的实现方式,比如可以直接不需要代理servlet,直接编写servlet读取需要的配置文件,然后取出需要的service的bean对象。

但是个人感觉代理的方式更方便扩展和管理。springmvc拦截器对于流对象传输的拦截

相关推荐