Tôi đang cố gắng báo cáo về mọi mã trạng thái HTTP được trả về từ webapp của tôi. Tuy nhiên, mã trạng thái dường như không thể truy cập được thông qua ServletResponse, hoặc thậm chí nếu tôi đưa nó vào một HttpServletResponse. Có cách nào để truy cập vào giá trị này trong ServletFilter không?Làm cách nào để lấy mã trạng thái HTTP ra khỏi ServletResponse trong ServletFilter?
Trả lời
Trước tiên, bạn cần phải lưu mã trạng thái vào một nơi có thể truy cập. Các tốt nhất để quấn phản ứng với thực hiện của bạn và giữ nó ở đó:
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;
}
}
Để sử dụng wrapper này, bạn cần phải thêm một bộ lọc servlet, là bạn có thể làm báo cáo của bạn:
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
}
}
Viết một HttpServletResponseWrapper và ghi đè tất cả các phương thức setStatus(), sendError() và sendRedirect() để ghi lại mọi thứ. Viết một Bộ lọc hoán đổi trình bao bọc của bạn cho đối tượng phản hồi trên mọi yêu cầu.
một điều mất tích từ câu trả lời của David trên là bạn cũng nên ghi đè lên các hình thức khác của sendError:
@Override
public void sendError(int sc, String msg) throws IOException {
httpStatus = sc;
super.sendError(sc, msg);
}
Cảm ơn William, tôi đã thêm nó cho mẫu của tôi. –
Kể từ Servlet 3.0, có một HttpServletResponse#getStatus()
.
Vì vậy, nếu có chỗ để nâng cấp, hãy nâng cấp lên Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, v.v.) và bạn không cần trình bao bọc.
chain.doFilter(request, response);
int status = ((HttpServletResponse) response).getStatus();
Cũng cần phải bao gồm một wrapper cho #sendRedirect, và nó sẽ là tốt hơn để khởi tạo trạng thái để '200' chứ không phải '0'
private int httpStatus = SC_OK;
...
@Override
public void sendRedirect(String location) throws IOException {
httpStatus = SC_MOVED_TEMPORARILY;
super.sendRedirect(location);
}
Tôi có thể thấy các tình huống mà vị trí ánh xạ bộ lọc của bạn có thể tác động đến việc mã ghi đè của bạn có được kích hoạt hay không. Ví dụ, một bộ lọc liên tiếp có thể không bao gồm phản hồi của bạn mà thay thế nó. Bên cạnh những tình huống đó, mã trạng thái có thể được đặt trên phản hồi mà không cần gọi các biến setStatus, sendError hoặc sendRedirect không? Đó có phải là lý do tại sao bạn đã khởi tạo trạng thái là 200? – 1in9ui5t
Nếu bạn đang mắc kẹt với một container cũ rồi một giải pháp thay thế để David Rabinowitz có sử dụng mã trạng thái thực tế (trong trường hợp nó thay đổi sau khi nó được thiết lập bằng cách sử dụng wrapper) là:
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();
}
}
Cảnh báo: rất nhiều giả định của hệ thống phân cấp lớp khi sử dụng SNE phản ánh và quan tâm đến các giá trị dữ liệu riêng tư.
Ngoài câu trả lời của David, bạn cũng sẽ muốn ghi đè lên các phương pháp thiết lập lại:
@Override
public void reset() {
super.reset();
this.httpStatus = SC_OK;
}
... cũng như phản đối setStatus (int, String)
@Override
public void setStatus(int status, String string) {
super.setStatus(status, string);
this.httpStatus = status;
}
- 1. Mã trạng thái HTTP System.Net.WebException
- 2. Đặt mã trạng thái HTTP trong Chai?
- 3. Cách lấy mã trạng thái từ webclient?
- 4. cách lấy mã trạng thái jquery ajax
- 5. Cách nhận mã trạng thái HTTP <img> thẻ
- 6. Mã trạng thái Http với libcurl?
- 7. Mã trạng thái HTTP cho lỗi chung
- 8. Làm cách nào để nhận mã trạng thái HTTP cho miền từ xa trong php?
- 9. Webpy: cách đặt mã trạng thái http thành 300
- 10. Http Mã trạng thái 400 và 412
- 11. Mã trạng thái HTTP 000 là gì?
- 12. Kiểm tra mã trạng thái HTTP trong Selenium
- 13. làm cách nào để kiểm tra mã trạng thái phản hồi yêu cầu http từ iOS?
- 14. Làm thế nào để chuyển đổi mã trạng thái HTTP thành văn bản trong Java?
- 15. Trả lại mã trạng thái HTTP 201 trong bình
- 16. Làm thế nào để lấy trạng thái thoát khỏi ruby Open3.popen3()?
- 17. Nhận mã trạng thái HTTP trong Android WebView
- 18. Python urllib2 URLĐịnh dạng mã trạng thái HTTP.
- 19. jQuery $ .get/$. Ajax chuyển mã trạng thái HTTP 200 thay vì mã trạng thái mong đợi là 201 hoặc 202
- 20. Lấy mã trạng thái thoát khỏi lệnh 'ftp' trong vỏ linux
- 21. Nhận mã trạng thái 500 http trống từ API Web
- 22. Trả lại mã trạng thái http trong Python CGI
- 23. Lấy mã trạng thái HTTP từ khung nội tuyến đã tải bằng Javascript
- 24. Mã trạng thái HTTP cho chuyển hướng ngôn ngữ
- 25. Thỏa thuận với mã trạng thái HTTP 308 là gì?
- 26. Nhận mô tả cho mã trạng thái HTTP
- 27. Tại sao display_errors thay đổi mã trạng thái HTTP?
- 28. Chụp mã trạng thái http bằng con nhện bị lột
- 29. Mã trạng thái HTTP đang được xử lý?
- 30. Cách dễ dàng để hiển thị JSON bằng mã trạng thái HTTP trong Grails
trong trường hợp ai đó không đọc cho đến cuối trang, hãy xem bình luận của Joel bên dưới để đặt trạng thái mặc định = 200 và cũng ghi đè lên sendRedirect (..) –
Điều này cực kỳ hữu ích cho phiên bản cũ của Tomcat có trong Servlet spec 2.4. Cảm ơn bạn! – user3621633
response.sendRedirect() đang cho phép bất hợp phápStateExcpetion. Tôi đã overridded sendRedirect cũng như bình luận của Joel –