承接上篇 MVC 設計,本文實現用戶註冊頁面,引入 Apache Commons BeanUtils 簡化參數綁定,並自定義註解實現服務端數據驗證。
register.jsp 僅包含用戶名、密碼、暱稱三個字段,驗證邏輯放在服務端。
跳轉註冊頁:UserServlet.register() 直接返回 user/register.jsp。
提交處理:表單提交至 user.do?method=add,由 UserServlet.add() 接收參數、創建 User 對象、調用 DAO 存儲,最後客戶端跳轉至用戶列表。
/** 接收註冊信息,添加用戶 */
public String add(HttpServletRequest req, HttpServletResponse resp) {
String username = req.getParameter("username");
String password = req.getParameter("password");
String nickname = req.getParameter("nickname");
User u = new User();
u.setUsername(username);
u.setPassword(password);
u.setNickname(nickname);
userDao.add(u);
return "client:user.do?method=list"; // 客戶端跳轉
}
手動 setXxx 繁瑣且難維護,引入 BeanUtils 利用反射自動映射請求參數到 JavaBean。
commons-beanutils、commons-logging、commons-collections。
public class RequestUtil {
public static Object setParams(Class> clz, HttpServletRequest req) {
Map maps = req.getParameterMap();
Set keys = maps.keySet();
Object o = null;
try {
o = clz.newInstance();
for (String key : keys) {
String[] arrs = maps.get(key);
if (arrs.length > 1) {
BeanUtils.copyProperty(o, key, arrs);
} else {
BeanUtils.copyProperty(o, key, arrs[0]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return o;
}
}
public String add(HttpServletRequest req, HttpServletResponse resp) {
User u = (User) RequestUtil.setParams(User.class, req);
userDao.add(u);
return "client:user.do?method=list";
}
BeanUtils 無法直接處理 java.util.Date,需自定義 Converter。
public class DateConvert implements Converter {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Object convert(Class> type, Object value) {
if (value != null && !"".equals(value)) {
try { return sdf.parse((String) value); }
catch (ParseException e) { e.printStackTrace(); }
}
return null;
}
}
註冊後即可自動轉換:ConvertUtils.register(new DateConvert(), Date.class);
public enum ValidType { NOTNULL, LENGTH, NUM }
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidCheck {
ValidType type();
String errsMsg();
}
public static boolean isChecked(Class> clz, HttpServletRequest req) {
Field[] fields = clz.getDeclaredFields();
boolean isValid = true;
Map errors = new HashMap<>();
req.setAttribute("errors", errors);
for (Field f : fields) {
if (f.isAnnotationPresent(ValidCheck.class)) {
ValidCheck vc = f.getAnnotation(ValidCheck.class);
if (vc.type() == ValidType.NOTNULL) {
if (!isNotNull(f.getName(), req)) {
isValid = false;
errors.put(f.getName(), vc.errsMsg());
}
}
}
}
return isValid;
}
private static boolean isNotNull(String field, HttpServletRequest req) {
String val = req.getParameter(field);
return val != null && !"".equals(val.trim());
}
public String add(HttpServletRequest req, HttpServletResponse resp) {
if (!RequestUtil.isChecked(User.class, req)) {
return "user/register.jsp"; // 驗證失敗回顯頁面
}
ConvertUtils.register(new DateConvert(), Date.class);
User u = (User) RequestUtil.setParams(User.class, req);
userDao.add(u);
return "client:user.do?method=list";
}
利用 EL 表達式 ${errors.username} 顯示錯誤信息,${param.username} 回填用戶輸入。
本篇構建了「註冊頁 → 參數自動綁定 → 註解驗證 → 錯誤回顯」的完整鏈路,為後續業務擴展奠定基礎。