博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringMVC 完美解决PUT请求参数绑定问题(普通表单和文件表单)
阅读量:5334 次
发布时间:2019-06-15

本文共 4770 字,大约阅读时间需要 15 分钟。

一 解决方案

修改web.xml配置文件 将下面配置拷贝进去(在原有的web-app节点里面配置 其它配置不变)

httpPutFormContentFilter
org.springframework.web.filter.HttpPutFormContentFilter
httpPutFormContentFilter
/*

写一个PostAndPutCommonsMultipartResolver继承CommonsMultipartResolver 重写isMultipart()

/** * 处理PUT提交参数(只对文件表单生效) * Created by Hy on 2018/9/30. */public class PostAndPutCommonsMultipartResolver extends CommonsMultipartResolver {    @Override    public boolean isMultipart(HttpServletRequest request) {        if ("POST".equalsIgnoreCase(request.getMethod()) || "PUT".equalsIgnoreCase(request.getMethod())) {            return FileUploadBase.isMultipartContent(new ServletRequestContext(request));        }        return false;    }}

修改spring-mvc.xml配置文件 将下面配置拷贝进去(在原有的beans节点里面配置 其它配置不变)

写一个Controller

/** * PUT请求 * Created by Hy on 2018/9/30. */@Controllerpublic class PutController {    @PutMapping("/put/normal") @ResponseBody    public String normalForm(String name, Integer age) {        System.out.println("name = " + name);        System.out.println("age = " + age);        return "ok";    }    @PutMapping("/put/file") @ResponseBody    public String fileForm(String name, MultipartFile file) throws Exception {        System.out.println("name = " + name);        if (null != file && !file.isEmpty()) {            System.out.println("file = " + file.getSize());            // 保存图片            String fileName = UUID.randomUUID().toString().replace("-", ""); //文件名            String extension = FilenameUtils.getExtension(file.getOriginalFilename()); //扩展名 不包含(.)            file.transferTo(new File("/Users/HUANGYI/Downloads/" + fileName + "." + extension));            return "ok";        }        return "error";    }}

以上就能完美解决PUT请求参数绑定问题 赶时间的老哥可以忽略下文

 

二 解决思路

先bb一下起因

我最近再重构一个自己的项目 打算把接口交互修改成RESTful风格 浅显的说一下RESTful风格 增删改查对应POST DELETE PUT GET请求

环境

客户端: Android 使用Retrofit发起请求

服务端: Java 使用SpringMVC处理请求

思路

客户端使用PUT请求发送表单数据 不管是普通表单还是文件表单 服务端Controller层参数绑定均为null

但是 客户端使用PUT请求发送非文件数据携带在Url上(类似GET请求) 服务端Controller层参数就能接收到

为了避免重复造轮子 我用Google解决了普通表单数据接收不到 也就是使用上面说的org.springframework.web.filter.HttpPutFormContentFilter就可以解决该问题

但是 文件表单数据还是接收不到 Google也不好用了 不知道是不是我姿势不对

自己尝试解决吧

先验证文件表单数据到底写入请求体没有?

我用logging-interceptor和Charles观察了好几遍请求 确认了数据确实已经写入了请求体

那么 问题肯定就出现在SpringMVC的文件参数绑定上

仔细观察org.springframework.web.multipart.commons.CommonsMultipartResolver

其中 isMultipart()是一个比较重要的方法 用来判断请求是否包含多部分内容 也就是判断是否是文件表单 深入观察一下该方法的实现

真相大白 该方法默认POST请求才可能包含多部分内容

使用上面说的PostAndPutCommonsMultipartResolver就可以解决该问题

Android客户端核心代码

/** * ... * Created by Hy on 2018/9/30. */public interface PutApi {    @PUT("/put/normal") @FormUrlEncoded    Call
normal(@Field("name") String name, @Field("age") Integer age); @PUT("/put/file") @Multipart Call
file(@Part("name") String name, @Part MultipartBody.Part file);}
@Overridepublic void onClick(View view) {    switch (view.getId()) {        case R.id.normal:            Call
normalCall = mApi.normal("黄祎", 18); normalCall.enqueue(new Callback
() { @Override public void onResponse(Call
call, Response
response) { try { Log.i("HUANG", "code = " + response.code()); if (null != response.body()) Log.i("HUANG", "body = " + response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call
call, Throwable t) { Log.i("HUANG", "t = " + t.getMessage()); } }); break; case R.id.file: RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), copy()); MultipartBody.Part body = MultipartBody.Part.createFormData("file", "a.mp4", fileBody); Call
fileCall = mApi.file("黄祎", body); fileCall.enqueue(new Callback
() { @Override public void onResponse(Call
call, Response
response) { try { Log.i("HUANG", "code = " + response.code()); if (null != response.body()) Log.i("HUANG", "body = " + response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call
call, Throwable t) { Log.i("HUANG", "t = " + t.getMessage()); } }); break; }}

总结

虽然只是寥寥几句 但是我走完这几步也花了一下午时间 哈哈哈 技术有限技术有限

希望能帮助到你 如果你的问题得到解决 请给个推荐点个赞 这样能帮助到更多人 毕竟搜索不到解决方案的时候太痛苦了

 

转载于:https://www.cnblogs.com/huangyi-427/p/9742000.html

你可能感兴趣的文章
UVa 10970 - Big Chocolate
查看>>
js输出
查看>>
H5多文本换行
查看>>
HAL层三类函数及其作用
查看>>
Odoo 去掉 恼人的 "上午"和"下午"
查看>>
web@h,c小总结
查看>>
java编程思想笔记(一)——面向对象导论
查看>>
Data Structure 基本概念
查看>>
Ubuntu改坏sudoers后无法使用sudo的解决办法
查看>>
NEYC 2017 游记
查看>>
[搬运] 写给 C# 开发人员的函数式编程
查看>>
Python之旅Day14 JQuery部分
查看>>
core--线程池
查看>>
redux-effect
查看>>
Swift和OC混编
查看>>
Android轻量级的开源缓存框架ASimpleCache
查看>>
他山之石:加载图片的一个小问题
查看>>
shell - 常识
查看>>
mssql sqlserver 使用sql脚本 清空所有数据库表数据的方法分享
查看>>
分层图最短路【bzoj2763】: [JLOI2011]飞行路线
查看>>