如何解决spring-boot中的URI编码问题? [英] How to resolve URI encoding problem in spring-boot?

查看:18
本文介绍了如何解决spring-boot中的URI编码问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 spring-boot 来托管 http 请求服务.

I am using spring-boot to host a http request service.

@RequestMapping("/extract")
    @SuppressWarnings("unchecked")
    @ResponseBody
    public ExtractionResponse extract(@RequestParam(value = "extractionInput") String input) {

        // LOGGER.info("input: " + input);
        JSONObject inputObject = JSON.parseObject(input);


        InputInfo inputInfo = new InputInfo();

        //Object object = inputObject.get(InputInfo.INPUT_INFO);
        JSONObject object = (JSONObject) inputObject.get(InputInfo.INPUT_INFO);

        String inputText = object.getString(InputInfo.INPUT_TEXT);
        inputInfo.setInputText(inputText);

        return jnService.getExtraction(inputInfo);
    }

当有%符号时,如下,报错:

When there is a % sign, as follows, it got an errror:

 http://localhost:8090/extract?extractionInput={"inputInfo":{"inputText":"5.00%"}} 

错误信息如下:

2018-10-09 at 19:12:53.340 [http-nio-8090-exec-1] INFO  org.apache.juli.logging.DirectJDKLog [180] [log] - Character decoding failed. Parameter [extractionInput] with value [{"inputInfo":{"inputText":"5.0022:%225.00%%22}}] has been ignored. Note that the name and value quoted here may be corrupted due to the failed decoding. Use debug level logging to see the original, non-corrupted values.
 Note: further occurrences of Parameter errors will be logged at DEBUG level.
2018-10-09 at 19:12:53.343 [http-nio-8090-exec-1] WARN  org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver [140] [resolveException] - Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'extractionInput' is not present]

如何在我的 spring-boot 配置中配置 URI 编码来解决这个问题?

How to configure the URI encoding to fix this issue in my spring-boot configurations?

发出请求的可能的 Java 客户端代码:

Possible Java client code to make the request:

public String process(String question) {

        QueryInfo queryInfo = getQueryInfo(question);

        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        String jsonResult = null;
        try {
            String jsonStr = mapper.writeValueAsString(queryInfo);
            String urlStr = Parameters.getQeWebserviceUrl() + URLEncoder.encode(jsonStr, "UTF-8");
            URL url = new URL(urlStr);
            BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
            jsonResult = in.readLine();
            in.close();
        } catch (Exception jpe) {
            jpe.printStackTrace();
        } 
     return jsonResult
}

推荐答案

如果不从客户端进行编码 - 如果在 servlet 中处理请求之前通过编码遵循以下任何策略,您仍然可以实现这一目标:

Without encoding from your client side - you could still achieve this if you follow any of the following strategies by encoding before the request is processed in the servlet:

>

  • 使用 Spring 预处理器 bean 预处理控制器端点请求
  • 使用 Spring AspectJ 预处理控制器端点请求
  • 使用 Spring servlet 过滤器预处理控制器端点请求
  • 使用上述任何一种横切策略,您都可以对请求 URL 进行编码并传回端点.

    With any of the above cross-cutting strategies, you could encode the request URL and pass back to the endpoint.

    例如下面是使用过滤器的一种实现.如果您需要更好的性能,您可以在那里进行一些缓存.

    For example below is one implmentation using Filter. You could possibly do some caching there if you need better performance.

    @Component
    public class SomeFilter implements Filter {
        private static final Logger LOGGER = LoggerFactory.getLogger(SomeFilter.class);
    
        @Override
        public void init(final FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletRequest modifiedRequest = new SomeHttpServletRequest(request);
            filterChain.doFilter(modifiedRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    
        class SomeHttpServletRequest extends HttpServletRequestWrapper {
            HttpServletRequest request;
    
            SomeHttpServletRequest(final HttpServletRequest request) {
                super(request);
                this.request = request;
            }
    
            @Override
            public String getQueryString() {
                String queryString = request.getQueryString();
                LOGGER.info("Original query string: " + queryString);
    
                try {
                    // You need to escape all your non encoded special characters here
                    String specialChar = URLEncoder.encode("%", "UTF-8");
                    queryString = queryString.replaceAll("\\%\\%", specialChar + "%");
    
                    String decoded = URLDecoder.decode(queryString, "UTF-8");
                    LOGGER.info("Modified query string: "  + decoded);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
    
                return queryString;
            }
    
            @Override
            public String getParameter(final String name) {
                String[] params = getParameterMap().get(name);
                return params.length > 0 ? params[0] : null;
            }
    
            @Override
            public Map<String, String[]> getParameterMap() {
                String queryString = getQueryString();
                return getParamsFromQueryString(queryString);
            }
    
            @Override
            public Enumeration<String> getParameterNames() {
                return Collections.enumeration(getParameterMap().keySet());
            }
    
            @Override
            public String[] getParameterValues(final String name) {
                return getParameterMap().get(name);
            }
    
            private Map<String, String[]> getParamsFromQueryString(final String queryString) {
                String decoded = "";
                try {
                    decoded = URLDecoder.decode(queryString, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                String[] params = decoded.split("&");
                Map<String, List<String>> collect = Stream.of(params)
                    .map(x -> x.split("="))
                    .collect(Collectors.groupingBy(
                        x -> x[0],
                        Collectors.mapping(
                            x -> x.length > 1 ? x[1] : null,
                            Collectors.toList())));
    
                Map<String, String[]> result = collect.entrySet().stream()
                    .collect(Collectors.toMap(
                        x -> x.getKey(),
                        x -> x.getValue()
                            .stream()
                            .toArray(String[]::new)));
    
                return result;
            }
        }
    }
    

    这篇关于如何解决spring-boot中的URI编码问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆