Spring MVC 邏輯視圖與非邏輯視圖詳解及示例
一、邏輯視圖與非邏輯視圖的定義
類型 | 定義 |
---|---|
邏輯視圖 | 通過視圖解析器(ViewResolver )將邏輯名稱(如 success )映射到具體視圖實現。 |
非邏輯視圖 | 直接返回具體視圖對象(如 JsonView ),或通過注解/方法直接生成響應,無需解析器。 |
二、邏輯視圖與非邏輯視圖的接口類型
類型 | 接口示例 |
---|---|
邏輯視圖 | JSP、Thymeleaf、FreeMarker(模板引擎生成HTML) |
非邏輯視圖 | JSON(MappingJackson2JsonView )、Excel(ExcelView )、PDF(PdfView )、XML等 |
三、邏輯視圖與非邏輯視圖的對比
維度 | 邏輯視圖 | 非邏輯視圖 |
---|---|---|
視圖解析 | 需要配置視圖解析器(如 ThymeleafViewResolver ) | 無需解析器,直接返回視圖對象或通過注解(如 @ResponseBody ) |
響應格式 | HTML(模板引擎渲染) | JSON、Excel、PDF、XML 等特定格式 |
解耦性 | 控制器與視圖解耦,通過名稱間接關聯 | 控制器直接綁定視圖實現,耦合度較高 |
配置復雜度 | 需配置解析器和模板引擎 | 簡單(如直接使用注解或自定義View類) |
典型場景 | 前端頁面渲染(如網頁跳轉) | API返回數據、文件下載、特殊格式輸出 |
四、代碼示例
1. 邏輯視圖示例
(1)JSP 示例
// 配置JSP視圖解析器(在Spring配置類中)
@Configuration
public class WebConfig implements WebMvcConfigurer {@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix("/WEB-INF/views/"); // JSP文件存放路徑resolver.setSuffix(".jsp"); // 文件后綴return resolver;}
}// 控制器方法
@Controller
public class UserController {@GetMapping("/user/jsp")public String showUserJsp(Model model) {model.addAttribute("userName", "John Doe");return "userProfile"; // 返回邏輯視圖名,對應userProfile.jsp}
}// userProfile.jsp 文件(存放于 /WEB-INF/views/)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>User Profile</title></head>
<body><h1>User Name: ${userName}</h1>
</body>
</html>
(2)Thymeleaf 示例
// 配置Thymeleaf視圖解析器(在Spring配置類中)
@Configuration
public class WebConfig implements WebMvcConfigurer {@Beanpublic SpringTemplateEngine templateEngine() {SpringTemplateEngine engine = new SpringTemplateEngine();engine.setTemplateResolver(templateResolver());return engine;}@Beanpublic SpringResourceTemplateResolver templateResolver() {SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();resolver.setPrefix("classpath:/templates/");resolver.setSuffix(".html");return resolver;}@Beanpublic ThymeleafViewResolver viewResolver() {ThymeleafViewResolver resolver = new ThymeleafViewResolver();resolver.setTemplateEngine(templateEngine());return resolver;}
}// 控制器方法
@Controller
public class UserController {@GetMapping("/user/thymeleaf")public String showUserThymeleaf(Model model) {model.addAttribute("user", new User("John", "Doe"));return "userProfile"; // 對應userProfile.html模板}
}// userProfile.html(存放于 templates/)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>User Profile</title></head>
<body><h1 th:text="${user.firstName} + ' ' + ${user.lastName}"></h1>
</body>
</html>
2. 非邏輯視圖示例
(1)JSON 示例
// 直接返回JSON(使用@ResponseBody注解)
@RestController
public class UserController {@GetMapping("/user/json")public User getUserJson() {return new User("John", "Doe"); // 自動序列化為JSON}
}// 或通過ModelAndView返回JSON視圖
@Controller
public class UserController {@GetMapping("/user/json-view")public ModelAndView getUserJsonView() {ModelAndView modelAndView = new ModelAndView();modelAndView.setView(new MappingJackson2JsonView());modelAndView.addObject("user", new User("John", "Doe"));return modelAndView;}
}
(2)Excel 示例(使用Apache POI)
// 自定義Excel視圖類
public class ExcelView extends AbstractView {@Overrideprotected void renderMergedOutputModel(Map<String, Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception {response.setContentType("application/vnd.ms-excel");response.setHeader("Content-Disposition", "attachment; filename=users.xls");HSSFWorkbook workbook = new HSSFWorkbook();HSSFSheet sheet = workbook.createSheet("Users");HSSFRow headerRow = sheet.createRow(0);headerRow.createCell(0).setCellValue("First Name");headerRow.createCell(1).setCellValue("Last Name");List<User> users = (List<User>) model.get("users");for (int i = 0; i < users.size(); i++) {HSSFRow row = sheet.createRow(i + 1);row.createCell(0).setCellValue(users.get(i).getFirstName());row.createCell(1).setCellValue(users.get(i).getLastName());}workbook.write(response.getOutputStream());workbook.close();}
}// 控制器方法
@Controller
public class ExcelController {@GetMapping("/generate/excel")public ModelAndView generateExcel() {ModelAndView modelAndView = new ModelAndView();modelAndView.setView(new ExcelView());modelAndView.addObject("users", Arrays.asList(new User("John", "Doe"),new User("Jane", "Smith")));return modelAndView;}
}
(3)PDF 示例(使用iText)
// 自定義PDF視圖類
public class PdfView extends AbstractView {@Overrideprotected void renderMergedOutputModel(Map<String, Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception {response.setContentType("application/pdf");response.setHeader("Content-Disposition", "inline; filename=document.pdf");Document document = new Document();PdfWriter.getInstance(document, response.getOutputStream());document.open();document.add(new Paragraph("Hello PDF!"));document.close();}
}// 控制器方法
@Controller
public class PdfController {@GetMapping("/generate/pdf")public ModelAndView generatePdf() {ModelAndView modelAndView = new ModelAndView();modelAndView.setView(new PdfView());return modelAndView;}
}
五、總結表格
類型 | 接口示例 | 響應格式 | 是否需要解析器 | 配置方式 | 典型場景 |
---|---|---|---|---|---|
邏輯視圖 | JSP、Thymeleaf | HTML | 是 | 配置ViewResolver | 前端頁面渲染 |
非邏輯視圖 | JSON、Excel、PDF | JSON、XLS、PDF | 否 | 直接實例化View或使用注解 | API響應、文件下載、特殊格式 |
關鍵區別
- 邏輯視圖:依賴模板引擎生成HTML,需配置視圖解析器,適合前后端分離場景。
- 非邏輯視圖:直接返回數據或文件,無需解析器,適合API、文件導出等場景,配置更靈活。