InternalResourceView 实现服务器端(SSI)渲染与转发技术
InternalResourceView
来实现SSI功能(Server Side Includes, SSI)是一种将一个文件的内容包含到另一个文件的机制。本次通过一个内容管理系统(CMS)的案例,探讨动态地合并和渲染页面。
类结构设计
业务说明:
内容管理系统允许编辑者创建和维护网页内容。为了提高内容的可重用性和一致性,编辑者希望能够在不同页面中包含共有的部分,如页眉、页脚或导航菜单。
核心技术:
- 服务器端包含(SSI) :一种将一个源文件的内容包含到另一个源文件的技术。
InternalResourceView
:Spring MVC中的一个视图,用于渲染服务器内部资源,如JSP页面。- JSP:JavaServer Pages,一种动态网页技术,允许在HTML中嵌入Java代码。
工作流程图:
核心代码:
1. Spring MVC配置(Java配置方式):
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.InternalResourceView;
@Configuration
public class WebConfig {
@Bean
public View internalResourceView() {
return new InternalResourceView();
}
}
2. JSP页面(包含SSI):
<!DOCTYPE html>
<html>
<head>
<title>Dynamic Page</title>
<!-- 包含共有的头部资源 -->
<%@ include file="header.jsp" %>
</head>
<body>
<h1>${pageTitle}</h1>
<!-- 页面主要内容 -->
<p>${pageContent}</p>
<!-- 包含共有的底部资源 -->
<%@ include file="footer.jsp" %>
</body>
</html>
3. 控制器:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class PageController {
@GetMapping("/page")
public ModelAndView getPage() {
ModelAndView modelAndView = new ModelAndView("dynamicPage");
modelAndView.addObject("pageTitle", "Sample Page");
modelAndView.addObject("pageContent", "This is a sample page content.");
return modelAndView;
}
}
4. InternalResourceView 实现转发核心代码
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
// 将模型对象作为请求属性公开,这样在渲染视图时可以访问这些数据。
exposeModelAsRequestAttributes(model, request);
// 如果有辅助工具,也作为请求属性公开。
exposeHelpers(request);
// 准备用于渲染的请求分发器的路径,这通常是一个JSP页面的路径。
String dispatcherPath = prepareForRendering(request, response);
// 获取目标资源的RequestDispatcher,这通常是一个JSP页面。
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
if (rd == null) {
// 如果无法获取RequestDispatcher,抛出异常。
throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
"]: Check that the corresponding file exists within your web application archive!");
}
// 判断是否已经是包含请求或响应已经被提交。
// 如果是,则使用include来包含视图,否则使用forward来转发请求。
if (useInclude(request, response)) {
response.setContentType(getContentType()); // 设置响应的Content-Type。
if (logger.isDebugEnabled()) {
logger.debug("Including [" + getUrl() + "]");
}
// 使用RequestDispatcher的include方法将模型数据包含到客户端请求中。
rd.include(request, response);
}
else {
// 如果不是包含请求,使用forward方法将请求转发到视图。
// 注意:被转发的资源应该自己确定内容类型。
if (logger.isDebugEnabled()) {
logger.debug("Forwarding to [" + getUrl() + "]");
}
rd.forward(request, response);
}
}
优点:
- 提高内容重用性:通过SSI,共有的页面部分可以在多个页面中重用,减少了代码重复。
- 简化页面维护:更新共有部分时,只需修改一个文件,所有引用该部分的页面都会自动更新。
- 动态内容生成:SSI可以在服务器端动态地将内容插入到页面中,提高了内容的灵活性。
- 与Spring MVC的无缝集成:
InternalResourceView
与Spring MVC集成,简化了配置和使用。
转载自:https://juejin.cn/post/7385776238789083145