【问题标题】:Java filter input XML before controller控制器之前的 Java 过滤器输入 XML
【发布时间】:2017-11-24 14:14:40
【问题描述】:

我想验证通过 http POST 请求接收到我的 Spring MVC 控制器的 XML,但我需要将其验证为 ServletFilter。

在输入流上使用 DocumentBuilderFactory 没问题:我在 ServletFilter 中正确解析和分析输入。

通过我的过滤器,调试器不让我看到它在各种库和类中发生了什么,但我无法登陆 Spring 控制器,我直接得到“400 Bad Request”作为响应。

没有这行代码(并且没有对xml文件的所有后续解析和验证)在我的过滤器中

Document doc = builder.parse(xml);

请求没有任何问题到达 Spring Controller,它将输入 XML 映射到名为 RequestModel.java

的对象

但是当我在过滤器中添加解析和验证时,导航在登陆Controller之前会阻塞,不会抛出任何异常。

这是让我在过滤器中调用失败的 sn-p:

InputStream xml = request.getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    try {
        DocumentBuilder builder = factory.newDocumentBuilder();

        Document doc = builder.parse(xml); //ADDING THIS LINE IT FAILS!

        //method continues with  xml parsing and validation...

这是我的Controller方法的开始(在解析之前,导航被阻塞):

@Controller
@EnableSwagger2
@RequestMapping("/listaprocessi")
@Api(description = "Lista processi ammessi", tags="Lista processi")
public class ListaProcessiController {

    @RequestMapping(produces = MediaType.APPLICATION_XML_VALUE, consumes = MediaType.APPLICATION_XML_VALUE, method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value="Lista processi")
    public BusinessListaProcessiModel listaProcessi(@RequestBody RequestModel requestModel) throws RemoteException{ ...}

是否因为要分析输入,过滤器必须等到流关闭?你有什么建议吗?

【问题讨论】:

    标签: xml spring-mvc controller inputstream servlet-filters


    【解决方案1】:

    您只能处理一次 ServletInputStream。因此,当您在过滤器中处理它时,Spring MVC 框架无法为您的控制器处理它。

    我遇到过很多次了。为了解决这个问题,我将 HttpServletRequest 包装在一个允许重新读取 InputStream 的新类中(见下文)。如果您将 HttpServletRequest 包装在下面类的实例中并在 DocumentBuilder 中使用它并将其传递给 Filter 的 doFilter 方法,那么您应该很好。

    public class CachingRequestWrapper extends HttpServletRequestWrapper {
    
        private final String cachedMsgBody;
    
        public CachingRequestWrapper(HttpServletRequest request) throws HttpErrorException {
            super(request);
            cachedMsgBody = ServletUtils.extractMsgBodyToString(request);
        }
    
        public CachingRequestWrapper(HttpServletRequest request, String msgBody) throws HttpErrorException {
            super(request);
            cachedMsgBody = msgBody;
        }
    
        public String getCachedMsgBody() {
            return cachedMsgBody;
        }
    
        @Override
        public BufferedReader getReader() throws IOException {
            InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(cachedMsgBody.getBytes()));
            return new BufferedReader(isr);
        }
    
        @Override
        public ServletInputStream getInputStream() throws IOException {
            ServletInputStream sis = new ServletInputStream() {
                private int i = 0;
                byte[] msgBodyBytes = cachedMsgBody.getBytes();
    
                @Override
                public int read() throws IOException {
                    byte b;
                    if (msgBodyBytes.length > i) {
                        b = msgBodyBytes[i++];
                    } else {
                        b = -1;
                    }
                    return b;
                }
    
                public boolean isFinished() {
                    return i == msgBodyBytes.length;
                }
    
                public boolean isReady() {
                    return true;
                }
    
                public void setReadListener(ReadListener rl) {
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
                }
            };
    
            return sis;
        }
    
    }
    

    参考:http://stackoverflow.com/a/6322667/1490322

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 2022-12-05
      相关资源
      最近更新 更多