关于spring controller 中注入 response

最近产品使用上了spring mvc 。喜欢其使用方法参数方式接受http中的参数列表,这样可以很直观的看到某个接口需要什么样的输入。

鉴于简单方便,我们让所有的接口都返回json的数据。于是按照最简单的办法就是拿取response,获取其writer后输出 json文本。

关于response 的获取,网络上基本都是使用方法参数传入的方式:

public void doSome(String uid,String pwd,HttpServletResquest request,HttpServletResponse response){
       //..........
}

 但是我有点代码洁癖,我想能否通过别的方式来获取response,从而让方法的参数简洁一致的全都是业务参数。各种百度谷歌之后,发现都答不上来。不过有人使用Filter 拦截,并将Response放到 ThreadLocal中,供后面使用。

@Component("responseHolderFilter")
public class ResponseHolderFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		LOGGER.info("ResponseHolderFilter init");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		System.out.println(request);
		System.out.println(response);
		ResponseHolder.set((HttpServletResponse)response);
		try{
			chain.doFilter(request, response);
		}finally{
			ResponseHolder.clear();
		}
	}

	@Override
	public void destroy() {
		LOGGER.info("ResponseHolderFilter destroy");
	}
	
	private static final Logger LOGGER = LoggerFactory.getLogger(ResponseHolderFilter.class);

}

 
按照此法,确实拿到了Response实例,也能获取Writer,并输出json。但是看页面提示404,找不到jsp页面。经过测试,如果使用 方法参数传入方式获取的Response 来输出json,那么就正常,浏览器直接显示了json内容。经过测试发现,如果Controller的方法中声明传入了Response对象,那么会在一个Resolver里设置一个ModelAndView的一个requestHandled属性为true,然后等待Controller方法执行完成之后和渲染页面之前,如果Controller 的方法没有返回值,并且requestHandled这个属性是true,那么就基本算是跳过渲染,返回给客户,于是呼浏览器就看到了json。

而为什么我们在Controller方法里没有传入Response对象的情况下,而只是用ThreadLocal中保存的Response对象输出json,就没会报错404 呢,就是因为刚才 requestHandled 属性没有被设置为true,于是即便Controller 方法返回的是null,spring也会寻找一个jsp进行渲染,默认就是使用Controller方法的访问地址作加上jsp作为页面查找路径(如/um/center/login.jsp)。

到此还没有满意的办法来杜绝在Controller的方法中使用Response参数。

猜你喜欢

转载自kangzye.iteye.com/blog/2274314