在使用一个框架时,程序员分为三种级别
1.看demo开发
2.看文档开发
3.看源码开发
明显1不如2,2不如3
但是考虑时间成本3不如2,2不如1
我的原则是
有好的demo不看文档,有好的文档不看源码
对于文件下载,再简单不过了,但我比较傻,不会自己写
于是在google搜索"Spring mvc 3 download",demo版本都差不多
- @RequestMapping("download")
- public void download(HttpServletResponse res) throws IOException {
- OutputStream os = res.getOutputStream();
- try {
- res.reset();
- res.setHeader("Content-Disposition", "attachment; filename=dict.txt");
- res.setContentType("application/octet-stream; charset=utf-8");
- os.write(FileUtils.readFileToByteArray(getDictionaryFile()));
- os.flush();
- } finally {
- if (os != null) {
- os.close();
- }
- }
- }
因为鄙人强烈的精神洁癖,心中大骂
“这样的狗屁代码也贴在网上?”
既然使用了mvc,怎么还能暴露HttpServletResponse这样的j2ee接口出来!
我相信spring提供了更好的方式,于是开始翻阅文档,得出如下代码
- @RequestMapping("download")
- public ResponseEntity<byte[]> download() throws IOException {
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
- headers.setContentDispositionFormData("attachment", "dict.txt");
- return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(getDictionaryFile()),
- headers, HttpStatus.CREATED);
- }
理论上没问题,实现上很优雅
但是文件下载后内容如下
- "YWEJMQ0KdnYJMg0KaGgJMw=="
正确内容为
- aa 1
- vv 2
- hh 3
我把代码改为
- ResponseEntity<String>
输出如下
- "aa 1\n\tvv 2\n\thh 3"
相信很多人看到这已经知道了发生了什么
但是因为本人狗屎一样的基础知识,又浪费了几小时
先去看了ByteArrayHttpMessageConverter的源码
- public ByteArrayHttpMessageConverter() {
- super(new MediaType("application", "octet-stream"), MediaType.ALL);
- }
- ...
- protected void writeInternal(byte[] bytes, HttpOutputMessage outputMessage) throws IOException {
- FileCopyUtils.copy(bytes, outputMessage.getBody());
- }
没感觉到有任何问题
捉耳挠腮了一阵子,又去看AnnotationMethodHandlerAdapter
- public AnnotationMethodHandlerAdapter() {
- // no restriction of HTTP methods by default
- super(false);
- // See SPR-7316
- StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
- stringHttpMessageConverter.setWriteAcceptCharset(false);
- //这里有默认值
- this.messageConverters = new HttpMessageConverter[]{new ByteArrayHttpMessageConverter(), stringHttpMessageConverter,
- new SourceHttpMessageConverter(), new XmlAwareFormHttpMessageConverter()};
- //set时默认值全被取消了
- public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {
- this.messageConverters = messageConverters;
再去看MappingJacksonHttpMessageConverter
- extends AbstractHttpMessageConverter<Object>//Object是万用的,就想Exception类型,优先级别应该最低
突然有一种自己是个傻 逼的感觉,浪费了大概3、4个小时
修改xml
- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
- <property name="messageConverters">
- <list>
- //把ByteArray加在Json前面
- <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
- <bean id="jsonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
- <property name = "supportedMediaTypes">
- <list>
- <value>text/plain;charset=UTF-8</value>
- </list>
- </property>
- </bean>
- </list>
- </property>
- </bean>
终于如我所愿了
记录一下我这几个小时干的蠢事
顺便想说,每个例子和demo最好都以最佳实践去写
这样我这种菜鸟程序员就没机会去看源码了~
http://www.iteye.com/topic/1125784