SpringMVC 的 Controller 能夠返回各類各樣的視圖。好比 JSP, JSON, Velocity, FreeMarker, XML, PDF, Excel, 還有Html字符流 等等。那它們該如何的進行處理的呢?這裏就涉及到 各類視圖(View)對應的各類視圖解析器(ViewResolver). 基本上上面說的每一種視圖就對應用一種視圖解析器來處理。基本上各類視圖解析器大體上能夠分爲兩類:一是基於URL的視圖解析器;一種是其它解析器;所謂的UrlBasedViewResolver,就是將返回值做爲最終視圖的url的一部分,而後和相關配置組合起來,就是最終的視圖地址url. 咱們看下UrlBasedViewResolver的解析器有哪些:html
1. 返回JSPweb
返回JSP是最簡單的,JSP視圖的視圖解析器爲 InternalResourceViewResolver,也是一個UrlBasedViewResolver解析器。其對應的解析器的配置通常以下:spring
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
使用該例子,咱們好好理解下什麼是 「基於URL」 的視圖解析器,好比咱們的 Controller 中最後的返回的處理代碼爲: return "index"; 那麼「基於URL」 的視圖解析器就會將返回值 「index」 做爲最後視圖的URL的一部分,而後結合上面的配置 <property name="prefix" value="/WEB-INF/jsp/"/> 和 <property name="suffix" value=".jsp"/>,最後獲得最終的URL: "/WEB-INF/jsp/" + "index" + ".jsp" == "/WEB-INF/jsp/index.jsp" json
這就是所謂的 「基於URL」 的視圖解析器的工做方式。數組
2. 返回 HTML 頁面
瀏覽器
咱們知道在Servlet中,咱們是能夠直接在其中打印輸出HTML字符流到最終頁面,好比下面的代碼來自阿里巴巴的支付寶的接入示例中的代碼:session
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); // ... ... //創建請求 String sHtmlText = AlipaySubmit.buildRequest(sParaTemp,"get","確認"); response.getWriter().println(sHtmlText); }
/** * 創建請求,以表單HTML形式構造(默認) * @param sParaTemp 請求參數數組 * @param strMethod 提交方式。兩個值可選:post、get * @param strButtonName 確認按鈕顯示文字 * @return 提交表單HTML文本 */ public static String buildRequest(Map<String, String> sParaTemp, String strMethod, String strButtonName) { //待請求參數數組 Map<String, String> sPara = buildRequestPara(sParaTemp); List<String> keys = new ArrayList<String>(sPara.keySet()); StringBuffer sbHtml = new StringBuffer(); sbHtml.append("<!doctype html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); sbHtml.append("<title>支付寶即時到帳交易接口</title></head><body>"); sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + ALIPAY_GATEWAY_NEW + "_input_charset=" + AlipayConfig.input_charset + "\" method=\"" + strMethod + "\">"); for (int i = 0; i < keys.size(); i++) { String name = (String) keys.get(i); String value = (String) sPara.get(name); sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>"); } //submit按鈕控件請不要含有name屬性 sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>"); sbHtml.append("<script>document.forms['alipaysubmit'].submit();</script>"); sbHtml.append("</body></html>"); return sbHtml.toString(); }
很顯然,Servlet直接將HTML的字符流輸出到了瀏覽器端,那麼在SpringMVC中該如何作呢?其實在SpringMVC中咱們也是能夠以下實現的:mvc
@RequestMapping(value="/getPage") public void writeSubmitHtml(Reader reader, Writer writer, HttpSession session) throws IOException { User user = (User) session.getAttribute(ConstantConfig.LONGIN_USER); StringBuffer sbHtml = new StringBuffer(); sbHtml.append("<!doctype html><html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"); sbHtml.append("<title>支付寶即時到帳交易接口</title></head><body>"+ user.getNo() +"</body></html>"); writer.write(sbHtml.toString()); }
咱們看到咱們直接使用了參數 Writer writer,返回值爲 void, 其實參數 Writer writer 也能夠換成 PrintWriter writer; 直接寫出HTML的字符流。app
咱們也知道在Servlet中,咱們是能夠直接forward或者redirecit到html頁面,因此咱們也能夠以下在springmvc中返回到html頁面:jsp
@RequestMapping(value="/htmlView") public void htmlView(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ // ... request.getRequestDispatcher("index.html").forward(request, response);
//response.sendRedirect("http://www.baidu.com"); }
這裏,咱們體會到了:springmvc他是創建在servlet之上的,因此在servlet中可以作到的,一樣在springmvc同樣有效。
3. 返回JSON格式
返回JSON格式在SpringMVC中有多種處理方式,一種是使用SpirngMVC自帶的 MappingJackson2JsonView 來處理,一種是本身寫代碼將返回值JSON格式化,而後直接用PrintWrite類型的對象寫出就好了。
1)直接用PrintWrite類型的對象寫出JSON格式
@RequiresRoles(value={"student"}) @RequestMapping(value="/queryScoreForStudent") public void queryScoreForStudent(ScoreQueryParam param, HttpSession sesion, PrintWriter printWriter){ Student student = (Student)sesion.getAttribute(ConstantConfig.LONGIN_STUDENT); param.setStudentId(student.getId()); PageBean<StudentScore> scoreList = this.studentCourseService.queryScoreForStudent(param); if(scoreList != null && scoreList.getSize() > 0){ Map<String, Object> map = new HashMap<>(); map.put("result", "ok"); map.put("data", scoreList); printWriter.write(JSON.toJSONString(map)); } }
如上代碼所示,咱們在方法中加入了 PrintWriter printWriter 參數,最後的返回結果使用了fastjson庫來格式化最後的返回的對象map. 而後使用printWriter寫出,就好了。咱們看到方法上的註解並無使用 @ResponseBody. 固然最好這裏是在方法上加上 @ResponseBody,可是由於返回的map已是JSON格式的,因此並不須要配置 MappingJackson2JsonView !
2)使用MappingJackson2JsonView 配合@ResponseBody來返回JSON格式
首先須要進行相關的視圖解析器的配置:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="mediaTypes"> <map> <entry key="atom" value="application/atom+xml"/> <entry key="html" value="text/html"/> <entry key="json" value="application/json"/> </map> </property> <property name="viewResolvers"> <list> <!-- <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/> --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"/> <property name="suffix" value=".jsp"/> </bean> </list> </property> <property name="defaultViews"> <list> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> </list> </property> </bean>
這裏用到了 ContentNegotiatingViewResolver ,「內容協商視圖解析器」,其實就是根據返回什麼類型的視圖,就協商使用哪一種視圖解析器。若是返回jsp就使用InternalResourceViewResolver視圖解析器,若是返回JSON格式就使用MappingJackson2JsonView來處理。如此而已。在 <property name="viewResolvers"> 下的<list> 標籤下,還能夠加入其餘的各類視圖解析器的配置。
配置了 MappingJackson2JsonView 以後,就沒有必要在本身手動 JSON格式化了,上面的例子,能夠改爲:
@RequiresRoles(value={"student"}) @RequestMapping(value="/queryScoreForStudent")
@ResponseBody public Map<String, Object> queryScoreForStudent(ScoreQueryParam param, HttpSession sesion){ Student student = (Student)sesion.getAttribute(ConstantConfig.LONGIN_STUDENT); param.setStudentId(student.getId()); PageBean<StudentScore> scoreList = this.studentCourseService.queryScoreForStudent(param); System.out.println(JSON.toJSONString(scoreList)); if(scoreList != null && scoreList.getSize() > 0){ Map<String, Object> map = new HashMap<>(); map.put("result", "ok"); map.put("data", scoreList); return map; } }
其餘格式Velocity, FreeMarker, XML, PDF, Excel等視圖的處理,後面有時間在補上。