如题,在一个html中指定编码为GBK,后台代码编码为UTF-8,在不修改html代码的情况下,如何在接口中获取或者转换成正确的值


多年后chatGPT给的方案
@GetMapping(value = "test", produces = BaseConstant.REQUEST_HEADERS_CONTENT_TYPE)
@ApiOperation(value = "test", notes = "test")
public String test(HttpServletRequest request) throws Exception {
/// 尝试从原始位置获取参数(优先 GET queryString,再尝试 POST body)
String retMsg = getRawParameter(request, "ret_msg", "GBK");
if (retMsg == null) {
// 回退到常规方式(容器解析)——但注意:如果容器已错误解码,可能是 "????"
String normal = request.getParameter("ret_msg");
return normal != null ? ("fallback:" + normal) : "no ret_msg";
}
System.out.println("decoded ret_msg = " + retMsg);
return retMsg;
}
/**
* 从原始请求(queryString 或 body)中解析指定参数,使用指定 charset 进行 URL 解码。
* 仅适用于 application/x-www-form-urlencoded 的场景。
*
* @param request HttpServletRequest
* @param name 参数名
* @param charsetName 如 "GBK"
* @return 解码后的参数值 或 null(未找到)
*/
private String getRawParameter(HttpServletRequest request, String name, String charsetName) throws IOException {
// 1) 优先处理 GET query string(raw)
String query = request.getQueryString();
if (query != null && !query.isEmpty()) {
String v = extractFromUrlEncoded(query, name, charsetName);
if (v != null) return v;
}
// 2) 如果是 POST 并且 content-type 是 application/x-www-form-urlencoded,读取 raw body
String method = request.getMethod();
String contentType = request.getContentType();
if ("POST".equalsIgnoreCase(method) && contentType != null &&
contentType.toLowerCase().startsWith("application/x-www-form-urlencoded")) {
// 注意:如果其他过滤器/拦截器/框架早已读取过 request.getInputStream() 或 getParameter,
// 那这里就无法再次读取到原始 body。确保此段在参数被访问之前运行。
byte[] bodyBytes = readRequestBody(request);
if (bodyBytes != null) {
// body 是 URL encoded 的字节序列,用给定 charset 解析
String body = new String(bodyBytes, charsetName);
String v = extractFromUrlEncoded(body, name, charsetName);
if (v != null) return v;
}
}
// 3) 未命中,返回 null
return null;
}
// 读取 request body 原始字节
private byte[] readRequestBody(HttpServletRequest request) throws IOException {
int contentLength = request.getContentLength();
ServletInputStream in = request.getInputStream();
if (contentLength > 0) {
byte[] buf = new byte[contentLength];
int read = 0;
while (read < contentLength) {
int r = in.read(buf, read, contentLength - read);
if (r < 0) break;
read += r;
}
return buf;
} else {
// contentLength 未提供时,读取到 EOF
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] tmp = new byte[4096];
int r;
while ((r = in.read(tmp)) != -1) {
baos.write(tmp, 0, r);
}
return baos.toByteArray();
}
}
// 从 URL-encoded 的字符串里提取指定参数(支持多个同名参数,返回第一个)
private String extractFromUrlEncoded(String urlEncoded, String name, String charsetName) throws UnsupportedEncodingException {
if (urlEncoded == null || urlEncoded.length() == 0) return null;
// 例如 urlEncoded: "ret_msg=%B1%...&x=1"
String[] pairs = urlEncoded.split("&");
for (String p : pairs) {
int idx = p.indexOf('=');
String k, v;
if (idx >= 0) {
k = p.substring(0, idx);
v = p.substring(idx + 1);
} else {
k = p;
v = "";
}
// 名称与值均是 URL encoded bytes,先按给定 charset 解码
String dk = urlDecode(k, charsetName);
if (name.equals(dk)) {
return urlDecode(v, charsetName);
}
}
return null;
}
// URL decode 指定编码(与 java.net.URLDecoder 不同:URLDecoder.decode 默认用 platform 编码,显式指定 charset)
private String urlDecode(String s, String charsetName) throws UnsupportedEncodingException {
if (s == null) return null;
// Use URLDecoder with charset
return java.net.URLDecoder.decode(s, charsetName);
}
public void test3() throws UnsupportedEncodingException {
String test = "测试";
String test_gbk_utf8 = new String(test.getBytes(StandardCharsets.UTF_8), "gbk");
System.out.println(test_gbk_utf8);//娴嬭瘯
String test_utf8_gbk = new String(test_gbk_utf8.getBytes("gbk"), StandardCharsets.UTF_8);
System.out.println(test_utf8_gbk);//测试
}
String test_gbk_utf8 = new String(test.getBytes("gbk"),StandardCharsets.UTF_8 );
实际上我需要的是这种,把这个test_gbk_utf8转换成正确的值。。。
@我恰芙蓉王: 思路就是这样,转成你想要的码就行。让别人直接写出答案是不现实的
@Biuget-Golang: 没办法,试过很多种方式,new String("字符串".getBytes("gbk"), "utf-8"),这种怎么样都转不回来
gbk 解码 然后utf编码试试
接口中获取时不能用string, 用ArrayBuffer 进行两次转换就可以了
用了string就可能会数据错误