Sto provando a segnalare su ogni codice di stato HTTP restituito dalla mia webapp. Tuttavia, il codice di stato non sembra accessibile tramite ServletResponse o anche se lo inoltro a HttpServletResponse. C'è un modo per ottenere l'accesso a questo valore all'interno di ServletFilter?Come posso ottenere il codice di stato HTTP da un ServletResponse in un ServletFilter?
risposta
Innanzitutto, è necessario salvare il codice di stato in un luogo accessibile. Il migliore per avvolgere la risposta con l'implementazione e tenerlo lì:
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;
}
}
Per poter utilizzare questo wrapper, è necessario aggiungere un filtro servlet, dove si può fare il vostro report:
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
}
}
Scrivere un HttpServletResponseWrapper e sovrascrivere tutti i metodi setStatus(), sendError() e sendRedirect() per registrare tutto. Scrivi un filtro che scambia il tuo wrapper per l'oggetto risposta su ogni richiesta.
una cosa che manca dalla risposta di David sopra è che si dovrebbe anche ignorare l'altra forma di sendError:
@Override
public void sendError(int sc, String msg) throws IOException {
httpStatus = sc;
super.sendError(sc, msg);
}
Grazie William, l'ho aggiunto al mio esempio –
dal Servlet 3.0, c'è un HttpServletResponse#getStatus()
.
Quindi, se c'è spazio per l'aggiornamento, eseguire l'aggiornamento a Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, ecc.) E non è necessario un wrapper.
chain.doFilter(request, response);
int status = ((HttpServletResponse) response).getStatus();
anche bisogno di includere un wrapper per #sendRedirect, e sarebbe meglio per inizializzare lo stato di '200', piuttosto che '0'
private int httpStatus = SC_OK;
...
@Override
public void sendRedirect(String location) throws IOException {
httpStatus = SC_MOVED_TEMPORARILY;
super.sendRedirect(location);
}
Sono in grado di vedere le situazioni in cui la posizione di mappatura del filtro può influire sull'attivazione del codice di override. Ad esempio, un filtro successivo potrebbe non avvolgere la tua risposta ma piuttosto sostituirla. Oltre a questi scenari, il codice di stato può essere impostato sulla risposta senza richiamare le varianti setStatus, sendError o sendRedirect? È per questo che hai inizializzato lo stato a 200? – 1in9ui5t
Se sei bloccato con un contenitore più vecchio allora una soluzione alternativa a David Rabinowitz che utilizza il codice di stato attuale (nel caso in cui cambia dopo che è stato impostato utilizzando l'involucro) è:
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();
}
}
Attenzione: un sacco di ipotesi della gerarchia di classe quando si utilizza END riflessione a fuoco e introspezione per ottenere valori di dati privati.
Oltre alla risposta di David, si potrà anche eseguire l'override del metodo di reset:
@Override
public void reset() {
super.reset();
this.httpStatus = SC_OK;
}
... così come il deprecato setStatus (int, String)
@Override
public void setStatus(int status, String string) {
super.setStatus(status, string);
this.httpStatus = status;
}
- 1. fa il nome di un codice di stato HTTP importa
- 2. Ottenere un codice di stato http vuoto 500 dall'API Web
- 3. Come ottenere il codice di stato HTTP dalla risposta SOAP
- 4. Ottenere codice di stato HTTP da Selenium WebDriver C#
- 5. Ottenere una descrizione per il codice di stato HTTP
- 6. System.Net.WebException codice di stato HTTP
- 7. Come ottenere il codice di stato della risposta da jQuery.ajax?
- 8. Come posso vedere il codice di stato HTTP dalla richiesta fatta da page.open?
- 9. Come ottenere il codice di stato da NSURLSessionDataTask?
- 10. HttpClient ottenere il codice di stato
- 11. Come ottenere il messaggio di stato HTTP in (py) curl?
- 12. Come posso ottenere un indirizzo MAC da una richiesta HTTP?
- 13. Python CGI restituisce un codice di stato http, come 403?
- 14. Assert restituito il codice di stato HTTP 400 come successo
- 15. Ottenere il codice di stato HTTP da più URL usando curl_multi?
- 16. Come posso restituire codici di stato HTTP specifici da un metodo remoto in loopback?
- 17. 502 codice di stato HTTP
- 18. Come posso ottenere un IL bytearray da un DynamicMethod?
- 19. come faccio a controllare un codice di stato di risposta della richiesta http da iOS?
- 20. Webpy: come impostare il codice di stato http su 300
- 21. Come ottenere un UIViewController da un UIView tramite il codice
- 22. Codice di stato HTTP in corso?
- 23. Come posso ottenere il codice c di un programma nim?
- 24. Come posso ottenere l'intestazione dalla risposta come ServletResponse(). GetHeader (stringa) non è visibile?
- 25. Come ottenere codici di stato HTTP numerici in PowerShell
- 26. Asp Classic restituisce il codice di stato http specifico
- 27. codice di stato HTTP HEAD del verbo
- 28. Come posso ottenere il punto di codice Unicode rappresentato da un numero intero in Swift?
- 29. Utilizzo di RoboSpice esiste un modo per ottenere il codice errore HTTP da un'eccezione?
- 30. Codice di stato HTTP per database inattivo
nel caso in cui qualcuno non legge fino alla fine della pagina, guarda il commento di Joel qui sotto per impostare anche lo stato di default = 200 e anche per sovrascrivere sendRedirect (..) –
Questo è stato estremamente utile per una versione precedente di Tomcat che è sulla specifica Servlet 2.4. Grazie! – user3621633
response.sendRedirect() sta dando illegalStateExcpetion. Ho sovrascritto sendRedirect anche come commento di Joel –