蓝凌EKP产品:JSP性能优化及JSTL/EL要点核查指南

2个月前发布 gsjqwyl
12 0 0

蓝凌EKP产品:JSP性能优化及JSTL/EL要点核查指南

Spring Filter实现Redis功能与JSP内置对象作用域性能优化

在蓝凌的办公自动化系统里,其功能丰富的门户系统、流程审批、报表统计以及消息与公告模块十分突出。门户访问能够应对高并发状况,审批环节需要查询大量权限和节点信息,致使数据库查询压力较大,报表查询的数据量也颇为可观(例如考勤统计、流程统计、费用报表等)。用户可能会在短时间内频繁刷新报表页面。消息数量和公告列表属于“热门数据”,被频繁访问,但它们的更新频率并不高(比如公告每天更新数次)。这些场景都需要借助缓存redis来进行数据的存储与页面数据的临时存放,从而让传统的JSP办公自动化系统在性能和架构方面,向“高并发、分布式、用户体验优良”的现代平台靠拢。因此,蓝凌针对办公自动化系统的这些痛点,深入研究,不放过任何可以改进的细节,决定从以下两个方面解决缓存的性能问题。

一、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:springSessionRepositoryFilter
     filter-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优化结合说明

实际项目中流程通常如下:
1. Filter拦截请求 → 使用 Redis缓存/统计请求
2. Controller返回数据 → 转发至JSP页面
3. 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容器对象提前声明

  1. Spring Filter + Redis
    • 使用DelegatingFilterProxySpringBeanUtils.getBean()获取Spring Bean
    • Filter由Tomcat管理,业务逻辑由Spring管理
    • 支持Redis缓存、限流、统计等功能
  2. JSP内置对象作用域优化
    • 临时页面变量用page作用域
    • 避免用request/session/application存短期临时数据
    • 提升性能,降低内存压力
© 版权声明

相关文章

没有相关内容!

暂无评论

none
暂无评论...