解決使用@ResponseBody後返回500錯誤的問題
阿新 • • 發佈:2020-09-15
在springmvc+mybatis的專案中,利用mybatis分頁外掛mybatis-paginator進行分頁查詢,結果出現了500異常,後端又沒有明顯的報錯。
原來的寫法,返回Map物件,由springmvc裡面的機制轉為json物件,這樣就會導致,在轉json過程中的報錯,都隱藏了,無法丟擲,前端獲取不到正確的資料,
最後就出現了500的異常。
@RequestMapping(value = "/query") @ResponseBody public Map<String,Object> data(HttpServletRequest request,HttpServletResponse response,CreditloanInfoParams params) { Map<String,Object> data = new HashMap<String,Object>(); if(params==null){ params=new CreditloanInfoParams(); } PageList<CreditloanInfo> list = (PageList<CreditloanInfo>) creditloanInfoService.getCreditloanInfoListData(params); data.put("total",list.getPaginator().getTotalCount()); data.put("rows",list); return data; }
改成使用fastJson主動轉化為json格式的字串,這樣的好處是,轉json過程中如果出現錯誤,會有很明確的提示。
@SuppressWarnings("unchecked") @RequestMapping(value = "/query") @ResponseBody public String data(HttpServletRequest request,BlackParams params) { //Map<String,Object>(); /*PageList<Blacklist> blackDatas = (PageList<Blacklist>) blackService.getPageData(params); data.put("total",blackDatas.getPaginator().getTotalCount()); data.put("rows",blackDatas);*/ //blackService.getPageData(params); /* Map data = new HashMap(); PageList<Blacklist> blackDatas = blackService.getBlackListData(params); data.put("total",blackDatas);*/ return JSON.toJSONString(blackService.getPageData(params)); }
最後發現是轉json中出現了空指標異常。修復後,問題解決。
補充知識:springboot 使用過濾器獲取response內容儲存介面訪問日誌
一、建立過濾器
1. 在spring boot的啟動入口出添加註解 @ServletComponentScan
@SpringBootApplication @ServletComponentScan public class Application { public static void main(String[] args) { SpringApplication.run(Applicatioin.class,args); } }
2.新建過濾器AccessLogFilter.java
@WebFilter(filterName = "accessLog",urlPatterns = "/api/*") public class AccessLogFilter implements Filter { @Autowired AccessLogMapper accessLogMapper; public void destroy() { } public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException { long startTime = System.currentTimeMillis(); ResponseWrapper wrapper = new ResponseWrapper((HttpServletResponse) response); HttpServletRequest req = (HttpServletRequest) request; chain.doFilter(request,wrapper); long endTime = System.currentTimeMillis(); Gson gson = new Gson(); // 獲取response返回的內容並重新寫入response String result = wrapper.getResponseData(response.getCharacterEncoding()); response.getOutputStream().write(result.getBytes()); String uri = req.getRequestURI(); AccessLog log = new AccessLog(); log.setMethod(req.getMethod()); log.setUrl(uri); log.setParameters(gson.toJson(req.getParameterMap())); log.setResponseCode(String.valueOf(wrapper.getStatus())); log.setResult(result); log.setCreateDatetime(new Date()); log.setTimeConsuming((int)(endTime - startTime)); accessLogMapper.insertSelective(log); } public void init(FilterConfig fConfig) throws ServletException { } }
這個過濾器使用了註解@WebFilter(filterName = "accessLog",urlPatterns = "/api/*") 進行配置,指定了url進入規則,只有以/api/開頭的url才能進入到此過濾器中。在doFilter方法中使用了自定義的ResponseWrapper對response進行封裝。Controller介面走完之後獲取到介面返回的資料並再次封裝到response。
3. ResponseWrapper.java 類
import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import javax.servlet.ServletOutputStream; import javax.servlet.WriteListener; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class ResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream buffer = null; private ServletOutputStream out = null; private PrintWriter writer = null; public ResponseWrapper(HttpServletResponse response) throws IOException{ super(response); buffer = new ByteArrayOutputStream(); out = new WapperedOutputStream(buffer); writer = new PrintWriter(new OutputStreamWriter(buffer,"UTF-8")); } //過載父類獲取outputstream的方法 @Override public ServletOutputStream getOutputStream() throws IOException { return out; } @Override public PrintWriter getWriter() throws IOException { return writer; } @Override public void flushBuffer() throws IOException { if (out != null) { out.flush(); } if (writer != null) { writer.flush(); } } @Override public void reset() { buffer.reset(); } public String getResponseData(String charset) throws IOException { flushBuffer();//將out、writer中的資料強制輸出到WapperedResponse的buffer裡面,否則取不到資料 byte[] bytes = buffer.toByteArray(); try { return new String(bytes,"UTF-8"); } catch (UnsupportedEncodingException e) { return ""; } } //內部類,對ServletOutputStream進行包裝,指定輸出流的輸出端 private class WapperedOutputStream extends ServletOutputStream { private ByteArrayOutputStream bos = null; public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException { bos = stream; } //將指定位元組寫入輸出流bos @Override public void write(int b) throws IOException { bos.write(b); } @Override public boolean isReady() { // TODO Auto-generated method stub return false; } @Override public void setWriteListener(WriteListener listener) { // TODO Auto-generated method stub } } }
以上這篇解決使用@ResponseBody後返回500錯誤的問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。