InputStream в servletInputStream

у меня есть этот InputStream:

InputStream inputStream = new ByteArrayInputStream(myString.getBytes(StandardCharsets.UTF_8));

как я могу преобразовать это в ServletInputStream?

Я пробовал:

ServletInputStream  servletInputStream = (ServletInputStream) inputStream;

но не работают.

EDIT:

мой метод это:

private static class LowerCaseRequest extends HttpServletRequestWrapper {

        public LowerCaseRequest(final HttpServletRequest request) throws IOException, ServletException {
            super(request);
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {

            ServletInputStream servletInputStream;

            StringBuilder jb = new StringBuilder();
            String line;
            String toLowerCase = "";

            BufferedReader reader = new BufferedReader(new InputStreamReader(super.getInputStream()));
            while ((line = reader.readLine()) != null) {
                toLowerCase = jb.append(line).toString().toLowerCase();
            }

            InputStream inputStream = new ByteArrayInputStream(toLowerCase.getBytes(StandardCharsets.UTF_8));

            servletInputStream = (ServletInputStream) inputStream;

            return servletInputStream;

        }
 }

Im пытается преобразовать весь мой запрос в нижний регистр.

3 ответов


попробуйте этот код.

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(myString.getBytes(StandardCharsets.UTF_8));
    ServletInputStream servletInputStream=new ServletInputStream(){
        public int read() throws IOException {
          return byteArrayInputStream.read();
        }
      }

мой совет: не создавать ByteArrayInputStream, просто используйте массив байтов, который вы получили от getBytes уже способ. Этого должно быть достаточно, чтобы создать ServletInputStream.

самое простое решение для

к сожалению, ответ aksappy переопределяет только read метод. Хотя этого может быть достаточно в Servlet API 3.0 и ниже, в более поздних версиях Servlet API есть три дополнительные методы, которые вы должны реализовать.

вот моя реализация класс, хотя он становится довольно длинным (из-за новых методов, введенных в Servlet API 3.1), вы можете подумать о его разложении на вложенный или даже класс верхнего уровня.

    final byte[] myBytes = myString.getBytes("UTF-8");
    ServletInputStream servletInputStream = new ServletInputStream() {
        private int lastIndexRetrieved = -1;
        private ReadListener readListener = null;

        @Override
        public boolean isFinished() {
            return (lastIndexRetrieved == myBytes.length-1);
        }

        @Override
        public boolean isReady() {
            // This implementation will never block
            // We also never need to call the readListener from this method, as this method will never return false
            return isFinished();
        }

        @Override
        public void setReadListener(ReadListener readListener) {
            this.readListener = readListener;
            if (!isFinished()) {
                try {
                    readListener.onDataAvailable();
                } catch (IOException e) {
                    readListener.onError(e);
                }
            } else {
                try {
                    readListener.onAllDataRead();
                } catch (IOException e) {
                    readListener.onError(e);
                }
            }
        }

        @Override
        public int read() throws IOException {
            int i;
            if (!isFinished()) {
                i = myBytes[lastIndexRetrieved+1];
                lastIndexRetrieved++;
                if (isFinished() && (readListener != null)) {
                    try {
                        readListener.onAllDataRead();
                    } catch (IOException ex) {
                        readListener.onError(ex);
                        throw ex;
                    }
                }
                return i;
            } else {
                return -1;
            }
        }
    };

добавление ожидаемых методов

в зависимости от ваших требований вы также можете переопределить другие методы. Как отметил ромфре, рекомендуется переопределить некоторые методы, такие как close и available. Если вы не реализуете их, поток всегда будет сообщать, что есть 0 байт, доступных для чтения, и close метод не влияет на состояние потока. Вы, вероятно, можете уйти, не переопределяя skip, поскольку реализация по умолчанию будет просто вызывать read несколько раз.

    @Override
    public int available() throws IOException {
        return (myBytes.length-lastIndexRetrieved-1);
    }

    @Override
    public void close() throws IOException {
        lastIndexRetrieved = myBytes.length-1;
    }

написание лучшего метода закрытия

к сожалению, из - за природы анонимного класса вам будет трудно написать эффективный close метод, потому что до тех пор, пока один экземпляр потока не был собран мусор Java, он поддерживает ссылку на массив байтов, даже если поток был закрыт.

однако, если вы разложите класс на вложенный или класс верхнего уровня (или даже анонимный класс с конструктором, который вы вызываете из строки, в которой он определен),myBytes может быть не конечным полем, а не конечной локальной переменной, и вы можете добавить строку типа:

myBytes = null;

на close метод, который позволит Java бесплатно память, занятая массивом байтов.

конечно, это потребует от вас написать конструктор, например:

    private byte[] myBytes;

    public StringServletInputStream(String str) {
        try {
            myBytes = str.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("JVM did not support UTF-8", e);
        }
    }

Mark и Reset

вы также можете переопределить mark, markSupported и reset если вы хотите поддержать Марка/сброс. Я не уверен, что они когда-либо на самом деле вызываются вашим контейнером.

    private int readLimit = -1;
    private int markedPosition = -1;

    @Override
    public boolean markSupported() {
        return true;
    }

    @Override
    public synchronized void mark(int readLimit) {
        this.readLimit = readLimit;
        this.markedPosition = lastIndexRetrieved;
    }

    @Override
    public synchronized void reset() throws IOException {
        if (markedPosition == -1) {
            throw new IOException("No mark found");
        } else {
            lastIndexRetrieved = markedPosition;
            readLimit = -1;
        }
    }

    // Replacement of earlier read method to cope with readLimit
    @Override
    public int read() throws IOException {
        int i;
        if (!isFinished()) {
            i = myBytes[lastIndexRetrieved+1];
            lastIndexRetrieved++;
            if (isFinished() && (readListener != null)) {
                try {
                    readListener.onAllDataRead();
                } catch (IOException ex) {
                    readListener.onError(ex);
                    throw ex;
                }
                readLimit = -1;
            }
            if (readLimit != -1) {
                if ((lastIndexRetrieved - markedPosition) > readLimit) {
                    // This part is actually not necessary in our implementation
                    // as we are not storing any data. However we need to respect
                    // the contract.
                    markedPosition = -1;
                    readLimit = -1;
                }
            }
            return i;
        } else {
            return -1;
        }
    }

Вы можете только бросить что-то вроде этого:

ServletInputStream  servletInputStream = (ServletInputStream) inputStream;

Если inputStream, который вы пытаетесь бросить, на самом деле уже является ServletInputStream. Он будет жаловаться, если это какая-то другая реализация InputStream. Вы не можете бросить объект на то, чем он не является.

в контейнере сервлетов вы можете получить ServletInputStream из ServletRequest:

ServletInputStream  servletInputStream = request.getInputStream();

Итак, что вы на самом деле пытаетесь сделать?

редактировать

я заинтригован почему вы хотите преобразовать свой запрос в нижний регистр-почему бы просто не сделать ваш сервлет нечувствительным к регистру? Другими словами, ваш код в нижнем регистре запроса данные могут быть скопированы в ваш сервлет, затем обработать их... всегда ищите самое простое решение!