Вопрос по servlets, http-status-codes, servlet-filters, java – Как я могу получить код состояния HTTP из ServletResponse в ServletFilter?

59

Я пытаюсь сообщить о каждом HTTP-коде статуса, возвращенном из моего веб-приложения. Однако код состояния, по-видимому, недоступен через ServletResponse или даже если я приведу его к HttpServletResponse. Есть ли способ получить доступ к этому значению в ServletFilter?

Ваш Ответ

7   ответов
6

tus (), sendError () и sendRedirect () для регистрации всего. Напишите фильтр, который заменяет вашу оболочку на объект ответа при каждом запросе.

16

и было бы лучше инициализировать статус в '200' вместо «0»

private int httpStatus = SC_OK;

...

@Override
public void sendRedirect(String location) throws IOException {
    httpStatus = SC_MOVED_TEMPORARILY;
    super.sendRedirect(location);
}
Я вижу ситуации, когда размещение сопоставления фильтров может повлиять на срабатывание переопределенного кода. Например, последовательный фильтр может не обернуть ваш ответ, а заменить его. Помимо этих сценариев, может ли код статуса быть установлен в ответе без вызова вариантов setStatus, sendError или sendRedirect? Вот почему тыВы инициализировали статус до 200? 1in9ui5t
83

его обернуть ответ вашей реализацией и сохранить его там:

public class StatusExposingServletResponse extends HttpServletResponseWrapper {

    private int httpStatus;

    public StatusExposingServletResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void sendError(int sc) throws IOException {
        httpStatus = sc;
        super.sendError(sc);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        httpStatus = sc;
        super.sendError(sc, msg);
    }


    @Override
    public void setStatus(int sc) {
        httpStatus = sc;
        super.setStatus(sc);
    }

    public int getStatus() {
        return httpStatus;
    }

}

Чтобы использовать эту оболочку, вам нужно добавить фильтр сервлетов, где вы можете создавать свои отчеты:

public class StatusReportingFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        StatusExposingServletResponse response = new StatusExposingServletResponse((HttpServletResponse)res);
        chain.doFilter(req, response);
        int status = response.getStatus();
        // report
    }

    public void init(FilterConfig config) throws ServletException {
        //empty
    }

    public void destroy() {
        // empty
    }

}
response.sendRedirect () дает нелегальное состояние StateExcpetion. Я переопределил sendRedirect также как Joel 'комментарий Prasanna Kumar
если кто-то не читает до конца страницы, остерегайтесь ДжоэляКомментарий ниже, чтобы также установить статус по умолчанию = 200 и также переопределить sendRedirect (..) manuel aldana
Это было чрезвычайно полезно для старой версии Tomcat, котораяs в спецификации сервлетов 2.4. Спасибо! user3621633
ЕстьHttpServletRepsone.getStatus() начиная с Servlet 3.0 - см. ответ BalusC:stackoverflow.com/a/4305235/280244 Ralph
12

ь другую форму sendError:

@Override
public void sendError(int sc, String msg) throws IOException {
    httpStatus = sc;
    super.sendError(sc, msg);
}
Спасибо, Уильям, ямы добавили его в мой образец. David Rabinowitz
62

HttpServletResponse#getStatus()

Итак, если естьпространство для обновления, обновления до Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6 и т. д.), и вы не сможетеМне не нужна обертка.

chain.doFilter(request, response);
int status = ((HttpServletResponse) response).getStatus();
Замечательно! Что мне нужно! Junjie
@ Сэм: это не единственный ответ на вопрос. В настоящее время принятый ответ настолько стар, что все еще применяется к Tomcat 6. BalusC
тот'Приятно иметь. Спасибо, сэр! asgs
А как насчет кота 6 ?? версия сервлета ниже 3 Prasanna Kumar
0

то альтернативное решение для Дэвида Рабиновича, в котором используется действительный код состояния (в случае, если он изменяется после его установки с помощью оболочки):

public class StatusExposingServletResponse extends HttpServletResponseWrapper {

    public StatusExposingServletResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void sendError(int sc) throws IOException {
        super.sendError(sc);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        super.sendError(sc, msg);
    }

    @Override
    public void setStatus(int sc) {
        super.setStatus(sc);
    }

    public int getStatus() {
        try {
            ServletResponse object = super.getResponse();

            // call the private method 'getResponse'
            Method method1 = object.getClass().getMethod("getResponse");
            Object servletResponse = method1.invoke(object, new Object[] {});

            // call the parents private method 'getResponse'
            Method method2 = servletResponse.getClass().getMethod("getResponse");
            Object parentResponse = method2.invoke(servletResponse, new Object[] {});

            // call the parents private method 'getResponse'
            Method method3 = parentResponse.getClass().getMethod("getStatus");
            int httpStatus = (Integer) method3.invoke(parentResponse, new Object[] {});

            return httpStatus;
        }
        catch (Exception e) {
            e.printStackTrace();
            return HttpServletResponse.SC_ACCEPTED;
        }
    }

    public String getMessage() {
        try {
            ServletResponse object = super.getResponse();

            // call the private method 'getResponse'
            Method method1 = object.getClass().getMethod("getResponse");
            Object servletResponse = method1.invoke(object, new Object[] {});

            // call the parents private method 'getResponse'
            Method method2 = servletResponse.getClass().getMethod("getResponse");
            Object parentResponse = method2.invoke(servletResponse, new Object[] {});

            // call the parents private method 'getResponse'
            Method method3 = parentResponse.getClass().getMethod("getReason");
            String httpStatusMessage = (String) method3.invoke(parentResponse, new Object[] {});

            if (httpStatusMessage == null) {
                int status = getStatus();
                java.lang.reflect.Field[] fields = HttpServletResponse.class.getFields();

                for (java.lang.reflect.Field field : fields) {
                    if (status == field.getInt(servletResponse)) {
                        httpStatusMessage = field.getName();
                        httpStatusMessage = httpStatusMessage.replace("SC_", "");
                        if (!"OK".equals(httpStatusMessage)) {
                            httpStatusMessage = httpStatusMessage.toLowerCase();
                            httpStatusMessage = httpStatusMessage.replace("_", " ");
                            httpStatusMessage = capitalizeFirstLetters(httpStatusMessage);
                        }

                        break;
                    }
                }
            }

            return httpStatusMessage;
        }
        catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    private static String capitalizeFirstLetters(String s) {

        for (int i = 0; i < s.length(); i++) {
            if (i == 0) {
                // Capitalize the first letter of the string.
                s = String.format("%s%s", Character.toUpperCase(s.charAt(0)), s.substring(1));
            }

            if (!Character.isLetterOrDigit(s.charAt(i))) {
                if (i + 1 < s.length()) {
                    s = String.format("%s%s%s", s.subSequence(0, i + 1), 
                            Character.toUpperCase(s.charAt(i + 1)), 
                            s.substring(i + 2));
                }
            }
        }

        return s;

    }

    @Override
    public String toString() {
        return this.getMessage() + " " + this.getStatus();
    }

}

Предупреждение: множество предположений об иерархии классов при использовании хитрой рефлексии и самоанализа для доступа к частным значениям данных.

8

@Override
public void reset() {
    super.reset();
    this.httpStatus = SC_OK;
}

... а также устаревший setStatus (int, String)

@Override
public void setStatus(int status, String string) {
    super.setStatus(status, string);
    this.httpStatus = status;
}

Похожие вопросы