springMVC中的ModelAndView,Model,ModelMap

写在前面

本文基于springboot环境来进行测试,没有这个环境的,可以参考这里,隔空👍这位同学的用心总结。下面我们正式开始。

1:整体分析

先看下ModelAndView源码:

public class ModelAndView {// 逻辑视图地址@Nullableprivate Object view;// 数据@Nullableprivate ModelMap model;
}

其中的Object view代表的就是视图,在jsp环境中可以认为就是jsp页面,ModelMap model就是数据,来看下ModelMap的定义:

public class ModelMap extends LinkedHashMap<String, Object> {}

可以看到继承了java.util.LinkedHashMap,所以其也是一个java.util.Map。通过Object view就有了页面,通过字典数据结构ModelMap model就有了页面需要的数据,二者结合就可以生成最终展示给用户的页面了。对于数据spring还提供了另外的选择,即接口org.springframework.ui.Model该接口在spring-context模块中,可以认为该接口是ModelMap外的另外一个选择。源码如下:

public interface Model {// 添加视图需要的数据Model addAttribute(String attributeName, @Nullable Object attributeValue);
}

其实现类

public class ExtendedModelMap extends ModelMap implements Model {}

可以看到其不仅仅实现了Model接口,还继承了类ModelMap,因此兼具二者的能力。接下来我们通过一个完整的例子来看一下。

2:综合例子

2.1:定义jsp

我们先来定义jsp页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Titletitle>
head>
<body>${user.id}---${user.userName}---${user.note}
body>
html>

2.2:定义User

public class User {private Long id;private String userName;private String note;...getter setter toString...
}

2.3:使用ModelAndView

2.3.1:代码

@RequestMapping("/useModelAndView")
public ModelAndView useModelAndView() {ModelAndView mv = new ModelAndView();// 设置数据模型User user = new User();user.setId(1L);user.setUserName("张三");user.setNote("张三的歌");mv.addObject("user", user);// 设置视图为user.jspmv.setViewName("user");return mv;
}

2.3.2:测试

在这里插入图片描述

2.3:使用Model

2.3.1:代码

@RequestMapping("/userModel")
public String userModel(Model model) {User user = new User();user.setId(2L);user.setUserName("李四");user.setNote("李四的小姨子");model.addAttribute("user", user);return "user";
}

2.3.2:测试

在这里插入图片描述

2.4:使用ModelMap

2.4.1:代码

@RequestMapping("/useModelMap")
public ModelAndView useModelMap(ModelMap modelMap) {User user = new User();user.setId(3L);user.setUserName("王五");user.setNote("王五的表姐");ModelAndView mv = new ModelAndView();// 设置视图mv.setViewName("user");// 通过ModelMap设置数据modelMap.addAttribute("user", user);return mv;
}

2.4.2:测试

在这里插入图片描述

3:其它视图

除了我们例子中的jsp视图(逻辑视图,即需要视图解析器),还有很多其它的视图,比如json视图,pdf视图,excel视图,但是这些视图都是非逻辑视图,即不需要视图解析器,所有的视图都会实现View接口,源码如下:

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";@Nullabledefault String getContentType() {return null;}// 渲染数据方法void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)throws Exception;
}

这里我们以pdf为例进行说明,pdf视图定义了接口AbstractPdfView,源码如下:

public abstract class AbstractPdfView extends AbstractView {protected abstract void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,HttpServletRequest request, HttpServletResponse response) throws Exception;
}

如果想要自定义PDF视图,只需要继承该抽象类,并实现抽象方法buildPdfDocument就可以了。

3.1:定义导出pdf的服务层接口

@FunctionalInterface
public interface PdfExportService {public void make(Map<String, Object> model,Document document,PdfWriter pdfWriter,HttpServletRequest request,HttpServletResponse response);
}

3.2:定义pdf视图

/*** 通过集成AbstractPdfView定义pdf视图*/
public class PdfView extends AbstractPdfView {private PdfExportService pdfExportService;public PdfView(PdfExportService pdfExportService) {this.pdfExportService = pdfExportService;}// pdf数据渲染接口@Overrideprotected void buildPdfDocument(Map<String, Object> model,Document document,PdfWriter pdfWriter,HttpServletRequest request,HttpServletResponse response) throws Exception {pdfExportService.make(model, document, pdfWriter, request, response);}
}

3.3:定义控制器

// 导出pdf
@RequestMapping("/export/pdf")
public ModelAndView exportPdf() {ModelAndView mv = new ModelAndView();// 需要渲染到pdf文档上的用户列表数据List<User> userList = new ArrayList<>();userList.add(new User(1L, "zhangsan", "the song of zhangsan"));userList.add(new User(2L, "lisi", "the xiaoyizi of lisi"));userList.add(new User(3L, "wangwu", "the biaojie of wangwu"));userList.add(new User(4L, "zhaoliu", "the guma of wangwu"));mv.addObject("userList", userList);// 定义PDF视图并设置View pdfView = new PdfView(exportService());mv.setView(pdfView);return mv;
}private PdfExportService exportService() {return (model, document, pdfWriter, request, response) -> {try {// A4纸张document.setPageSize(PageSize.A4);// 设置页面标题document.addTitle("用户信息");// 换行document.add(new Chunk("\n"));// 表格4行PdfPTable pdfPTable = new PdfPTable(3);// 单元格//PdfPCell cell = null;// 字体,定义为蓝色加粗Font f8 = new Font();f8.setColor(Color.BLUE);f8.setStyle(Font.BOLD);String[] headTileArr = new String[]{ "id", "username", "note" };for (String headTitle : headTileArr) {// 表格的表头标题PdfPCell cell = new PdfPCell(new Paragraph(headTitle, f8));// 居中cell.setHorizontalAlignment(1);// 添加到表格中pdfPTable.addCell(cell);}// 设置数据到表格中List<User> userList = (List<User>) model.get("userList");for (User user : userList) {PdfPCell idCell = new PdfPCell(new Paragraph(user.getId() + ""));pdfPTable.addCell(idCell);PdfPCell usernameCell = new PdfPCell(new Paragraph(user.getUserName()));pdfPTable.addCell(usernameCell);PdfPCell noteCell = new PdfPCell(new Paragraph(user.getNote()));pdfPTable.addCell(noteCell);}// 添加表格到文档中document.add(pdfPTable);} catch (Exception e) {e.printStackTrace();}};
}

3.4:测试

在这里插入图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部