视图和视图解析器
- 视图是业务处理后展现给用户的内容,而在此之前,要通过控制器得到对应的数据模型,如果是非逻辑视图,则不会经过 视力解析器定位视图,而是直接将数据模型渲染便结束了;而逻辑视图则要对其进一步解析,以定位真实视图,这就是视 图解析器的作用.而视图则是把从控制器查询回来的数据模型进行渲染,以显示给请求者查看.
视图
-
在请求之后,Spring MVC 控制器获取了对应的数据,绑定到数据模型中,那么视图就可以展示数据模型的信息了.
-
Spring MVC中定义了多种视图,只是常用的并不是太多,它们都要满足视图的定义,它就是接口------View,
视图接口定义
package org.springframework.web.servlet;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface View {
//响应状态属性
String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";
//定义数据模型下取出变量路径
String PATH_VARIABLES = View.class.getName() + ".pathVariables";
//选择响应内容类型
String SELECTED_CONTENT_TYPE = View.class.getName() + ".selectedContentType";
//响应客户端的类型;getContentType表示返回一个 字符串,标明给用户佬类型的文件响应,可以是HTML,JSON,PDF等
String getContentType();
//渲染方法, var1是数据模型;render方法是一个渲染视图的方法,通过它就可以渲染视图了.
void render(Map<String, ?> var1, HttpServletRequest var2, HttpServletResponse var3) throws Exception;
}
- 当控制器返回ModelAndView的时候,视图解析器就会解析它,然后将数据模型传递给render方法,这样就能够渲染视图了. 在Spring MVC中实现视图的类很多,比如JSTL视图JstlView, JSON视图MappingJackson2JsonView, PDF视图 AbstractPdfView等,通过它们的render方法,Spring MVC就可以将数据模型渲染成为各类视图,以满足各种需求.
视图解析器
视图解析器定义
package org.springframework.web.servlet;
import java.util.Locale;
/**
* 视图解析器定义
* @param var1 视图名称
* @param var2 用于国际化的
*/
public interface ViewResolver {
View resolveViewName(String var1, Locale var2) throws Exception;
}
- Spring MVC自带了很多视图解析器,所以它能够解析各种各样需要逻辑视图的控制器返回.之前我们配置了InternalResourceViewResolver, 有时候在控制器中并没有返回一个ModelAndView,而只是返回了一个字符串,它也能够渲染视图,因为视力解析器生成了对应的视图.
不返回ModelAndView的视图
@RequestMapping("/getHeaderAndCookie")
public String testHeaderAndCookie(
@RequestHeader(value = "User-Agent", required = false, defaultValue = "attribute") String userAgent,
@CookieValue(value = "JSESSIONID", required = false, defaultValue = "MyJsessionId") String jsessionId) {
System.out.println("User-Agent: " + userAgent);
System.out.println("JSESSIONID: " + jsessionId);
return "index";
}
实例: Excel视图的使用
-
视图和视图渲染器是Spring MVC中重要的一步,JSTL视图和JSON视图,这是最常用的视图技术.有时候还需要导出Excel的功能,这也是常用的 功能,主要的功能是导出数据库中所有角色的信息.
-
对于Excel而言,Spring MVC所推荐的是使用AbstractXlsView,它实现了视图接口,从其命名也可以知道它只是一个抽象类,不能生成实例对象. 它自己定义了一个抽象方法------buildExcelDocument要去实现.其它的方法Spring的AbstractXlsView已经实现了,所以完成这个方法便 可以使用Excel的视图功能了, AbstractXlsView类定义的buildExcelDocument方法:
/**
* 创建Excel文件
* @param model -------Spring MVC数据模型
* @param workbook -------- POI workbook对象
* @param request ----------- http请求对象
* @param response ----------- http响应对象
* @throws Execption 异常
*/
protected abstract void buildExcelDocument(Map<String, Object> model,Workbook workbook,
HttpServletRequest request, HttpServletResponse response) throws Exception
- 这个方法的主要任务是创建一个Workbook,它要用到POI的API,这需要我们自行下载架包:
<dependencies>
<!-- 使用Apache POI生成和解析Excel文件 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
- 假设需要一个所有角色信息的功能,但是将来也许还有其他的导出功能。为了方便,先定义一个接口,这个接口主要是让开发者自定义生成Excel的规则,
package top.bfylu.chapter15.view;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.Map;
/**
* @author bfy
* @version 1.0.0
* 创建时间: 18-5-7 下午10:03
* @email bfyjian@gmail.com
*/
public interface ExcelExportService {
public void makeWorkBook(Map<String, Object> model, Workbook workbook);
}
- 有了这个接口还需要完成一个可实例化的Excel视图类-----ExcelView,对于导出而言还需要一个下载文件名称,所以不会定义一个文件名(fileName) 属性,由于该视图不是一个逻辑视图,所以无须视图解析器也可以运行它,其定义:
package top.bfylu.chapter15.view;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.servlet.view.document.AbstractXlsView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* 定义Excel视图
*
* @author bfy
* @version 1.0.0
* 创建时间: 18-5-7 下午10:20
* @email bfyjian@gmail.com
*/
public class ExcelView extends AbstractXlsView {
//文件名
private String fileName = null;
//导出视图自定义接口
private ExcelExportService excelExportService = null;
//构造方法1
public ExcelView(ExcelExportService excelExportService) {
this.excelExportService = excelExportService;
}
//构造方法2
public ExcelView(String viewName, ExcelExportService excelExportService) {
this.setBeanName(viewName);
}
@Override
protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
//没有自定义接口
if (excelExportService == null)
throw new RuntimeException("导出服务接口不能为null!!");
//文件名不为空,为空则使用请求路径中的字符串作为文件名
if (!StringUtils.isEmpty(fileName)) {
//进行字符转换
String reqCharset = request.getCharacterEncoding();
reqCharset = reqCharset == null ? "UTF-8" : reqCharset;
fileName = new String(fileName.getBytes(reqCharset), "ISO8859-1");
//设置下面文件名
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
}
//回调接口方法,使用自定义生成Excel文档
excelExportService.makeWorkBook(model, workbook);
}
/********Setter and Getter***************/
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public ExcelExportService getExcelExportService() {
return excelExportService;
}
public void setExcelExportService(ExcelExportService excelExportService) {
this.excelExportService = excelExportService;
}
}
使用ExcelView导出Excel
/**
* @author bfy
* @version 1.0.0
* 创建时间: 2018/5/4 下午5:07
* @email bfyjian@gmail.com
*/
@Controller
@RequestMapping("role")
public class RoleController {
@Autowired
private RoleService roleService = null;
/***********使用ExcelView导出Excel*************/
@RequestMapping(value = "/export", method = RequestMethod.GET)
public ModelAndView export() {
//模型和视图
ModelAndView mv = new ModelAndView();
//Excel视图,并设置自定义导出接口
ExcelView ev = new ExcelView(exportService());
//文件名
ev.setFileName("所有角色.xlsx");
//设置SQL后台参数
RoleParams roleParams = new RoleParams();
//限制1万条
PageParams page = new PageParams();
page.setStart(0);
page.setLimit(10000);
roleParams.setPageParams(page);
//查询
List<Role> roleList = roleService.findRoles(roleParams);
//加入数据模型
mv.addObject("roleList", roleList);
mv.setView(ev);
return mv;
}
@SuppressWarnings({"unchecked"})
public ExcelExportService exportService() {
//使用Lambda表达式自定义导出excel规则
return (Map<String, Object> model, Workbook workbook) -> {
//获取用户列表
List<Role> roleList = (List<Role>) model.get("roleList");
//生成Sheet
Sheet sheet = workbook.createSheet("所有角色");
//加载标题
Row title = sheet.createRow(0);
title.createCell(0).setCellValue("编号");
title.createCell(1).setCellValue("名称");
title.createCell(2).setCellValue("备注");
//便历角色列表,生成一行行的数据
for (int i = 0; i<roleList.size(); i++) {
Role role = roleList.get(i);
int roleIdx = i + 1;
Row row = sheet.createRow(roleIdx);
row.createCell(0).setCellValue(role.getId());
row.createCell(1).setCellValue(role.getRoleName());
row.createCell(2).setCellValue(role.getNote());
}
};
}
}
来源:oschina
链接:https://my.oschina.net/u/3505611/blog/1808620