好的,没问题。下面是一篇关于在Spring Boot中集成JSP和FreeMarker等传统视图技术的文章,力求幽默风趣、通俗易懂,并包含丰富的代码示例。
Spring Boot 遇上老朋友:JSP 和 FreeMarker 的浪漫邂逅
各位看官,今天咱们聊点怀旧的,啊不,是经典的!在Spring Boot的世界里,它就像一个精力充沛的年轻人,拥抱各种新技术,玩转各种花样。但有时候,咱们这些老家伙(JSP和FreeMarker)也想出来溜达溜达,回忆回忆当年叱咤风云的岁月。
Spring Boot 呢,也很 open-minded,它说:“没问题,来吧,老朋友,我给你们安排!” 所以,今天咱们就来聊聊如何在 Spring Boot 里,让 JSP 和 FreeMarker 焕发第二春。
1. JSP:那个熟悉的味道
JSP (JavaServer Pages) 这玩意儿,估计是不少 Java 程序员的初恋。当年写个页面,Servlet 里拼 HTML 字符串那叫一个酸爽。有了 JSP,总算能把 Java 代码和 HTML 分开了,虽然还是有点藕断丝连,但也算进步了。
1.1 引入依赖
首先,咱们得告诉 Spring Boot,我们要用 JSP。在 pom.xml
里加入以下依赖:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
tomcat-embed-jasper
: 这个是 Tomcat 内嵌的 JSP 引擎,负责解析和执行 JSP 页面。注意scope
是provided
,意思是编译时需要它,但运行时 Tomcat 会提供,Spring Boot 打包的时候就不用把它打进去了,避免冲突。jstl
: JSP Standard Tag Library,JSP 标准标签库,提供了一堆常用的标签,比如c:forEach
、c:if
,让 JSP 页面更简洁。
1.2 配置 JSP 视图解析器
Spring Boot 默认情况下,会使用 Thymeleaf 作为视图引擎。要让它认识 JSP,我们需要配置一下视图解析器。在 application.properties
或 application.yml
里添加以下配置:
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.mvc.view.prefix
: JSP 页面存放的目录。这里我们约定放在/WEB-INF/jsp/
目录下。这个目录放在webapp
下,这样才能被 Tomcat 正确加载。spring.mvc.view.suffix
: JSP 页面的后缀名,一般是.jsp
。
1.3 创建 JSP 页面
在 src/main/webapp/WEB-INF/jsp/
目录下,创建一个 JSP 页面,比如 hello.jsp
:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Hello JSP</title>
</head>
<body>
<h1>Hello, ${name}!</h1>
<c:if test="${age > 18}">
<p>你已经成年了!</p>
</c:if>
<c:forEach var="item" items="${items}">
<p>${item}</p>
</c:forEach>
</body>
</html>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
: 引入 JSTL 核心标签库。${name}
: EL 表达式,用于获取 Model 中的数据。<c:if>
: JSTL 条件判断标签。<c:forEach>
: JSTL 循环标签。
1.4 Controller 代码
写一个 Controller,把数据传递给 JSP 页面:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("name", "张三");
model.addAttribute("age", 20);
List<String> items = Arrays.asList("苹果", "香蕉", "橘子");
model.addAttribute("items", items);
return "hello"; // 返回 JSP 页面名称,不包含前缀和后缀
}
}
@Controller
: 声明这是一个 Controller。@GetMapping("/hello")
: 映射/hello
请求到hello
方法。Model model
: 用于向视图传递数据。return "hello";
: 返回 JSP 页面名称。Spring Boot 会根据spring.mvc.view.prefix
和spring.mvc.view.suffix
自动拼接成完整的 JSP 路径/WEB-INF/jsp/hello.jsp
。
1.5 运行测试
启动 Spring Boot 应用,访问 http://localhost:8080/hello
,就能看到 JSP 页面了。
1.6 注意事项
- JSP 页面存放位置: 必须放在
src/main/webapp/WEB-INF/jsp/
目录下,否则 Tomcat 找不到。 - 依赖冲突: 如果项目中使用了其他视图引擎,可能会和 JSP 引擎冲突。需要仔细检查依赖,排除冲突。
- 性能问题: JSP 在运行时需要编译成 Servlet,性能相对较低。在高并发场景下,建议使用更高效的视图引擎,比如 Thymeleaf 或 FreeMarker。
2. FreeMarker:模板界的常青树
FreeMarker 是一个模板引擎,它可以把数据和模板结合起来,生成各种文本格式的文件,比如 HTML、XML、JSON 等。它的语法比较简洁,功能也很强大,在模板界也算得上是常青树了。
2.1 引入依赖
在 pom.xml
里加入 FreeMarker 的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
Spring Boot 已经集成了 FreeMarker,所以只需要引入 spring-boot-starter-freemarker
就可以了。
2.2 配置 FreeMarker
Spring Boot 默认情况下,会自动配置 FreeMarker。如果需要自定义配置,可以在 application.properties
或 application.yml
里添加以下配置:
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.cache=false
spring.freemarker.template-loader-path
: FreeMarker 模板存放的目录。这里我们约定放在classpath:/templates/
目录下,也就是src/main/resources/templates/
目录下。spring.freemarker.suffix
: FreeMarker 模板的后缀名,一般是.ftl
。spring.freemarker.cache
: 是否开启缓存。在开发环境下,建议关闭缓存,方便修改模板后立即生效。在生产环境下,可以开启缓存,提高性能。
2.3 创建 FreeMarker 模板
在 src/main/resources/templates/
目录下,创建一个 FreeMarker 模板,比如 hello.ftl
:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello FreeMarker</title>
</head>
<body>
<h1>Hello, ${name}!</h1>
<#if age > 18>
<p>你已经成年了!</p>
</#if>
<ul>
<#list items as item>
<li>${item}</li>
</#list>
</ul>
</body>
</html>
${name}
: FreeMarker 表达式,用于获取 Model 中的数据。<#if>
: FreeMarker 条件判断指令。<#list>
: FreeMarker 循环指令。
2.4 Controller 代码
写一个 Controller,把数据传递给 FreeMarker 模板:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("name", "李四");
model.addAttribute("age", 25);
List<String> items = Arrays.asList("西瓜", "葡萄", "草莓");
model.addAttribute("items", items);
return "hello"; // 返回 FreeMarker 模板名称,不包含后缀
}
}
@Controller
: 声明这是一个 Controller。@GetMapping("/hello")
: 映射/hello
请求到hello
方法。Model model
: 用于向视图传递数据。return "hello";
: 返回 FreeMarker 模板名称。Spring Boot 会根据spring.freemarker.template-loader-path
和spring.freemarker.suffix
自动拼接成完整的模板路径classpath:/templates/hello.ftl
。
2.5 运行测试
启动 Spring Boot 应用,访问 http://localhost:8080/hello
,就能看到 FreeMarker 页面了。
2.6 FreeMarker 的高级用法
FreeMarker 的功能非常强大,除了基本的变量输出和条件判断,还可以使用宏、函数、自定义指令等高级特性。
-
宏 (Macro): 类似于函数,可以封装一段模板代码,方便重复使用。
<#macro greet name> <h1>Hello, ${name}!</h1> </#macro> <@greet name="王五" />
-
函数 (Function): 可以调用 Java 代码,实现更复杂的逻辑。
// 定义一个函数 public String formatDate(Date date, String pattern) { SimpleDateFormat sdf = new SimpleDateFormat(pattern); return sdf.format(date); } // 在 FreeMarker 配置中注册函数 configuration.setSharedVariable("formatDate", new TemplateMethodModelEx() { @Override public Object exec(List arguments) throws TemplateModelException { Date date = (Date) ((TemplateDateModel) arguments.get(0)).getWrappedObject(); String pattern = arguments.get(1).toString(); return formatDate(date, pattern); } }); // 在模板中使用函数 ${formatDate(now, "yyyy-MM-dd")}
-
自定义指令 (Custom Directive): 可以自定义模板指令,实现更灵活的布局和组件化。
// 定义一个自定义指令 public class MyDirective implements TemplateDirectiveModel { @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { String name = params.get("name").toString(); env.getOut().write("<h1>Hello, " + name + "!</h1>"); if (body != null) { body.render(env.getOut()); } } } // 在 FreeMarker 配置中注册自定义指令 configuration.setSharedVariable("myDirective", new MyDirective()); // 在模板中使用自定义指令 <@myDirective name="赵六"> <p>这是一个自定义指令的内容。</p> </@myDirective>
2.7 注意事项
- 模板存放位置: 默认情况下,FreeMarker 模板放在
src/main/resources/templates/
目录下。 - 语法错误: FreeMarker 的语法比较严格,如果写错了,会抛出异常。
- 性能优化: FreeMarker 的性能相对较高,但如果模板过于复杂,也会影响性能。可以通过开启缓存、优化模板结构等方式来提高性能。
3. JSP vs FreeMarker:谁更胜一筹?
JSP 和 FreeMarker 都是优秀的视图技术,各有优缺点。
特性 | JSP | FreeMarker |
---|---|---|
语法 | 混合了 Java 代码和 HTML | 类似于脚本语言,更简洁 |
性能 | 较低,需要编译成 Servlet | 较高,模板引擎直接解析 |
功能 | 依赖 JSTL 等标签库,功能较简单 | 功能强大,支持宏、函数、自定义指令 |
适用场景 | 小型项目,对性能要求不高 | 中大型项目,需要更灵活的模板引擎 |
学习曲线 | 较陡峭,需要熟悉 Java 和 JSTL | 较平缓,语法简洁易懂 |
总结一下:
- 如果你是一个 Java 老鸟,喜欢在页面里写点 Java 代码,那就选 JSP。
- 如果你追求简洁、高效,喜欢用模板引擎来分离前后端,那就选 FreeMarker。
- 当然,你也可以根据项目的具体情况,选择最合适的视图技术。
4. Spring Boot 的选择:拥抱未来,不忘初心
Spring Boot 作为一个现代化的框架,鼓励使用更先进的视图技术,比如 Thymeleaf、React、Vue 等。但它也并没有抛弃 JSP 和 FreeMarker 这些老朋友,而是提供了良好的集成支持。
Spring Boot 的理念是:拥抱未来,不忘初心。它既能让你体验最新的技术,也能让你在熟悉的环境中继续开发。
所以,无论你选择 JSP 还是 FreeMarker,Spring Boot 都会给你提供最好的支持。
5. 总结
今天咱们聊了聊如何在 Spring Boot 中集成 JSP 和 FreeMarker。虽然它们都是比较传统的视图技术,但在某些场景下仍然很有用。
希望这篇文章能帮助你更好地理解 Spring Boot 的视图技术,并在项目中做出正确的选择。
记住,技术没有好坏之分,只有适用与不适用。选择最适合你的,才是最好的!
好了,今天就到这里。各位看官,下次再见!