十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Servlet请求参数获取全解析:从getParameter到乱码排查

Servlet请求参数获取全解析:从getParameter到乱码排查 1. 为什么我决定把参获取这件事彻底理一遍先交代一下背景。我前阵子帮同事排查一个老项目的问题现象很典型前端提交的表单数据到了后端中文全部变成问号复选框选了三个值后端只拿到了最后一个。最后定位下来既不全是前端的问题也不全是后端的问题就是Servlet里获取参数这件事的几个关键细节没吃透。当时我就想这种基础中的基础网上的资料其实不少但多数讲得比较零散要么只讲getParameter()怎么用要么只贴一段解决乱码的过滤器代码很少有人把请求参数从浏览器到Servlet的完整链路讲明白。所以这篇笔记我想用我自己在项目里的排查思路重新梳理一遍HttpServletRequest获取参数的完整知识。核心内容围绕四块getParameter()这一类API到底怎么工作、GET和POST在传参机制上的本质区别、中文乱码到底是在哪一环出的问题、以及多值参数的正确打开方式。这篇东西适合谁看一种是刚学Servlet不久、被request.getParameter()各种细节磨得头疼的初学者另一种是工作了一两年能写代码但遇到乱码、多值丢失这种问题还是要靠搜索引擎救急的同学。我会把原理和实操都放到一起讲尽量让这篇笔记能当工具文来查。2. getParameter() 这套API的使用边界很多人第一步就没搞清2.1 三个最常用的方法各自的脾气不一样HttpServletRequest里跟参数相关的方法其实有十几个但日常开发中最常碰到的就三个getParameter()、getParameterValues()、getParameterMap()。先说明最核心的getParameter(String name)。它的作用是返回指定名称的参数值。这里有个特别容易踩的坑如果前端提交的参数名不存在它返回的是null不是空字符串。很多新手写代码直接拿返回值去判空结果NPE了还不知道怎么回事。我已经不止一次看到类似这样的代码String username request.getParameter(username); if (username.equals(admin)) { // 这里如果参数缺失直接空指针 // ... }正确写法应该是先判null或者用admin.equals(username)这种把常量放前面的写法。再说getParameterValues(String name)。这个方法返回的是String[]数组专门用来接收同一名称对应多个值的情况。典型场景是复选框、多选下拉框。比如页面上有input typecheckbox namehobby valuereading checked input typecheckbox namehobby valuecoding checked input typecheckbox namehobby valuegaming后端就得用getParameterValues(hobby)来取拿到的是[reading, coding]。如果你这时候用getParameter(hobby)只会得到第一个值reading。最后是getParameterMap()返回MapString, String[]。这个方法在写框架、封装通用参数解析工具的时候非常有用可以把整个请求的参数一次性拿全。它的特点是返回的Map是只读的你不能往里put不然会抛异常。2.2 参数获取的设计逻辑为什么API要这样分层搞清楚这三个方法之后你会发现它们的划分逻辑其实很清晰getParameter()面向大多数一参数一值的场景getParameterValues()面向复选场景getParameterMap()面向需要整体遍历的场景。Servlet规范之所以这样设计本质上是HTTP表单的数据模型决定的——一个字段名可以对应多个值这种数据形态用MapString, String[]来表达是最贴切的。另外还有一个容易被忽略的细节凡是获取参数的API拿到的值全部是String类型。这意味着如果你要接收数字、布尔值必须在后端自己转换。而且转换失败时不要指望Servlet容器帮你处理它们的默认行为就是抛NumberFormatException。从排查问题的角度来看我建议你接手一个项目时先看它的统一参数入口是怎么封装的。很多老项目会写一个BaseServlet在里面通过getParameterMap()统一收参再按业务需要转成JavaBean。这种设计的好处是收参逻辑收敛在一处出了问题只需要在基类里打断点而不是满项目找request.getParameter()的调用点。3. GET和POST在传参机制上的差异别再背八股了要看数据怎么流的3.1 GET请求参数住在URL里GET请求的参数是拼在URL问号后面的也就是query string。比如http://localhost:8080/hello?usernamezhangsanage25这里username和age就是参数名zhangsan和25是参数值多个参数之间用连接。当Servlet容器收到这个请求时会帮你把query string解析好放到request里你在代码里getParameter(username)就能拿到zhangsan。这里面有一个非常关键的编码问题URL里能直接使用的字符是有限制的RFC规范里明确规定URL只能包含ASCII字符集中的一部分。所以一旦参数里出现中文、空格、特殊符号就必须先进行百分号编码Percent-encoding也叫URL编码。编码规则很简单把字符转成UTF-8字节然后每个字节前面加一个%。张三两个字经过URL编码后是什么样我用Java代码模拟一下String encoded URLEncoder.encode(张三, UTF-8); System.out.println(encoded); // 输出 %E5%BC%A0%E4%B8%89所以你在浏览器地址栏里看到那一串%E5%BC%A0%E4%B8%89其实就是张三的UTF-8编码形态。这里要特别注意浏览器在发送GET请求时默认对URL中的非ASCII字符使用UTF-8编码。这看起来好像没问题但坑在于后端在解码时是否也用UTF-8两边一旦不一致乱码就来了。后面第4节我会展开讲这一段。3.2 POST请求参数住在请求体里POST请求的参数不在URL里而是放在请求体body中。当浏览器提交一个表单methodpost时表单数据会按照一定的格式写入body默认情况下这个格式是application/x-www-form-urlencoded。这种格式长什么样其实和query string的格式差不多usernamezhangsanage25区别在于数据存放的位置不同。用抓包工具看的话GET请求可以在请求行里直接看到参数POST请求则要到body里才能看到。Servlet容器处理POST参数时会读取body中的内容按照application/x-www-form-urlencoded的格式解析再放到request里面。但这里有个使用者必须知道的前提Servlet容器默认只在body的内容类型是application/x-www-form-urlencoded时才会解析参数。如果你在AJAX请求里用fetch或axios发送JSON数据content-type为application/json后端用getParameter()是拿不到任何东西的必须单独通过getReader()或getInputStream()读取body再自己解析。这个点我见过太多人踩坑了。前端明明把数据传上来了Network面板里也能看到payload后端getParameter()却返回null。原因就是content-type不对Servlet容器认为这不是表单提交不会自动帮你解析。3.3 GET和POST参数解析路径的差异直接决定了乱码的修法不同从上面的分析就能看出一个关键结论GET和POST的参数存放位置不同导致它们的编码处理链路也不同。GET参数在URL里解析发生在请求行的处理阶段解码用到的字符集由server.xml里的URIEncoding决定。POST参数在body里解析发生在请求体读取阶段解码用到的字符集由request.setCharacterEncoding()或Content-Type里的charset决定。这两条链路独立各有各的编码设置。所以经常会遇到一种情况POST的中文已经正常了但GET的中文还是乱码或者反过来。原因就是两个位置的编码设置没有同时修好。很多人只写了一个request.setCharacterEncoding(UTF-8)就以为所有乱码都解决了结果GET请求依然乱就是因为没有理解这两条链路的区别。我把它们的差异整理成一张表方便对照对比维度GETPOST参数存放位置URL的query string请求体bodycontent-type要求无特殊要求application/x-www-form-urlencoded表单默认时容器才自动解析编码设置入口server.xml的URIEncodingrequest.setCharacterEncoding()或Content-Type的charset数据长度限制由浏览器和服务器URL长度限制决定理论上由服务器端配置决定实际比GET宽松得多安全性参数直接暴露在URL中容易被日志记录相对隐蔽但HTTPS下才真正安全典型使用场景查询、翻页、搜索表单提交、登录、数据变更这张表我建议你收藏起来排查问题的时候对照着看比死记硬背八股管用得多。4. 乱码问题的完整排查链路从字符编码的本质到Tomcat的底层逻辑4.1 先搞清楚乱码产生的底层机制编码和解码用的字符集不一致乱码的本质其实只有一句话数据在编码时用的字符集和解码时用的字符集不是同一个。拿中文两个字来举例。如果用UTF-8编码中文会变成6个字节一个汉字3个字节如果用GBK编码中文会变成4个字节一个汉字2个字节。浏览器用UTF-8把中文转成字节发出去后端却拿着GBK去解码这一串字节解码出来的自然是一堆乱七八糟的字符。这个过程好比我们把一串英文放到一个中文格式的Word文档里粘贴Word自作主张帮你尝试用中文的断句方式来断英文结果就是既不像英文、也不像中文的乱文本。理解了这一点排查乱码的思路就清晰了顺着数据的流向逐一确认每一站用了什么字符集。请求发送端浏览器用的什么编码、传输过程中的编码声明是什么、服务端接收端用的什么编码三者必须一致。4.2 Tomcat 8 和 Tomcat 7 的差异为什么以前改server.xml现在不用了启动一个Servlet项目时大家应该都听过一个说法GET请求中文乱码要去conf/server.xml里改Connector的URIEncodingUTF-8。这个说法没有错但有一个重要前提在Tomcat 8及以上版本里这个配置其实已经不需要手动改了。从Tomcat 8.0开始默认的URIEncoding就是UTF-8。也就是说只要你的代码和页面都统一用UTF-8GET请求的URL参数在新版Tomcat上基本不会出现乱码问题。真正需要手动改URIEncoding的场景是你在用Tomcat 7或更老的版本时因为它们的默认编码是ISO-8859-1。这是一个西欧字符集完全不支持中文。在ISO-8859-1下中文被百分号编码后后端拿到的是每个字节单独映射成的字符看起来就是乱码。网上很多教程还说要把URIEncoding改成UTF-8如果你用的是Tomcat 8以上的版本这个动作其实是多余的。当然为了防止团队里有用老版本启动的情况统一加上这句配置也不算错只是要能识别出哪些是真正必要的操作。另外还有一个容易被忽略的参数useBodyEncodingForURI。把它设为true时GET请求的URI解码也会使用request.setCharacterEncoding()设置的编码。这个参数在Tomcat 8以上默认是false。如果你遇到既想做全局UTF-8、又不想动server.xml的情况可以在Connector上加这一句然后统一走setCharacterEncoding(UTF-8)这条路。4.3 POST请求乱码setCharacterEncoding为什么必须在第一次getParameter之前调用POST请求乱码的修复相对简单只要在读取任何参数之前先调用request.setCharacterEncoding(UTF-8);这个方法的本质是告诉Servlet容器解析body里的表单参数时请用UTF-8来解码。关键的坑在于setCharacterEncoding()一旦调用过后面再调用就不生效了。准确地说Servlet容器在第一次读取请求参数时就会用当前设置好的字符集完成解析之后你再改编码参数已经解析完了改也没用。有一段代码可以验证这个行为// 错误示范先获取参数再设置编码乱码依旧 String username request.getParameter(username); // 已经用默认编码解析了 request.setCharacterEncoding(UTF-8); // 太晚了不生效 // 正确示范先设置编码再获取参数 request.setCharacterEncoding(UTF-8); String username request.getParameter(username);所以你在写Filter的时候一定要把setCharacterEncoding(UTF-8)放在filterChain.doFilter()执行之前而且最好是直接在请求一进来的时候就设置好。这也是为什么Spring MVC里会有一个CharacterEncodingFilter来处理这件事——它本质上就是帮你确保在读取参数之前就把编码设好。另外还有一个更稳妥的写法在设置编码之前先判断一下请求是否已经指定了编码避免覆盖业务方特定需求。if (request.getCharacterEncoding() null) { request.setCharacterEncoding(UTF-8); }在Servlet 4.0规范里setCharacterEncoding()必须在读取请求体之前调用一次不同容器的实现细节略有差异但先设置再获取的原则是通用的。4.4 响应端编码乱码不只在请求参数这一侧聊请求参数乱码很多人会忽略响应端。但实际项目中经常是请求这边已经修好了发现响应的中文还是乱码。这时候就要检查response的编码设置了。如果你在Servlet里直接往response里写中文response.getWriter().write(中国);你必须保证response的字符编码也是UTF-8并且Content-Type里声明的charset一致。最稳妥的做法是response.setCharacterEncoding(UTF-8); response.setContentType(text/html;charsetUTF-8);setCharacterEncoding()要在getWriter()之前调用否则写入流的字符已经用默认编码处理了后面再改也不会重写。还有一个容易被忽视的点你在服务端设置的编码和浏览器解析响应时使用的编码可能由响应头里的Content-Type的charset决定也可能由HTML页面里的meta标签决定。如果页面文件里有而服务端响应的是UTF-8浏览器就可能按GBK去解看起来又是乱码。所以排查乱码的时候不要只看Java代码还要看一眼前端页面声明的字符集。4.5 乱码问题排查的完整流程从现象定位到根因我自己在实际排查乱码问题时一般会按照下面这个顺序走每一步都能排除一个变量先确认页面/请求方的编码。如果是网页表单提交看一下HTML文件的charset声明如果是AJAX请求看一下JS里有没有显式设置content-type的charset。打开浏览器的Network面板查看请求详情。GET请求直接看Request URL里参数是不是已经被百分号编码了POST请求看Request Headers里的Content-Type有没有带charset。后端在Servlet入口打断点用request.getCharacterEncoding()和request.getParameter()看实际拿到的值判断是前端发过来就是坏的还是后端解析坏了。如果前端发送时已经是%E5%BC%A0%E4%B8%89这种形态后端收到的却是乱码说明解码环节的字符集不对按照GET和POST分别检查URIEncoding和setCharacterEncoding。如果后端拿到的字符串是正确的但写回响应时变成乱码检查response的编码设置以及前端页面的meta charset。这个顺序的核心思路是沿着数据流的上下游逐步排查而不是瞎改一通。很多新手一遇到乱码就百度servlet 乱码 解决然后照抄一个Filter进去结果有时候能用有时候不能用就是因为没有定位到真正出问题的环节。5. 多值参数处理场景、代码、以及绕开getParameter的坑5.1 什么时候会用到多值参数不止复选框这一种场景getParameterValues()最常见的场景是复选框这个前面已经提到了。但实际开发里多值参数还有一些容易忽略的使用场景多选下拉框select multiple批量操作时传一组ID如批量删除ids1ids2ids3同一字段允许填写多个值的表单动态拓展比如批量删除的接口前端可能会构造这样的请求POST /deleteBatch ids1001ids1002ids1003后端如果只用getParameter(ids)拿到的只会是1001另外两个ID就丢了。这种Bug非常隐蔽因为单测时可能只传了一个ID到了联调阶段才发现批量功能有问题。正确写法String[] ids request.getParameterValues(ids); if (ids ! null) { for (String id : ids) { // 处理每个ID } }5.2 一个参数都没有的时候会怎样有时候前端传的参数名比较特殊比如某个字段叫array[]中括号。前端用AJAX传的时候键名是这样的$.ajax({ url: /demo, method: POST, data: { array[]: [1, 2, 3] }, traditional: true });这时候后端如果用getParameter(array[])去取运气好能取到第一个值但取值方式最好是String[] arr request.getParameterValues(array[]);因为方括号被当成普通字符的话getParameter(array)是取不到的。这类问题排查起来比较费时因为名字看起来顺手改一下就好但实际要严格按照前端传过来的键名来取。5.3 getParameterMap 在接收多值参数上的配合用法当你的接口接收大量参数且结构繁多时比起一个个getParameter直接遍历getParameterMap()会更高效MapString, String[] paramMap request.getParameterMap(); for (Map.EntryString, String[] entry : paramMap.entrySet()) { String name entry.getKey(); String[] values entry.getValue(); // 每个name可能对应多个value }这里有个兼容性细节要说明一下getParameterMap()返回的Map是只读的。如果你尝试往里面put数据会抛出UnsupportedOperationException。如果你确实需要修改参数Map比如某些框架要统一往参数里加一个traceId那就要自己new一个HashMap把原有内容复制进去再往新的Map里添加。5.4 多值参数和乱码叠加的场景先编码再取值还有一类问题更隐蔽多值参数本身就涉及中文。比如一个标签选择功能用户勾选多个中文标签前端提交的参数里既有多个同名参数值又是中文。这种情况下上面两节的知识要叠加起来用request.setCharacterEncoding(UTF-8); String[] tags request.getParameterValues(tags);先保证编码正确再取多值。如果编码没设好即使getParameterValues()返回了数组数组里的每个值也都是乱码排查起来会更加头大。6. 参数获取的实战封装把重复劳动收敛到一个地方6.1 为什么建议封装参数工具三个场景说明问题大多数Servlet项目里参数获取都是散落在各个Servlet里的。这样的代码风格没有什么硬伤只是当项目越来越大的时候你会发现三个问题第一取参之后的类型转换代码高度重复。每个Servlet里都要写Integer.parseInt(request.getParameter(age))写多了容易出错而且代码不美观。第二参数校验逻辑很难统一。比如某个字段要求必填、某个字段要求最大值如果每个Servlet各写各的口径不统一联调时经常因为这个扯皮。第三参数缺失时有的Servlet返回null有的返回空字符串有的直接抛异常表现不一致对接前端时很痛苦。6.2 一个简单的参数获取工具类思路我一般在项目中会封装一个ParamsUtil工具类核心方法大致如下public class ParamsUtil { public static String getString(HttpServletRequest request, String name) { String value request.getParameter(name); return value null ? : value.trim(); } public static Integer getInteger(HttpServletRequest request, String name) { String value request.getParameter(name); if (value null || value.trim().isEmpty()) { return null; } try { return Integer.parseInt(value.trim()); } catch (NumberFormatException e) { return null; } } public static ListString getList(HttpServletRequest request, String name) { String[] values request.getParameterValues(name); if (values null) { return Collections.emptyList(); } ListString list new ArrayList(); for (String value : values) { list.add(value.trim()); } return list; } }这只是个最小可用的版本实际项目中你可以根据自己的需求扩展支持默认值、支持泛型转换、支持嵌套Map结构等。但核心思路是一致的把getParameter()和getParameterValues()的常见处理逻辑收敛起来避免每个Servlet重复造轮子。这里我特别想强调一个细节getString方法里我做了trim()操作。很多前端传过来的参数会带空格尤其是在textarea或输入框里用户手滑多打了空格。如果不trim后面做equals比较或者数据库查询时很容易出现数据匹配不上的诡异问题。6.3 在Filter里统一处理编码一劳永逸的乱码解决方案与其在每个Servlet里手写request.setCharacterEncoding(UTF-8)不如直接写一个EncodingFilter统一处理。这也是实际项目中解决POST乱码最标准的做法。WebFilter(/*) public class EncodingFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; if (req.getCharacterEncoding() null) { req.setCharacterEncoding(UTF-8); } resp.setCharacterEncoding(UTF-8); resp.setContentType(text/html;charsetUTF-8); chain.doFilter(req, resp); } }这里有三个要点用WebFilter(/*)注解或者传统web.xml里配置filter-mapping确保所有请求都会经过。先判断getCharacterEncoding()是否为null避免覆盖业务方主动设置的编码。filterChain.doFilter()之前做了所有设置确保后续Servlet读取参数时编码已经生效。注意这个Filter只能解决POST请求的参数乱码。如果你使用的是Tomcat 8以上版本GET请求默认UTF-8所以也不用额外处理。如果你在用老版本Tomcat并且GET乱码还是得回server.xml里加URIEncodingUTF-8。6.4 Content-Type的charset声明setCharacterEncoding的等价写法除了手动调用setCharacterEncoding(UTF-8)还有一个等价做法在请求的Content-Type里带上charset。浏览器如果发这样的请求头Content-Type: application/x-www-form-urlencoded; charsetUTF-8Servlet容器在解析body时就知道用UTF-8来解码。所以在fetch、axios这类AJAX请求中你可以通过设置请求头来声明编码fetch(/demo, { method: POST, headers: { Content-Type: application/x-www-form-urlencoded; charsetUTF-8 }, body: username encodeURIComponent(张三) });不过这个方案依赖前端正确设置Content-Type不如直接在服务端Filter里兜底来得可靠。我的建议是服务端Filter里的setCharacterEncoding(UTF-8)是标配前端能带上charset最好不依赖它也不会出问题。7. 从Servlet规范出发谈谈请求参数解析的底层逻辑7.1 参数什么时候被解析进Request对象要真正理解HttpServletRequest获取参数你得稍微看一眼Servlet容器内部是怎么处理的。以Tomcat为例当请求到达后Tomcat会先从Request Line里解析出请求URL和请求方法。对于GET请求紧接着就会去解析URL里的query string把参数放到内部的ParameterMap数据结构里。对于POST请求Tomcat会比较关键的一个逻辑当请求的content-type是application/x-www-form-urlencoded时Tomcat会把body里的内容解析成参数如果content-type是multipart/form-data文件上传时用的格式参数的解析逻辑完全不同需要单独处理。Tomcat解析参数的具体时机是惰性的lazy。也就是说并不是请求一进来就立刻把所有参数解析好而是等你第一次调用getParameter()、getParameterValues()、getParameterMap()中的任意一个时才真正触发解析工作。这个惰性加载机制解释了前面提到的setCharacterEncoding()为什么必须最先调用——因为第一次触发参数解析时用的编码取决于当时getCharacterEncoding()的返回值。你如果在解析后修改编码解析结果不会变。7.2 参数被解析后存储结构是什么样的Tomcat内部会把解析出来的参数放在一个ParameterMap里面这个Map的key是参数名value是String[]数组。注意这个设计value是一个数组。因为规范层面已经考虑到同名多值的情况所以即使你只传了一个值内部存储的也是数组。getParameter()方法本质上是帮你去取这个数组的第一个元素getParameterValues()则是返回整个数组。意识到这一点后很多问题就有了合理的解释为什么getParameterValues()返回值不会是null当参数不存在时getParameterValues()返回null当参数存在但值为空时返回一个包含空字符串的数组。为什么getParameter()对不存在的参数返回null因为数组唯一的元素不存在getParameter()的逻辑就是如果数组存在且第一个元素为null就返回整个数组的第一个元素即null。7.3 看一段Tomcat源码级的伪代码理解getParameter()我把Tomcat中getParameter()的核心逻辑用伪代码描述一下方便理解public String getParameter(String name) { // 第一次调用时会触发参数解析 parseParameters(); // 从存储结构里找对应名字的值 String[] values parameters.get(name); if (values ! null) { return values[0]; // 只取第一个 } return null; }这行return values[0]就是问题所在当同名参数有多个值时getParameter()永远只返回第一个。很多人以为取不到后面的值是代码写错了其实API设计就是这样。7.4 一个容易被忽略的场景参数名相同但大小写不同HTTP参数名的处理方式在所有Servlet容器里都区分大小写。也就是说name和Name是两个完全不同的参数。前端如果某一次不小心改了大小写后端getParameter()就会取不到值而且不报任何错只是返回null。排查的时候特别容易漏所以建议大家在团队规范里统一约定参数命名风格建议全部使用小驼峰或全部小写杜绝大小写混用。还有一点有些框架比如Spring MVC在处理参数时会做更智能的类型转换和对象绑定但底层依然依赖Servlet容器的解析结果。理解原生Servlet这套机制对于理解上层框架的行为也是事半功倍的。8. 我把这些年的实战心得整理成了一张排查清单最后把我这些年处理Servlet参数问题的经验沉淀成一张清单你可以直接拿去做成团队内部的规范文档也可以贴在工位上备用。参数获取类问题取不到参数时先确认参数名是否有拼写错误注意大小写。确认请求是GET还是POSTGET看URL里query string是否正常POST看content-type是否是application/x-www-form-urlencoded。有多个同名参数记得用getParameterValues()getParameter()只返回第一个。参数值类型转换失败时catch住NumberFormatException并给出友好提示不要让500错误直接抛给前端。乱码类问题页面统一UTF-8后端统一UTF-8数据库连接串指定characterEncodingUTF-8。POST乱码在Filter里统一setCharacterEncoding(UTF-8)确保在读取参数之前设置。GET乱码Tomcat 8以上默认UTF-8Tomcat 7或更老版本改server.xml的URIEncodingUTF-8。响应乱码response.setCharacterEncoding(UTF-8) response.setContentType(text/html;charsetUTF-8)并且要在getWriter()之前设置。遇到前端AJAX POST中文乱码时检查请求头Content-Type里是否带charset或者前端是否用encodeURIComponent编码过。多值参数类问题复选框、多选下拉、批量ID一律用getParameterValues()。遍历时先判null避免空指针。参数Map只能读不能改需要修改时复制一份再操作。代码检查类问题所有getParameter()调用前先看看Filter里有没有设置编码。转换Integer时做一下null和空串的判断。前端如果encodeURIComponent了后端不需要手动解码URLEncoder的结果容器请求URL时已经做了解码处理。我自己在实际开发中发现参数获取这件事难点从来不是API本身而是API背后的数据流和编码链路。你只要能顺着浏览器 → HTTP报文 → Servlet容器 → request对象这条线把数据走向理清楚绝大多数问题都能在十分钟内定位出来。分享一个小技巧给你当你怀疑某个接口的参数处理有问题时可以在Servlet入口处临时打印一下getParameterMap()把整个参数Map打出来看。这一步能直接告诉你容器到底收到了哪些参数、每个参数有几个值、值是不是乱码。比你在前端和后端之间来回打断点高效得多。等定位完了再把这段调试代码删掉就好。
返回列表