视图的作用时渲染模型数据,将模型里的数据以某种形式呈现给客户,Spring的视图实现类都位于org.springframework.web.servlet.view包中。SpringMVC为逻辑视图名的解析提供了不同的策略,可以在Spring web上下文中配置一种或多种策略,并指定它们的先后顺序。下面是一些常用的视图解析器。
视图解析器类型 | 说明 |
InternalResourceViewResolver | 将视图名解析为一个URL文件,一般使用该解析器将视图名映射为保存在WEB-INF目录中的程序文件。优先级最低。 |
BeanNameViewResolver | 将逻辑视图名解析为一个Bean,Bean的id等于逻辑视图名 |
ContentNegotiatingViewResolver | 它不负责具体的视图解析,而是作为一个中间人的角色根据请求所要求的MIME类型,从上下文中选择一个合适的视图解析器,再将视图解析工作委托其负责,优先级最高。 |
1. JSP和JSTL
1.1 使用InternalResourceViewResolver(略)
1.2 使用Spring表单标签(略)
2. Excel
如果想要返回Excel视图,则仅需扩展Spring的AbstractXlsView,实现BuildExcelDocument方法即可(AbstractExcelView已被废止,AbstractXlsxView总是会出现问题)。AbstractXlsView基于POI API,需要添加相应的依赖项。
2.1 添加依赖项
org.apache.poi和org.apache.poi.poi-ooxml
2.2 扩展AbstractXlsView
public class UserListExcelView extends AbstractXlsView {
/**
* @since 1.8+
*/
protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setHeader("Content-Disposition","inline;filename="+new String("用户列表.xls".getBytes(),"iso8859-1"));//必须为iso8859-1,不然会乱码
response.setContentType("application/ms-excel");
response.setCharacterEncoding("utf-8");
OutputStream outputStream=response.getOutputStream();
List<User> list=(List<User>)model.get("userList");
Sheet sheet=workbook.createSheet("users");
Row header=sheet.createRow(0);
header.createCell(0).setCellValue("用户名");
header.createCell(1).setCellValue("密码");
header.createCell(2).setCellValue("年龄");
header.createCell(3).setCellValue("出生日期");
int rowNum=1;
for(User user:list){
Row row=sheet.createRow(rowNum++);
row.createCell(0).setCellValue(user.getUserName());
row.createCell(1).setCellValue(user.getPassword());
row.createCell(2).setCellValue(user.getAge());
row.createCell(3).setCellValue(user.getBirthday().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
}
}
2.3 spring配置文件
<!--配置EXCEL视图-->
<!-- <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0" /> 可省略-->
<bean id="userListExcelView" class="view.UserListExcelView"/>
2.4 Controller方法
@RequestMapping("/testExcelView")
public String testExcelView(ModelMap mm){
mm.addAttribute("userList",list);
return "userListExcelView";
}
3. pdf视图
PDF视图和Excel视图类似,也使用一个Bean作为视图对象,扩展AbstractPdfView类,实现BuildPdfDocument方法即可。
3.1 添加依赖项
itext和itextasian
3.2 扩展AbstractPdfView
public class UserPdfView extends AbstractPdfView {
/**
* @since 1.8+
*/
protected void buildPdfDocument(Map<String, Object> model, com.lowagie.text.Document document, com.lowagie.text.pdf.PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setHeader("Content-Disposition","inline;filename="+new String("用户列表.pdf".getBytes(),"iso8859-1"));//编码必须为iso8859-1
List<User> list=(List<User>)model.get("userList");
Table table=new Table(4);//列数
table.setWidth(40);//列宽
table.setBorder(1);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
BaseFont cnBaseFont=BaseFont.createFont("STSongStd-Light","UniGB-UCS2-H",false);
Font cnFont=new Font(cnBaseFont,10,Font.NORMAL, Color.BLUE);
table.addCell(buildFontCell("用户名",cnFont));
table.addCell(buildFontCell("密码",cnFont));
table.addCell(buildFontCell("年龄",cnFont));
table.addCell(buildFontCell("出生日期",cnFont));
for(User user:list){
table.addCell(buildFontCell(user.getUserName(),cnFont));
table.addCell(user.getPassword());
table.addCell(String.valueOf(user.getAge()));
table.addCell(user.getBirthday().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
document.add(table);
}
private Cell buildFontCell(String content,Font font)throws RuntimeException{
try{
Phrase phrase=new Phrase(content,font);
return new Cell(phrase);
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
3.3 Controller编写
@RequestMapping("/testPdfView")
public ModelAndView testPdfView(ModelMap mm){
List<User> list=init();
mm.addAttribute("userList",list);
return new ModelAndView(new UserPdfView(),mm);
}//这里传递进去的是一个视图类,所以不用配置,excel视图也可以这样。
4. xml视图
4.1 添加依赖项
com.thoughtworks.xstream和org.springframework.oxm
4.2 spring配置文件
<bean id="userListXml" class="org.springframework.web.servlet.view.xml.MarshallingView"
p:modelKey="userList"
p:marshaller-ref="xmlMarshaller"/>
<bean id="xmlMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="streamDriver">
<bean class="com.thoughtworks.xstream.io.xml.StaxDriver"/>
</property>
<property name="annotatedClasses">
<list>
<value>entity.User</value>
</list>
</property>
</bean>
4.3 Controller编写
@RequestMapping("/testXmlView")
public String testXmlView(ModelMap mm){
mm.addAttribute("userList",list);
return "userListXml";//userListXml已经在XML文件中配置
}
5. json视图
5.1 添加依赖项
jackson-databind
5.2 spring配置文件
<!--配置json视图-->
<bean id="userListJson" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"
p:modelKey="userList"/>
5.3 Controller方法
@RequestMapping("/testJosnView")
public String testJsonView(ModelMap mm){
mm.addAttribute("userList",list);
return "userListJson";
}
6. 使用XmlViewResolver
当定义视图的bean数量太多,可以考虑使用XmlViewResolver定义视图的配置信息。
<!--配置XmlviewResolver-->
<bean class="org.springframework.web.servlet.view.XmlViewResolver" p:order=”20” p:location=”WEB-INF/views/views.xml”/>
views.xml是一个普通的Spring配置文件,如可以定义userExcelView:
<!--配置Excel视图-->
<bean id=”userExcelView” class="view.UserListExcelView"/>