Spring所支持的Resolver 非常多,但是我們最爲常用的還是 InternalResourceViewResolver 。常規就是貼出一下InternalResourceViewResolver的常用配置:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/" p:suffix=".jsp" p:order="99" ></bean>
這裏我說一下其餘的兩個resolver
BeanNameViewResolver 這個resolver會找到相應的bean最爲view這個非常有用,我們會使用這個resolver處理一些導出EXCEL和導出PDF的view,當然也有人使用這個來做JSON和XML View的視圖解析,但是一般情況下我都是採用HttpMessageConvert做JSON和XML的輸出。
CommonsMultipartResolver 這個用於文件上傳之用。
其他還有什麼國際化的、解析爲URL文件的等等,這裏就不再細說。下面我會做一個excel導出 和文件上傳功能,來感受BeanNameViewResolver和CommonsMultipartResolver的作用。
EXCEL導出
Excel導出在SpringMVC非常簡單,我們需要實現一個AbstractXlsxView的類,作爲相應的View。然後通過BeanNameViewResolver 獲得並使用這個View的輸出進行響應。
編寫一個導出用戶數據excel的view
public class UserListExcelView extends AbstractXlsxView { protected void buildExcelDocument(Map<String, Object> map, Workbook workbook, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { httpServletResponse.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline;filename=" + new String("UserList.xlsx".getBytes(), "utf-8")); List<User> resultList = (List<User>) map.get("userList"); Sheet sheet = workbook.createSheet("UserList"); Row header = sheet.createRow(0); header.createCell(0).setCellValue("User id"); header.createCell(1).setCellValue("User name"); header.createCell(2).setCellValue("User Password"); int rowIndex = 1; for (User userItem : resultList) { Row rowItem = sheet.createRow(rowIndex++); rowItem.createCell(0).setCellValue(userItem.getUserId()); rowItem.createCell(1).setCellValue(userItem.getUsername()); rowItem.createCell(2).setCellValue(userItem.getPwd()); } } }
使用之前我們需要一些依賴包的支持,maven的dependence:
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency>
然後將我們寫的UserListExcelView 配置爲springMVC的bean:
<bean id="userListEXCEL" class="com.maxfunner.view.UserListExcelView"/>
最後我們需要定義BeanNameViewResolver,如果我們同時定義了InternalResourceViewResolver的話,需要注意優先級的問題。優先級後面會說
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="10"/>
然後就在controller中編寫一個處理方法:
@RequestMapping("/userListExport") public ModelAndView getUserList() { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("userListEXCEL"); modelAndView.addObject("userList", this.userService.getUserByIdRange(0, 30)); return modelAndView; }
這裏可以看見我們在設置ViewName的時候,是設置的<bean id="userListEXCEL" class="com.maxfunner.view.UserListExcelView"/>這個bean的id。BeanNameViewResolver主要的目的就是找到相對於ViewName的Bean作爲視圖。
但是InternalResourceViewResolver也會解析viewName,這個就涉及都一個優先級的問題,如果InternalResourceViewResolver優先級比較高,那麼InternalResourceViewResolver會直接去找userListEXCEL.jsp這個文件,然後就不會執行BeanNameViewResolver的解析。所以我們應該將BeanNameViewResolver的優先級調高,如果BeanNameViewResolver發現有ID爲userListEXCEL的bean就直接處理解析,如果沒有找到就將這個處理請求交由InternalResourceViewResolver。
剛剛XML配置中的Order屬性就是優先級,數值越小越優先。由於我們定義了InternalResourceViewResolver,所以我們需要將InternalResourceViewResolver設置一個較大的值,然後BeanNameViewResolver設置爲一個較小的值。
然後我們嘗試訪問/userListExport就會獲得一份Excel。
需要提醒的是,在以前的版本中使用AbstractExcelView,但是已經被廢棄了,現在是使用AbstractXlsxView這個接口。AbstractXlsxView導出的是xlsx文件後綴的excel文件。
順便一提:如果想導出PDF的話 是實現AbstractPdfView 同理也是使用BeanNameViewResolver作爲解析器。以下是需要實現PDF導出的依賴包的pom文件dependence:
<dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency>
SpringMVC的文件上傳
使用SpringMVC進行文件上傳功能相對比較簡單,使用CommonsMultipartResolver作爲解析器,以下是相應的配置:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8"></property> <property name="maxUploadSize" value="10485760000"></property> <property name="uploadTempDir" value="upload/temp"></property> <property name="maxInMemorySize" value="40960"></property> </bean>
還有一些依賴包:
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
最後就是相應的controller處理方法
@RequestMapping("/uploadFile.action") public ModelAndView updateFile(@RequestParam(value = "file",required = false) MultipartFile file, HttpSession session) throws IOException { ModelAndView modelAndView = new ModelAndView(); if (file == null || file.isEmpty()) { modelAndView.setViewName("redirect:/user/uploadFile.html"); } else { File targetFile = new File(session.getServletContext().getRealPath("/image"), file.getOriginalFilename()); if (!targetFile.getParentFile().exists() || !targetFile.getParentFile().isDirectory()) { targetFile.getParentFile().mkdirs(); } file.transferTo(targetFile); modelAndView.addObject("imagePath", targetFile.getName()); modelAndView.setViewName("showImage"); } return modelAndView; }
BeanNameViewResolver如果View的bean比較多會導致MVC的配置文件極度不簡潔,所以我們可以使用一個單獨的XML作爲View的bean定義:
<bean class="org.springframework.web.servlet.view.XmlViewResolver" p:order="20" p:location="views.xml" />
XmlViewResolver是定義view的xml文件位置。需要注意的是views.xml 定義的bean都不會被MVC容器中的bean所使用,這寫bean只提供給相應的解釋器使用。
views.xml的配置如下,其實就一個份普通的Spring配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userListEXCEL" class="com.maxfunner.view.UserListExcelView"/> </beans>