当前位置: 首页 > news >正文

Spring MVC 逻辑视图(JSP、Thymeleaf、FreeMarker)与非逻辑视图(JSON、Excel、PDF、XML)详解及示例

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 {
    @Bean
    public 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 {
    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver());
        return engine;
    }

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("classpath:/templates/");
        resolver.setSuffix(".html");
        return resolver;
    }

    @Bean
    public 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 {
    @Override
    protected 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 {
    @Override
    protected 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、ThymeleafHTML配置ViewResolver前端页面渲染
非逻辑视图JSON、Excel、PDFJSON、XLS、PDF直接实例化View或使用注解API响应、文件下载、特殊格式

关键区别
  • 逻辑视图:依赖模板引擎生成HTML,需配置视图解析器,适合前后端分离场景。
  • 非逻辑视图:直接返回数据或文件,无需解析器,适合API、文件导出等场景,配置更灵活。

相关文章:

  • 2025年AI生成引擎搜索发展现状与趋势总结​​
  • 【数学】线性代数(Python)
  • 水果成篮 -- 滑动窗口
  • Franka双臂机器人:多领域革新与核心技术深度解析
  • 数组划分使元素总和最接近
  • 如何迁移 GitHub 仓库到 GitLab?
  • 最新版PhpStorm超详细图文安装教程,带补丁包(2025最新版保姆级教程)
  • 三类人解决困境的方法
  • 【项目管理】第5章 信息系统管理 --知识点整理
  • Oracle 表空间高水位收缩全攻略
  • Ubuntu 22.04 AI大模型环境配置及常用工具安装
  • 消息队列(Message Queue)简介
  • AIGC2——AI生成艺术的边界与伦理:艺术性、版权与美学价值的争议
  • 学习海康VisionMaster之多直线查找
  • 使用python访问mindie部署的vl多模态模型
  • 【数据结构】二叉搜索树
  • Android Input——输入子系统(三)
  • C++ Primer Plus 编程练习题 第六章 分支语句和逻辑运算符
  • 544 eff.c:1761处loop vect 分析
  • C++ 基本语法
  • 落实中美经贸高层会谈重要共识,中方调整对美加征关税措施
  • 《新时代的中国国家安全》白皮书(全文)
  • 民生谣言误导认知,多方联动守护清朗——中国互联网联合辟谣平台2025年4月辟谣榜综述
  • 专访|日本驻华大使金杉宪治:对美、对华外交必须在保持平衡的基础上稳步推进
  • 江西省司法厅厅长张强已任江西省委政法委分管日常工作副书记
  • 重庆三峡学院回应“中标价85万设备网购300元”:已终止采购