0

我所有的控制器都扩展了以下抽象类:

public abstract class AbstractController {

    public HttpServletRequest request;
    public HttpServletResponse response;
    public ModelMap model;

}

此外,我实现了以下拦截器:

public class HttpRequestInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {
        if (handler instanceof AbstractController) {
            AbstractController controller = (AbstractController) handler;
            controller.request = request;
            controller.response = response;
            controller.model = new ModelMap();
        }
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        if (handler instanceof AbstractController && modelAndView != null) {
            AbstractController controller = (AbstractController) handler;
            modelAndView.addAllObjects(controller.model);
        }
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }

}

这是我发现的改进代码分解的解决方案,因为您不需要在控制器中传递request、 theresponsemodelas 方法参数。该解决方案工作正常,直到我发现这个问题:

public class HomeController extends AbstractController {

    @RequestMapping
    public void download1() {
        // use the parent attribute response
        File file = new File(MY_FILE_PATH);
        InputStream in = new BufferedInputStream(new FileInputStream(file));
        ServletOutputStream out = response.getOutputStream();
        IOUtils.copy(in, out);
        response.flushBuffer();
    }

    @RequestMapping
    public void download2(HttpServletResponse response) {
        // use the response passed as parameter
        File file = new File(MY_FILE_PATH);
        InputStream in = new BufferedInputStream(new FileInputStream(file));
        ServletOutputStream out = response.getOutputStream();
        IOUtils.copy(in, out);
        response.flushBuffer();
    }

}

上述两种方法都使浏览器下载文件,但是download1一种生成了一个空文件,而download2生成了应有的原始文件。知道为什么吗?

感谢调试器,我注意到在postHandle拦截器的方法中,该download2方法生成了一个modelAndViewwhich equals null,而该方法生成了download1一个实例化的。这应该对这个问题意味着什么,但我找不到什么。

response当作为控制器方法的参数传递时如何获得实例化?

4

2 回答 2

7

不要这样做:

public abstract class AbstractController {

    public HttpServletRequest request;
    public HttpServletResponse response;
    public ModelMap model;

}

控制器中的实例变量(其默认范围为单例)是个坏主意。

于 2012-09-17T13:02:45.443 回答
3

做这样的事情(到一个txt文件):

@RequestMapping(value="/download", method=RequestMethod.GET, produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public String download(HttpServletResponse response) throws IOException {
    response.setContentType("application/force-download");
    FileReader fr = new FileReader("/folder/file.extension");
    return IOUtils.toString(fr); // IOUtils come from Apache Commons IO
}
于 2012-12-12T19:03:32.547 回答