一、增加用户、角色实体
1、角色枚举
package com.jh.heroes.api.domain;
public enum AuthorityName {
ROLE_USER, ROLE_ADMIN
}
2、用户实体
package com.jh.heroes.api.domain;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
import lombok.Getter;
import lombok.Setter;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "sys_user")
public class SysUser {
@Id
@Column(name = "id",length=32)
@GenericGenerator(name="system-uuid",strategy="uuid")
@GeneratedValue(generator="system-uuid")
private String id;
@Column(name="username",unique=true, columnDefinition = "varchar(128) not null comment '用户名称'")
private String username;
@Column(name="password",columnDefinition = "varchar(128) not null comment '用户密码'")
private String password;
@Column(name = "email",columnDefinition = "varchar(50) not null comment '邮箱'")
private String email;
@Column(name = "enabled",columnDefinition = "bit default 1 not null comment '是否可用:0 不可用;1 可用'")
private Boolean enabled=true;
@Column(name = "lastPasswordResetDate",columnDefinition = "datetime not null comment '最近设置密码日期'")
@Temporal(TemporalType.TIMESTAMP)
private Date lastPasswordResetDate;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "sys_user_role", joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
private List<SysRole> authorities;
}
注:A、使用lombok,在类上声明@Date,从而减少pojo类干瘪的get、set、toString()代码,使代码简洁。
B、在类上声明@Entity,表示这个是一个实体类,存在@Table声明则用它声明的表名创建表;没有@Table声明则用类名创建表。
C、@Id声明,表示这个字段是主键,可以使用findById进行查询
D、@Column声明,表示这是一个字段,可以使用:name表示字段名称,length表示长度,unique=true表示聚合(多个字段组成的聚合,在类上声明),columnDefinition更详细的定义字段。
E、多对多的声明以及中间表的定义
F、主键的字段类型,我选择string,并且是uuid的。主要是比较讨厌用户去猜测下一个、上一个主键数据,用uuid他猜不了,我也猜不了。
3、角色实体
package com.jh.heroes.api.domain;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.hibernate.annotations.GenericGenerator;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "sys_role")
public class SysRole {
@Id
@Column(name = "id", length=32)
@GenericGenerator(name="system-uuid",strategy="uuid")
@GeneratedValue(generator="system-uuid")
private String id;
@Column(name="name",columnDefinition = "varchar(50) not null comment '角色名称'")
@Enumerated(EnumType.STRING)
private AuthorityName name;
@ManyToMany(mappedBy = "authorities", fetch = FetchType.LAZY)
private List<SysUser> users;
public SysRole(@NotNull AuthorityName name) {
super();
this.name = name;
}
}
二、增加用户、角色repository
1、增加角色的repository
package com.jh.heroes.api.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.jh.heroes.api.domain.SysRole;
@Repository
public interface SysRoleRepository extends JpaRepository<SysRole, String> {
}
注:这个repository就是一个空的接口类,继承JpaRepository
2、增加用户 的repository
package com.jh.heroes.api.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.jh.heroes.api.domain.SysUser;
@Repository
public interface SysUserRepository extends JpaRepository<SysUser, String>{
}
三、增加用户、角色的service
1、增加角色的service
package com.jh.heroes.api.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.jh.heroes.api.domain.AuthorityName;
import com.jh.heroes.api.domain.SysRole;
import com.jh.heroes.api.repository.SysRoleRepository;
@Service
public class SysRoleService {
@Autowired
private SysRoleRepository sysRoleRepository;
public Long count() {
return sysRoleRepository.count();
}
public List<SysRole> findAll() {
return sysRoleRepository.findAll();
}
public Optional<SysRole> findById(String id) {
return sysRoleRepository.findById(id);
}
public Optional<SysRole> findByName(AuthorityName name) {
SysRole role= new SysRole(name);
Example<SysRole> example=Example.of(role);
return sysRoleRepository.findOne(example);
}
@Transactional
public SysRole save(SysRole sysRole) {
return sysRoleRepository.save(sysRole);
}
@Transactional
public void delete(String id) {
sysRoleRepository.deleteById(id);
}
}
2、增加用户的service
package com.jh.heroes.api.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.jh.heroes.api.domain.SysUser;
import com.jh.heroes.api.repository.SysUserRepository;
@Service
public class SysUserService {
@Autowired
private SysUserRepository sysUserRepository;
public Long count() {
return sysUserRepository.count();
}
/**
* 查询所有用户
* @return
*/
public List<SysUser> findAll() {
return sysUserRepository.findAll();
}
/**
* 查询指定id的用户
* @param id
* @return
*/
public Optional<SysUser> findById(String id) {
return sysUserRepository.findById(id);
}
/**
* 查询指定用户名的用户
* @param username
* @return
*/
public Optional<SysUser> findByUsername(String username) {
SysUser user = new SysUser();
user.setUsername(username);
Example<SysUser> example = Example.of(user);
return sysUserRepository.findOne(example);
}
/**
* 保存
* @param user
* @return
*/
@Transactional
public SysUser save(SysUser user) {
return sysUserRepository.save(user);
}
/**
* 删除指定用户
* @param user
*/
@Transactional
public void delete(SysUser user) {
sysUserRepository.delete(user);
}
/**
* 删除指定id的用户
* @param id
*/
@Transactional
public void deleteById(String id) {
sysUserRepository.deleteById(id);
}
}
四、增加用户、角色的controller
1、增加角色的controller
/**
*
*/
package com.jh.heroes.api.web.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.jh.heroes.api.domain.AuthorityName;
import com.jh.heroes.api.domain.SysRole;
import com.jh.heroes.api.service.SysRoleService;
/**
* 角色操作.
* @author liangxh
*
*/
@RestController
@RequestMapping("/role")
public class RoleController {
@Autowired
private SysRoleService sysRoleService;
@GetMapping()
public List<SysRole> findAll() {
return sysRoleService.findAll();
}
@GetMapping("/{id}")
public Optional<SysRole> findById(@PathVariable String id) {
return sysRoleService.findById(id);
}
@GetMapping("/")
public Optional<SysRole> findByName(@RequestParam AuthorityName name) {
return sysRoleService.findByName(name);
}
@PutMapping()
public SysRole insert(@RequestBody SysRole sysRole) {
return sysRoleService.save(sysRole);
}
@PostMapping()
public SysRole save(@RequestBody SysRole sysRole) {
return sysRoleService.save(sysRole);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable String id) {
sysRoleService.delete(id);
}
}
2、增加用户的controller
/**
*
*/
package com.jh.heroes.api.web.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.jh.heroes.api.domain.SysUser;
import com.jh.heroes.api.service.SysUserService;
/**
* 用户操作.
* @author liangxh
*
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private SysUserService sysUserService;
@GetMapping()
public List<SysUser> findAll() {
return sysUserService.findAll();
}
/**
* 查询指定id的用户
* @param id
* @return
*/
@GetMapping("/{id}")
public Optional<SysUser> findById(@PathVariable String id) {
return sysUserService.findById(id);
}
/**
* 查询指定用户名的用户
* @param username
* @return
*/
@GetMapping("/")
public Optional<SysUser> findByUsername(@RequestParam String username) {
return sysUserService.findByUsername(username);
}
/**
* 增加
* @param user
* @return
*/
@PutMapping
public SysUser insert(@RequestBody SysUser user) {
return sysUserService.save(user);
}
/**
* 修改
* @param user
* @return
*/
@PostMapping
public SysUser update(@RequestBody SysUser user) {
return sysUserService.save(user);
}
/**
* 删除指定id的用户
* @param id
*/
@DeleteMapping("/{id}")
public void deleteById(@PathVariable String id) {
sysUserService.deleteById(id);
}
}
五、启动数据初始化
1、增加包init
com.jh.heroes.api.init
2、增加数据库初始化类InitDatabase
/**
*
*/
package com.jh.heroes.api.init;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.jh.heroes.api.domain.AuthorityName;
import com.jh.heroes.api.domain.SysRole;
import com.jh.heroes.api.domain.SysUser;
import com.jh.heroes.api.service.SysRoleService;
import com.jh.heroes.api.service.SysUserService;
/**
* 初始化数据库数据.
* @author liangxh
* 当数据库中用户表数据为空时,向数据库中添加数据
*/
@Component
public class InitDatabase implements CommandLineRunner{
@Autowired
private SysUserService sysUserService;
@Autowired
private SysRoleService sysRoleService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
@Transactional
public void run(String... args) throws Exception {
if (sysUserService.count() ==0) {
SysRole AdminRole= new SysRole(AuthorityName.ROLE_ADMIN);
AdminRole=sysRoleService.save(AdminRole);
SysRole userRole= new SysRole(AuthorityName.ROLE_USER);
userRole=sysRoleService.save(userRole);
SysUser adminUser=new SysUser();
adminUser.setUsername("admin");
adminUser.setPassword(passwordEncoder.encode("123456"));
adminUser.setEmail("admin@qq.com");
adminUser.setEnabled(true);
adminUser.setLastPasswordResetDate(new Date());
List<SysRole> adminRoles= new ArrayList<>();
adminRoles.add(AdminRole);
adminUser.setAuthorities(adminRoles);
sysUserService.save(adminUser);
SysUser user=new SysUser();
user.setUsername("jim");
user.setPassword(passwordEncoder.encode("123456"));
user.setEmail("admin@qq.com");
user.setEnabled(true);
user.setLastPasswordResetDate(new Date());
List<SysRole> roles= new ArrayList<>();
roles.add(userRole);
user.setAuthorities(roles);
sysUserService.save(user);
}
}
}
每次启动之后,都会自动运行这个类的run方法。在方法中,我们通过判断会员记录数量是否为零来判断是否空数据库,是空数据库,则添加数据。
六、测试
1、系统启动之后,在数据库生成sys_user、sys_role、sys_user_role这三张表,并且存在我们生成的数据。
2、在postman中测试,http:localhost:8001/user,http://localhost:8001/role,都报“Expected ',' instead of ”,同时heroapi的日志也报错,查看postman的body,可以发现循环引用,那么我们就在SysRole中忽略对SysUser的json解析,增加声明如下
@JsonIgnore
@ManyToMany(mappedBy = "authorities", fetch = FetchType.LAZY)
private List<SysUser> users;
3、在http://localhost:8001/user中,我们可以查看到password字段。如果不需要查看这个字段呢,我们可以使用@JsonView。@JsonView
可以过滤序列化对象的字段属性,可以使我们有选择的序列化对象。使用@JsonView,需要三个方面的修改:
A、定义接口类,用于区别各个类的包含的字段:定义的接口,彼此有一定的继承关系最好;这些接口,不需要定义在单独的文件中,只需要在实体中定义即可;
B、在各个字段上通过@JsonView声明给不同的接口;
C、在controller的特定方法上通过@JsonView声明不同的接口,从而实现JSON中字段过滤。
4、在http://localhost:8001/user中,通过put,可以增加用户,但是密码是明码,不能满足我们需要,在SysUserService中增加一个方法add,处理用户增加逻辑。
5、在角色中取消对用户的关联,并把用户中的角色映射关系从多对多改成一对多。
七、小结
本节就是普通的数据库增删改查,以及通过@JsonView来过滤明感数据以及循环引用。
1、在数据库操作上,通过继承JpaRepository,最少代码实现的增删改查;
2、通过对CommandLineRunner的实现,进行数据库初始化;
3、在实体及controller方法上通过@JsonView过滤数据