前面用了六节内容把项目的项目配置,项目日志、项目管理以及数据库建立起来了。
用户中心主要是我们对账号的管理,用户登录账号等,现在暂时不做权限角色的管理,只是先做一个角色的用户登录。
在本项目中我们要使用Lombok注解,可以帮我们省略大量重复代码编写工作,正所谓:任何技术的出现都是为了解决某一类问题,我们在学习基础的时候应该都学过getter/setter/to String在数据封装就会用到这些,这些代码都是可以通过快捷键一键生成的,会使一个类中出现大量无含量的代码,然而使用Lombok可以让我们将这些代码省略掉,只需要加一个注解即可,这就是现在开发中常用到的
org.projectlombok
lombok
1.18.22
在pom.xml中添加这个依赖,
依赖添加完成之后,我们要在IDEA中安装Lombok这个插件,方便我们的开发,使得我们开发工具去支持这个功能
点击项目的File -> Settings
打开,点击Plugins ,在搜索框中搜索Lombok,点击Install进行安装,安装后点击Apply,再点击OK
Lombok组件安装完成之后,可能需要 重启一下IDEA
我们最早用到的是@Date注解,里面有@Getter/@Setter,具体的等会使用的时候进行具体讲解。
首先实现用户列表的功能,这个就是从数据库中捞出数据,在后台页面上展示即可,这里的查找就会用到分页的功能,虽然是我们自己的管理,没几个账号,就不适用分页了,我们会在文章管理功能页面使用分页。
用户中心添加的总目录参考:
在项目personblog/entity下新建一个实体类,命名为Userji
即在创建的entity包中创建一个User.java的实体类,
将数据进行封装,引入@Date注解
在类的上方添加一个@Date注解,这个注解就是我们刚刚引入的Lombok,可以帮我们省略@Getter/@Setter方法
package com.blog.personblog.entity;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 添加@Date注解
*/
@Data
public class User {
/**
* 主键id
*/
private Integer id;
/**
* 用户名
*/
private Integer userName;
/**
* 密码
*/
private String passWord;
/**
* 邮箱
*/
private String email;
/**
* 上次登录时间
*/
private Date lastLoginTime;
/**
* 手机号
*/
private Integer phone;
/**
* 昵称
*/
private String nickname;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
}
在我们创建的service包中,创建一个UserService.java类型,该类是一个接口类,将我们的业务功能暴露出去,可以供接口层调用
在包service处右键New -> Java Class
选择Interface,填入接口名UserService
此类实现了用户增删改查功能接口, 其中增加、修改和删除只需要在接口层返回一个成功或者失败的信息即可,不需要返回信息
package com.blog.personblog.service;
import com.blog.personblog.entity.User;
import java.util.List;
public interface UserService {
/**
* 查询所有用户列表
* @return
*/
List findAll();
/**
* 添加用户
* @param user
*/
void createUser(User user);
/**
* 修改用户
* @param user
*/
void updateUser(User user);
/**
* 修改用户
* @param id
*/
int deleteUser(int id);
}
实现类则实现了业务接口这个功能,继承这个接口,具体的业务逻辑都会在这个类中写,很重要,同时和数据库接口相连,进行调用数据库的接口,实现数据处理。
在创建的lmpl包New -> Java Class,命名为UserServiceImpl.java,同时继承UserService接口,用关键字implements去实现继承接口,
生成 UserServiceImpl.java文件,
使用关键字 implements 实现接口,添加具体的实现类
然后按快捷键 Alt+Enter,勾选implements methods实现方法
弹出一个弹出框,里面就是在UserService.java中创建的方法,然后点击OK,
就生成了四个具体的重写方法
package com.blog.personblog.service.Impl;
import com.blog.personblog.entity.User;
import com.blog.personblog.service.UserService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 四个重写方法
*
*/
@Service
public class UserServiceImpl implements UserService {
@Override
public List findAll() {
return null;
}
@Override
public void createUser(User user) {
}
@Override
public void updateUser(User user) {
}
@Override
public int delete(int id) {
return 0;
}
}
在我们创建的Mapper包中,创建一个UserMapper.java接口
这里我们在传递参数时用了一个@param注解,这个注解一般在传递多个参数条件才使用。
/**
* 多条件参数下一般使用@param注解
*
*/
int updateByExampleSelective(@Param("record") AccessRecord record, @Param("example") AccessRecordExample example);
/**
* 单条件参数下一般不使用@param注解
*
*/
int updateByPrimaryKey(AccessRecord record);
我们这里业务没这么复杂,不涉及到多个参数,但我们也使用一下,作为扩展
@Param的主要作用就是给参数命名,参数命名后就能根据参数得到参数值,正确得将参数传入sql语句中,(一般通过#{} 得方式,${}会有sql注入问题)
在mapper包右键 -> New -> Java Class
选择Interface命名为UserMapper.java
package com.blog.personblog.mapper;
import com.blog.personblog.entity.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMapper {
/**
* 查询全部用户信息
*
* @return
*/
List findAll();
/**
* 添加用户
* @param user
*/
void create(@Param("user") User user);
/**
* 修改用户
* @param user
*/
void update(@Param("user") User user);
/**
* 删除用户
* @param id
*/
int delete(@Param("id") int id);
}
可以看到,在UserMapper类上多了一个@Repository注解,
作用@Repository是需要在Spring中配置扫描包地址,然后生成dao层的bean,之后被注入ServiceImpl中,如果不加在实现类中引用了mapper层的类来调用dao层的处理,使用@Autowired注解被标红线,找不到bean
加了这个之后,还需要在启动类上注解并加上Mapper包的地址,这样我们就可以正常使用mapper接口了,
也可以使用@Mapper注解,用了就不需要在启动类上配置扫描地址,则是通过mapper.xml中的namespace对应相关的mapper类,Spring将动态的生成Bean后注入ServiceImpl中
在上面,我们在Mapper层中用的是@Repository注解,所以我们要在启动类上加一个扫描包的注解,去扫描Mapper包的接口类。
启动类:
package com.blog.personblog;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
/**
* 添加扫描包
*/
@MapperScan("com.blog.personblog.mapper")
public class PersonBlogApplication {
public static void main(String[] args) {
SpringApplication.run(PersonBlogApplication.class, args);
}
}
我们在resource下的mapper文件夹中新建一个UserMapper.xml文件,这里放的就是一些对数据库的操作,一些SQL语句,
下面开始编写xml文件
之所以这样写可以看看官方文档的解释:https://mybatis.org/mybatis-3/sqlmap-xml.html#select
标签中放的是数据表里的字段和实体类中属性名的映射 - property放的是属性名
然后开始写sql语句,注意sql中的id要和mapper中的方法名一致
如果在写sql语句的过程中,表名和相关属性都爆红,点击右侧的Database是空白的,说明数据库没有导入,
点击+号,点击Data Source ,点击MySQL
填写建立数据库就设立好的用户名和密码,填入表名称,点击Apply,点击OK
这时再点击Database就会有相应的表格出现了,也就不会爆红了
- @Param的主要作用就是给参数命名,参数命名后就能根据参数得到参数值,正确得将参数传入sql语句中,(一般通过#{} 得方式,${}会有sql注入问题)
- 在这里就用到了 #{}
- mybatis 非常的智能,如果配置了resultMap,返回值统一使用 resultMap=“BaseResultMap”,mybatis会根据查询到的条目数量自动进行判断,如果是一条就返回对象,如果是多条就返回List对象列表
- useGeneratedKeys =true 这个表示插入数据之后返回一个自增的主键id给你对应实体类中的主键属性。通过这个设置可以解决在主键自增的情况下通过实体的getter方法获取主键(当然还需要keyproperty指明数据库中返回的主键id给实体类中的哪个属性)。
- keyproperty=主键,这样就可以解决在主键自增的情况下获取主键。
INSERT INTO person_user (username, password, email, last_login_time, phone, nickname, create_time, update_time)
VALUES (#{userName}, #{passWord}, #{email}, #{lastLoginTime}, #{phone}, #{nickname}, #{createTime}, #{updateTime})
update person_user
username=#{userName},
password=#{passWord},
email=#{email},
last_login_time=#{lastLoginTime},
phone=#{phone},
nickname=#{nickname},
WHERE id = #{id}
delete from person_user where id = #{id,jdbcType=INTEGER}
数据库的接口基本上已经完成了,
还有接口实现类Impl没写,接下来回到UserServiceImpl.java中,我们首先要引入Mapper接口类
使用@Autowired注解,它可以对类成员变量,方法,及构造函数进行标注,完成自动装配工作
@Autowired
UserMapper userMapper;
利用@Autowired引入Mapper层,然后用userMapper去调用UserMapper中的功能的接口
package com.blog.personblog.service.Impl;
import com.blog.personblog.entity.User;
import com.blog.personblog.mapper.UserMapper;
import com.blog.personblog.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Service注解用于类上,标记当前类是一个service类,加上该注解会将当前类自动注入到spring容器中
*
*/
@Service
public class UserServiceImpl implements UserService {
/**
* 业务实现层
*
*/
@Autowired
UserMapper userMapper;
@Override
public List findAll() {
/**
*userMapper.findAll();
* 调用UseMapper中的findALL方法
*/
List userList = userMapper.findAll();
return userList;
}
@Override
public void createUser(User user) {
/**
*userMapper.insert;
* 调用UseMapper中的insert方法
*/
userMapper.insert(user);
}
@Override
public void updateUser(User user) {
/**
*userMapper.update;
* 调用UseMapper中的insert方法
*/
userMapper.update(user);
}
@Override
public void deleteUser(int id) {
/**
*userMapper.delete;
* 调用UseMapper中的delete方法
*/
userMapper.delete(id);
}
}
到此,我们基本的业务逻辑功能都完成了,但是我们查出来的数据如何暴露在外面呢,前面说了,这是个前后端分离的项目,也就是我们后端的服务和前端后台管理页面分开部署,所以要通过接口来进行统一的调用,每一个接口代表一个功能的实现,
这些进行调用的接口写在Controller层中,
在编写Controller类之前,我们还需要做一件事,就是需要封装一个返回类,封装我们的返回类型,统一设置返回格式方便前端调用,在这里定义了一个返回类 ,以后所有的接口都会用这个返回类进行数据的返回和返回错误信息供前端参考
在我们建的util包中新建一个JsonResult.java类,
里面放我们设置好的统一的返回格式,返回的三个参数分别是:返回数据、错误码、错误信息
JsonResult.java完整代码
package com.blog.personblog.util;
import java.io.Serializable;
public class JsonResult implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功
*/
public static final int SUCCESS = 200;
/**
* 失败
*/
public static final int error = 500;
/**
* 返回数据
*/
private int code;
/**
* 错误码
*/
private String msg;
/**
* 错误信息
*/
private T data;
public static JsonResult success() {
return jsonResult(null, SUCCESS, "操作成功");
}
public static JsonResult success(T data) {
return jsonResult(data, SUCCESS, "操作成功");
}
public static JsonResult error() {
return jsonResult(null, error, "操作失败");
}
public static JsonResult error(String msg) {
return jsonResult(null, error, msg);
}
public static JsonResult error(T data) {
return jsonResult(data, error, "操作失败");
}
private static JsonResult jsonResult(T data, int code, String msg) {
JsonResult result = new JsonResult<>();
result.setCode(code);
result.setData(data);
result.setMsg(msg);
return result;
}
/**
* 通过 Alt + Insert 快捷键一键生成,Get/Set方法
*/
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
然后在controller包中新建一个UserController类,通过注解@Autowired引入我们的UserService类,实现业务接口调用
先说一下其中可能会出现的小问题:
引入@Vaild注解爆红
打开pom.xml添加依赖,添加完成点击刷新,添加成功后,再在爆红的位置,按快捷键Alt +Enter引入即可,
使用到了@PathVariable注解,具体的使用规则参考这位博主的文章:
(1条消息) @PathVariable注解的用法和作用(Demo详解)_辰兮要努力的博客-CSDN博客_pathvariable
UserController.java类完整代码
package com.blog.personblog.controller;
import com.blog.personblog.entity.User;
import com.blog.personblog.service.UserService;
import com.blog.personblog.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
/**
* 用户列表
* @return
*/
@PostMapping("/list")
public JsonResult
以上的代码都使用了很多注解,
org.springframework.boot
spring-boot-starter-validation
到这里,用户中心的基础功能已经基本实现,
记得提交代码到Gitee,
总结了一下大概流程
先构建实体类
在构建Service层(接口),让业务功能暴露出去,可以供接口层调用
构建ServiceImpl实现类,实现业务接口,重写实现类中的方法
创建Mapper层接口,数据库查询接口实现
在启动类中添加扫描包
编写数据库的xml文件,Mapper.xml
回到Impl实现类,在ServiceImpl中利用@Autowired注解引入mapper,进行调用mapper中的方法,及mapper中的功能的接口
注:Mapper接口类的方法名和ServiceImpl实现类中的方法名尽量不要一样,
封装一个返回类,用于封装我们的返回类型,统一设置返回格式方便前端调用
新建Controller类,引入Service层,实现业务接口调用