跟大家说明一下,本来用户模块是计划昨天(2月9日)更新的,但是不巧昨天下午到今天上午八点断网了,我也不知道csdn怎么了,就自动把这篇未完成的博文发表了,在这里跟大家说明一下,非常抱歉各位,让大家看了空文章。
在开发模块功能之前,我们先来封装一些高复用的响应对象或者工具类
一、高复用服务对象的封装
(1)、请求对象的封装
/**序列化高复用响应对象(类)
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class ServerResponse implements Serializable{
// 返回状态,内容,时间
private int status;
private String msg;
private T data;
private ServerResponse(int status){
this.status = status;
}
private ServerResponse(int status, T data){
this.status = status;
this.data = data;
}
private ServerResponse(int status, String msg, T data){
this.status = status;
this.msg = msg;
this.data = data;
}
private ServerResponse(int status, String msg){
this.status = status;
this.msg = msg;
}
@JsonIgnore
// 判断请求是否成功
public boolean isSuccess(){
return this.status == ResponseCode.SUCCESS.getCode();
}
public int getStatus(){
return status;
}
public String getMsg(){
return msg;
}
public T getData(){
return data;
}
// 处理成功的请求状态
public static ServerResponse createBySuccess(){
return new ServerResponse(ResponseCode.SUCCESS.getCode());
}
public static ServerResponse createBySuceessMessage(String msg){
return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg);
}
public static ServerResponse createBySuccess(T data){
return new ServerResponse(ResponseCode.SUCCESS.getCode(), data);
}
public static ServerResponse createBySuccess(String msg, T data){
return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg, data);
}
// 处理失败的请求状态
public static ServerResponse createByError(){
return new ServerResponse(ResponseCode.ERROR.getCode());
}
public static ServerResponse createByErrorMessage(String errorMessage){
return new ServerResponse(ResponseCode.ERROR.getCode(), errorMessage);
}
public static ServerResponse createByErrorCodeMessage(int errorCode, String errorMessage){
return new ServerResponse(errorCode, errorMessage);
}
}
我们在java文件夹下创建util或者common包,我的是common包,用来存放我们自己封装的公用对象。
创建一个名为ServerResponse的类,当然也可以叫其他名称,直观方便就好,让他实现序列化接口,这样在任何地方调用我们的ServerResponse都可以返回JSON序列,降低了项目的耦合度,提升了开发效率。根据返回结果,我们需要定义三个字段,分别是返回状态status,返回信息msg,返回时间data,这里的data指定为泛型,为以后模块的开发提供一个公有的时间字段。接着我们封装了四个私有的无泛型的构造方法,这个是在类中使用的,不暴露给其他类使用,所以我们封装为私有的,分别返回请求状态,请求状态和时间,请求状态和信息及请求时间,最后返回请求状态和请求信息,这是一个理想化的返回结果。然后我们可以看到一个isSuccess()的方法,这个方法用来判断请求是否成功,返回boolean类型,这个方法是不能被JSON序列化的,所以我添加了@JsonIgnore注解,防止方法被序列化。最后就是封装了暴露给外面的构造方法以及基于泛型的返回信息的通用构造方法。还有一点值得注意,在我们这个类的最外面我标红了一句代码,使用JsonSerialize注解的include属性来把返回值为空的方法也去除掉,不让其JSON序列化。这样一个高复用的响应对象就封装完成了。
(2)、公用请求状态工具类的封装
/**封装请求的状态(枚举实现)
*/
public enum ResponseCode {
SUCCESS(0, "SUCCESS"),
ERROR(1, "ERROR"),
NEED_LOGIN(10, "NEED_LOGIN"),
ILLEGALARGUMENT(2, "ILLEGALARGUMENT");
private final int code;
private final String desc;
ResponseCode(int code, String desc){
this.code = code;
this.desc = desc;
}
public int getCode(){
return code;
}
public String getDesc(){
return desc;
}
}
对于一些公用字段或者专用字段的处理,一般而言只是做一个工具类就行了,但是在实际的项目开发中这样做往往会使产品经理不满意。针对于这样的场景,Java早就提供了解决方法,那就是将这些字段以枚举的方式封装起来。如果需要使用枚举,我们需要像声明类一样进行声明:pulic enum ResponseCode,这样就声明了一个名为ResponseCode的枚举;在一个枚举里面,我们可以直接来对我们的字段进行处理,例如我想封装一个请求成功的字段,我就可以这样写SUCCESS(0, "SUCCESS"),多个字段之间用逗号进行分割,然后再写构造,再写getter就可以了。
正题开始:
我们先来看一下用户模块主要实现哪些功能:
用户模块对于整个项目而言还是比较简单的,并没有难于实现的功能。
二、用户模块-登录功能的实现
登录功能逻辑:从数据库中查询用户名和密码,如果都存在且都正确的话,则表示用户登录成功,此时为了确保用户的登录状态,需要把用户存放到session中去。
/**用户服务接口
*/
@Controller
@RequestMapping("/user/")
public class UserController {
@Autowired
private IUserService iUserService;
/**
* 用户登录
* @param username
* @param password
* @param session
* @return
*/
@RequestMapping(value = "login.do", method = RequestMethod.POST)
@ResponseBody
public ServerResponse login(String username, String password, HttpSession session){
ServerResponse response = iUserService.login(username, password);
if(response.isSuccess()){
session.setAttribute(Const.CURRENT_USER, response.getData());
}
return response;
}
使用Controller注解告诉Spring MVC容器这是一个Controller,并交给Spring自行处理,使用RequestMapping注解将请求全部映射到user空间下,使用Autowired注解,导入user服务;在方法之前使用RequestMapping注解指定方法的请求接口名称以及请求方式,使用ResponseBody注解,声明该方法的返回值是一个JSON序列。这样Controller就写完了。
我们再来看用户服务层:
// 用户登录
public ServerResponse login(String username, String password){
int resultCount = userMapper.checkUsername(username);
if(resultCount == 0){
return ServerResponse.createByErrorMessage("用户名不存在");
}
String md5Password = MD5Util.MD5EncodeUtf8(password);
User user = userMapper.selectLogin(username, md5Password);
if(user == null){
return ServerResponse.createByErrorMessage("密码错误");
}
user.setPassword(StringUtils.EMPTY);
return ServerResponse.createBySuccess("登录成功", user);
}
我们使用MyBatis封装好的Mapper注入方式来处理SQL语句,通过userMapper操作SQL语句返回给我们一一个包含SQL执行结果的资源句柄,而且是int型,如果查询结果为0则尝试登录的用户不存在,否则将返回值中的密码password字段通过apache.lang3包下的内置工具类StringUtils.EMPTY设置为空;如果上述逻辑都没问题,即表示数据库中存在该用户,之后要检验用户的登录密码是否正确,通过selectLogin方法去数据库中查找,如果结果为null,表示密码错误,否则将返回值中的密码password字段通过apache.lang3包下的内置工具类StringUtils.EMPTY设置为空并返回登录成功的用户信息。
到这里,用户模块的第一部分就完成了,在下接我会继续实现用户模块的功能,同时也要封装一个通用的字段验证方法。敬请期待。