在第四期内容中,我们主要解决的是用 ajax 技术,实现用户在注册页面时候,输出要注册的用户名,当输入完用户名,点击空白处的时候,前端发送请求,检测用户名是否重复。
处理
在 regist.html 处,要进行如下处理:

在 controller 包下的 SysUserController 下应该新增加一个 checkUsernameUsed 方法:

增加这两段代码后,就可以实现我们预期的功能,但海撒存在一些问题:
- 响应乱码问题,浏览器打开开发者模式,响应的"可用"中,显示的是乱码
2 响应格式不规范,处理方式不规范
后端响应回来的信息,应该有一个统一的格式,前后端共同遵守
==》
响应一个 JSON 串
{
"code":"100/200/300/400...":业务状态码 本次请求业务是否成功...
"message":业务状态码的补充说明
"data":{ } 本次响应的数据 List<Schedule>...
... ...
}
- 当校验不通过,即用户名已经被占用的时候,无法阻止表单提交
解决
创建 common 包
创建类 Result:
java
/**
* 全局统一响应结果封装类
* 用于标准化API接口的返回格式,包含状态码、响应消息和业务数据
* @param <T> 响应数据的泛型类型,支持任意数据类型
*/
public class Result<T> {
// 返回码:表示请求处理的状态(成功/失败/异常等)
private Integer code;
// 返回消息:对处理结果的文字描述(如"操作成功"、"参数错误"等)
private String message;
// 返回数据:业务处理的具体数据,泛型支持各种数据类型
private T data;
/**
* 无参构造方法
* 用于JSON序列化等场景
*/
public Result() {
}
/**
* 构建基础响应对象
* @param data 响应数据
* @param <T> 数据类型
* @return 包含数据的Result对象
*/
protected static <T> Result<T> build(T data) {
Result<T> result = new Result<>();
if (data != null) {
result.setData(data);
}
return result;
}
/**
* 构建完整响应对象
* @param body 响应数据
* @param code 状态码
* @param message 响应消息
* @param <T> 数据类型
* @return 包含数据、状态码和消息的Result对象
*/
public static <T> Result<T> build(T body, Integer code, String message) {
Result<T> result = build(body);
result.setCode(code);
result.setMessage(message);
return result;
}
/**
* 通过枚举构建响应对象
* @param body 响应数据
* @param resultCodeEnum 结果状态枚举(包含状态码和消息)
* @param <T> 数据类型
* @return 基于枚举的完整Result对象
*/
public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
Result<T> result = build(body);
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
return result;
}
/**
* 快速构建成功响应
* @param data 响应数据
* @param <T> 数据类型
* @return 包含成功状态和数据的Result对象
*/
public static <T> Result<T> ok(T data) {
return build(data, ResultCodeEnum.SUCCESS);
}
/**
* 链式设置响应消息
* @param msg 响应消息
* @return 当前Result对象(支持链式调用)
*/
public Result<T> message(String msg) {
this.setMessage(msg);
return this;
}
/**
* 链式设置状态码
* @param code 状态码
* @return 当前Result对象(支持链式调用)
*/
public Result<T> code(Integer code) {
this.setCode(code);
return this;
}
// Getter和Setter方法
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
创建类 ResultCodeEnum:
java
public enum ResultCodeEnum {
SUCCESS(200, "success"),
USERNAME_ERROR(501, "usernameError"),
PASSWORD_ERROR(503, "passwordError"),
NOTLOGIN(504, "notLogin"),
USERNAME_USED(505, "usernameUsed");
private Integer code;
private String message;
private ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode(){
return code;
}
public String getMessage() {
return message;
}
}
我们要将这个 Result 对象转换成 JSON 串,需要导 jackson 包
controller 包下面的 SysUserControoller checkUsernameUsed 方法:
java
/**
* 注册时,接收要注册的用户名,校验用户名是否被占用的业务接口
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void checkUsernameUsed(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 接收用户名
String username = req.getParameter("username");
// 调用服务处层业务处理方法查询用户名是否已经有对应的用户
SysUser sysUser = userService.finByUsername(username);
Result result = Result.ok(null);
if (null != sysUser) {
result = Result.build(null, ResultCodeEnum.USERNAME_USED);
}
// 将 result 对象转换为 JSON 串相应给客户端
ObjectMapper objectMapper = new ObjectMapper();
String info = objectMapper.writeValueAsString(result);
// 告诉客户端响应的是一个是字符串
resp.setContentType("application/json;charse=UTF-8");
resp.getWriter().write(info);
}
regist.html 修改:

这样就解决了两个问题。
在 SysUserController 下面的 checkUsernameUsed 中将 result 对象转换为 JSON 串的逻辑会经常被使用,我们可用抽象出一个方法:
java
public class WebUtil {
private static ObjectMapper objectMapper;
static {
objectMapper = new ObjectMapper();
}
// 专门用于向客户端响应 JSON 串的方法
public static void writeJson(HttpServletResponse resp, Result result) {
// 告诉客户端响应的是一个是字符串
resp.setContentType("application/json;charse=UTF-8");
// 将 result 对象转换为 JSON 串相应给客户端
try {
String info = objectMapper.writeValueAsString(result);
resp.getWriter().write(info);
} catch (IOException e) {
e.printStackTrace();
}
}
}