蓝凌EKP产品:JSP 性能优化和 JSTL/EL要点检查列表
Spring Filter 实现 Redis 功能及 JSP 内置对象作用域性能优化
在 Java Web 项目中,我们经常会遇到两类问题:
使用 Spring Filter 对请求进行拦截,并操作 Redis 实现缓存或限流
JSP 页面中使用内置对象,如果作用域选择不当,会带来性能问题
本文将结合实际开发场景,说明原理、实现方式及优化方法。
一、Spring Filter 如何使用 Bean
一、Spring Filter 实现 Redis 功能
1. 背景
在实际业务中,我们可能需要:
请求限流
用户访问缓存
统计接口调用次数
这些功能通常借助 Redis 来实现。为了拦截所有请求并统一处理,可以使用 Filter。
2. 问题
普通 Filter 由 Servlet 容器管理(如 Tomcat),无法直接使用 Spring 容器管理的 Bean(如 RedisTemplate),如果直接 @Autowired
会失败。
3. 解决方式
方案 A:DelegatingFilterProxy(推荐)
Spring 提供 DelegatingFilterProxy
,原理如下:
Tomcat FilterRegistry|v DelegatingFilterProxy|v Spring 管理的业务 Filter Bean(可以依赖 RedisTemplate)
Tomcat 负责调用入口
Spring 管理业务 Filter,支持依赖注入
可以安全使用 RedisTemplate、Service 等 Spring Bean
示例:
public class KmssSessionRepositoryFilter extends SessionRepositoryFilter<MapSession> implements ContextLoadedListener {//自行查找蓝凌实现。
}
在 web.xml 或 Spring Boot 配置中注册:
<!--filter:springSessionRepositoryFilterfilter-name必须是这个,并且在 sys\authentication\spring.xml中有对应的bean--><filter><filter-name>springSessionRepositoryFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class></filter><filter-mapping><filter-name>springSessionRepositoryFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
这样,Filter 就可以安全使用 Redis 功能,同时支持 Spring 注入。
二、为什么 JSP 内置对象作用域会产生性能问题
在 JSP 页面中,我们经常用 <c:set>
设置变量:
<c:set var="canPrint" value="false" scope="page" />
1. JSP 作用域
JSP 支持四种作用域:
Scope | 生命周期 | 典型用途 |
---|---|---|
page | 单个页面请求 | 临时变量,渲染当前页面 |
request | 单次 HTTP 请求 | 跨 JSP 或 Servlet 传递数据 |
session | 用户会话级别 | 用户登录状态、会话数据 |
application | 应用级别 | 全局共享数据 |
2. 性能问题原理
如果临时页面变量使用了 request、session 或 application:
Request/Session 范围的对象可能需要序列化(尤其在分布式环境中)
大量临时变量占用内存,增加 GC 压力
Request 范围中对象过多,会增加每次请求的查找成本
而 page
作用域的变量:
仅在当前 JSP 页面有效
生命周期短,JSP 渲染完成即释放
无需序列化或跨请求传递
性能最佳
3. 正确示例
<!-- 临时渲染变量,page 作用域 --> <c:set var="canPrint" value="false" scope="page" />
错误示例(会增加性能负担):
<!-- 临时渲染变量却使用 session 作用域 --> <c:set var="canPrint" value="false" scope="session" />
三、结合 Filter 与 JSP 优化说明
在实际项目中,流程通常如下:
Filter 拦截请求 → 使用 Redis 缓存/统计请求
Controller 返回数据 → 转发到 JSP 页面
JSP 渲染页面 → 使用
<c:set>
或其他内置对象
优化点:
Filter 负责业务逻辑(如 Redis 功能)
JSP 页面只使用
page
作用域存放临时变量避免把 Filter 逻辑产生的临时数据放入 Session 或 Request,减少内存和序列化压力
原理图:
请求 ---> Filter(DelegatingFilterProxy, Redis操作)
|
v
Controller
|
v
JSP渲染(page作用域临时变量)
EKP 的正确指导实现
1. JSTL 正确写法
推荐写法:
<c:set var="canPrint" value="false" scope="page" />
避免默认作用于 session 导致 Redis 写入。
2. 容器对象提前声明
<%
if (request.getAttribute("nodeAdditionalMap") == null) {pageContext.setAttribute("nodeAdditionalMap", new HashMap());
}
%>
//防止 xxx.abc 触发全类扫描。
3 pageContext.removeAttribute 显式 scope
pageContext.removeAttribute("canPrint", PageContext.PAGE_SCOPE);
防止错误地修改 session。
四、总结EL 容器对象提前声明
Spring Filter + Redis
使用
DelegatingFilterProxy
或SpringBeanUtils.getBean()
获取 Spring BeanFilter 本身由 Tomcat 管理,但业务逻辑由 Spring 管理
支持 Redis 缓存、限流、统计等功能
JSP 内置对象作用域优化
临时页面变量使用
page
作用域避免使用 request/session/application 存储短期临时数据
提升性能,降低内存压力