vida usar servlet que httpservletresponse codigo clases ciclo java servlets servlet-filters http-status-codes

java - usar - servlets pdf



¿Cómo puedo obtener el código de estado HTTP de ServletResponse en un ServletFilter? (7)

Estoy tratando de informar sobre cada código de estado HTTP devuelto por mi aplicación web. Sin embargo, el código de estado no parece ser accesible a través de ServletResponse, o incluso si lo echo a un HttpServletResponse. ¿Hay alguna forma de acceder a este valor dentro de un ServletFilter?


Además de la respuesta de David, también querrás anular el método de reinicio:

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

... así como el setStatus en desuso (int, String)

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


Algo que falta en la respuesta de David anterior es que también debes anular la otra forma de sendError:

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


Desde Servlet 3.0, hay un HttpServletResponse#getStatus() .

Por lo tanto, si hay espacio para la actualización, actualice a Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, etc.) y no necesita un contenedor.

chain.doFilter(request, response); int status = ((HttpServletResponse) response).getStatus();


Escriba un HttpServletResponseWrapper y anule todos los métodos setStatus (), sendError () y sendRedirect () para registrar todo. Escriba un filtro que intercambia el contenedor para el objeto de respuesta en cada solicitud.


Primero, debe guardar el código de estado en un lugar accesible. Lo mejor para envolver la respuesta con su implementación y mantenerla allí:

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; } }

Para usar este contenedor, debe agregar un filtro de servlet, ¿podría hacer su informe?

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 } }


Si está atascado con un contenedor más antiguo, entonces una solución alternativa a David Rabinowitz que utiliza el código de estado real (en caso de que cambie después de que se establezca utilizando el contenedor) es:

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(); } }

Advertencia: muchas suposiciones de la jerarquía de clases cuando se usa reflexión furtiva e introspección para obtener valores de datos privados.


También es necesario incluir un contenedor para #sendRedirect, y sería mejor inicializar el estado a ''200'' en lugar de ''0''

private int httpStatus = SC_OK; ... @Override public void sendRedirect(String location) throws IOException { httpStatus = SC_MOVED_TEMPORARILY; super.sendRedirect(location); }