跨设备访问Java EE+JSF+Primefaces应用时数据库内容未更新
解决JSF/PrimeFaces CRUD应用跨设备数据更新不显示的问题
嘿,这个问题我之前帮不少做JEE Web开发的朋友解决过,结合你的技术栈(Java EE+JSF+PrimeFaces+NetBeans+GlassFish),大概率是数据缓存未及时刷新导致的,我给你拆解几个最可能的原因和对应的解决步骤:
1. 先检查Managed Bean的作用域
如果你的用户列表是存在@SessionScoped或者@ApplicationScoped的Bean里,那不同设备(或者不同会话的用户)拿到的就是缓存的旧数据:
- 展示数据列表的Bean,应该用
@ViewScoped(最适合JSF视图生命周期)或者@RequestScoped,这样每次加载视图或者发起请求时,都会重新从数据库拉取最新数据。 - 举个例子,把原来的
@SessionScoped改成@ViewScoped(记得让Bean实现Serializable):@ManagedBean @ViewScoped public class UserBean implements Serializable { // 你的用户列表、业务逻辑都放这儿 }
2. JPA EntityManager的一级缓存要及时清理
JPA的EntityManager默认会缓存已经查询过的实体,如果你添加完数据后没刷新缓存或者重新查询,就会拿到旧数据:
- 在保存用户的方法里,完成持久化后,调用
flush()同步到数据库,再用clear()清空一级缓存,最后重新查询用户列表:public void addUser(User newUser) { entityManager.persist(newUser); entityManager.flush(); // 立即把数据同步到MySQL entityManager.clear(); // 清空EntityManager的本地缓存 // 重新查询最新的用户列表 userList = entityManager.createQuery("SELECT u FROM User u", User.class).getResultList(); }
3. 让PrimeFaces组件实时刷新数据
有些PrimeFaces组件比如p:dataTable,可能会在客户端缓存数据,或者没触发组件更新:
- 保存用户成功后,用PrimeFaces的Ajax API手动更新数据表格:
// PrimeFaces 6.x及以上版本用这个写法 public void addUser() { // 先执行保存用户的逻辑 // ... // 更新数据表格,把"userDataTable"换成你页面上表格的实际ID PrimeFaces.current().ajax().update("userDataTable"); } - 还要检查
p:dataTable的cache属性,如果设成了true,改成false,关掉客户端缓存:<p:dataTable id="userDataTable" value="#{userBean.userList}" var="user" cache="false"> <!-- 你的列定义 --> </p:dataTable>
4. 浏览器缓存也要考虑
不同设备的浏览器可能缓存了旧页面,导致看不到新数据:
- 在页面头部加几个禁用缓存的元标签:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="0" /> - 或者写个Filter在服务器端设置响应头,全局禁止缓存:
@WebFilter("/*") public class NoCacheFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); httpResponse.setHeader("Pragma", "no-cache"); httpResponse.setDateHeader("Expires", 0); chain.doFilter(request, response); } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} }
5. 最后检查GlassFish的服务器级缓存(少见但有可能)
如果你的GlassFish开了会话复制或者服务器级缓存,可能会导致数据同步延迟:
- 登录GlassFish的管理控制台,看看有没有开不必要的缓存服务,暂时关掉试试能不能解决问题。
建议你先从Bean作用域和JPA缓存这两个最常见的点入手排查,测试的时候,手机加完数据后,用其他设备强制刷新页面(Ctrl+F5),先排除浏览器缓存的问题。
内容的提问来源于stack exchange,提问作者Fouzi Otoman
相关产品推荐
相关产品推荐

