JSP JavaBean
JavaBean 规范、useBean / setProperty / getProperty、作用域与最佳实践。
JavaBean 规范
- 公开的无参构造函数 —— 容器要能
newInstance() - 私有字段 + 公开 getter/setter —— 属性名由方法名推出
- 可序列化 —— 实现
Serializable,便于会话持久化
package com.example;
import java.io.Serializable;
public class User implements Serializable {
private int id;
private String name;
private String email;
public User() { }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
// 布尔属性的 getter 可以叫 isXxx
public boolean isActive() { return id > 0; }
}The property name comes from getName/setName: strip the prefix and lowercase the first letter. A field named userName with getName exposes the property name — EL follows the methods, not the field.
在 JSP 里用
<%@ page contentType="text/html;charset=UTF-8" %>
<jsp:useBean id="user" class="com.example.User" scope="request"/>
<%-- 手动赋值 --%>
<jsp:setProperty name="user" property="name" value="张三"/>
<%-- 自动绑定同名请求参数 --%>
<jsp:setProperty name="user" property="*"/>
<p>ID:<jsp:getProperty name="user" property="id"/></p>
<p>姓名:<jsp:getProperty name="user" property="name"/></p>
<%-- 用 EL 更简洁 --%>
<p>邮箱:${user.email}</p>ID:0
姓名:张三
邮箱:<jsp:useBean> means "find, create only if absent": an existing object in that scope is reused. That makes it safe to place anywhere on the page.
四种作用域
| scope | Lifetime | Typical use |
|---|---|---|
| page | 当前页面 | 临时对象 |
| request | 当前请求 | Controller 传给 View 的数据 |
| session | 当前会话 | 登录用户、购物车 |
| application | 整个应用 | 全局配置、缓存 |
为什么现在少用 useBean
<%-- useBean 写法:三行标签,属性名靠字符串,改错不报错 --%>
<jsp:useBean id="user" class="com.example.User" scope="request"/>
<jsp:setProperty name="user" property="*"/>
<p><jsp:getProperty name="user" property="name"/></p>
<%-- Controller + EL 写法:数据由 Servlet 准备,页面只读 --%>
<p>${user.name}</p>property="*" is hard to debug: a typo or type mismatch raises nothing, the property is just empty. Modern practice constructs and populates the bean explicitly in the servlet and lets the page read with EL — a breakpoint then tells the whole story.
${user.total} appearing a dozen times means a dozen queries. Compute once in the controller and store the result.JavaBean 规范
- 公开的无参构造函数 —— 容器要能
newInstance() - 私有字段 + 公开 getter/setter —— 属性名由方法名推出
- 可序列化 —— 实现
Serializable,便于会话持久化
package com.example;
import java.io.Serializable;
public class User implements Serializable {
private int id;
private String name;
private String email;
public User() { }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
// 布尔属性的 getter 可以叫 isXxx
public boolean isActive() { return id > 0; }
}属性名 name 来自 getName / setName:去掉前缀、首字母小写。所以字段叫 userName 但方法叫 getName,属性名就是 name——EL 用的是方法名推出来的那个。
在 JSP 里用
<%@ page contentType="text/html;charset=UTF-8" %>
<jsp:useBean id="user" class="com.example.User" scope="request"/>
<%-- 手动赋值 --%>
<jsp:setProperty name="user" property="name" value="张三"/>
<%-- 自动绑定同名请求参数 --%>
<jsp:setProperty name="user" property="*"/>
<p>ID:<jsp:getProperty name="user" property="id"/></p>
<p>姓名:<jsp:getProperty name="user" property="name"/></p>
<%-- 用 EL 更简洁 --%>
<p>邮箱:${user.email}</p>ID:0
姓名:张三
邮箱:<jsp:useBean> 的语义是「查找,没有才创建」:指定作用域里已有同名对象就直接用,没有才 new 一个。所以它可以安全地放在页面任意位置。
四种作用域
| 作用域 | 生命周期 | 典型用途 |
|---|---|---|
| page | 当前页面 | 临时对象 |
| request | 当前请求 | Controller 传给 View 的数据 |
| session | 当前会话 | 登录用户、购物车 |
| application | 整个应用 | 全局配置、缓存 |
为什么现在少用 useBean
<%-- useBean 写法:三行标签,属性名靠字符串,改错不报错 --%>
<jsp:useBean id="user" class="com.example.User" scope="request"/>
<jsp:setProperty name="user" property="*"/>
<p><jsp:getProperty name="user" property="name"/></p>
<%-- Controller + EL 写法:数据由 Servlet 准备,页面只读 --%>
<p>${user.name}</p>property="*" 的隐式绑定难调试:参数名拼错、类型不匹配都不报错,只是属性为空。现代做法是在 Servlet 里显式 new User() 并逐个赋值,页面只用 EL 读——出了问题断点一看就清楚。
getter 里不要做重活(查库、远程调用)。EL 每次求值都会调用 getter,一个页面里 ${user.total} 可能出现十几次,就是十几次查询。需要算好的值,在 Controller 里算完放进属性。