- 一.电商管理后台 API 接口
- 1.1API V1 接口说明
- 1.2 支持的请求方法
- 1.3 通用返回状态说明
- 二.登录
- 2.1登录验证接口
- 后端实现
- 三.用户管理
- 3.1用户数据列表
- 后端实现
- 3.2. 添加用户
- 后端实现
- 3.3. 修改用户状态
- 后端实现
- 3.4. 根据 ID 查询用户信息
- 后端实现
- 3.5. 编辑用户提交
- 后端实现
- 3.6. 删除单个用户
- 后端实现
- 3.7. 分配用户角色
- 后端实现
- 接口基准地址:http://127.0.0.1:8888/api/private/v1/
- 服务端已开启 CORS 跨域支持
- API V1 认证统一使用 Token 认证
- 需要授权的 API ,必须在请求头中使用 Authorization 字段提供 token 令牌
- 使用 HTTP Status Code 标识状态
- 数据返回格式统一使用 JSON
- GET(SELECt):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源。
- HEAD:获取资源的元数据。
- OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
| 状态码 | 含义 | 说明 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | CREATED | 创建成功 |
| 204 | DELETED | 删除成功 |
| 400 | BAD REQUEST | 请求的地址不存在或者包含不支持的参数 |
| 401 | UNAUTHORIZED | 未授权 |
| 403 | FORBIDDEN | 被禁止访问 |
| 404 | NOT FOUND | 请求的资源不存在 |
| 422 | Unprocesable entity | [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误 |
| 500 | INTERNAL SERVER ERROR | 内部错误 |
二.登录 2.1登录验证接口
- 请求路径:login
- 请求方法:post
- 请求参数
| 参数名 | 参数说明 | 备注 |
|---|---|---|
| username | 用户名 | 不能为空 |
| password | 密码 | 不能为空 |
- 响应参数
| 参数名 | 参数说明 | 备注 |
|---|---|---|
| id | 用户 ID | |
| rid | 用户角色 ID | |
| username | 用户名 | |
| mobile | 手机号 | |
| 邮箱 | ||
| token | 令牌 | 基于 jwt 的令牌 |
- 响应数据
{
"data": {
"id": 500,
"rid": 0,
"username": "admin",
"mobile": "123",
"email": "123@qq.com",
"token": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjUwMCwicmlkIjowLCJpYXQiOjE1MTI1NDQyOTksImV4cCI6MTUxMjYzMDY5OX0.eGrsrvwHm-tPsO9r_pxHIQ5i5L1kX9RX444uwnRGaIM"
},
"meta": {
"msg": "登录成功",
"status": 200
}
}
后端实现
数据返回实体类封装
meta.java
package com.vueshop.manager.controller.http.response.base;
import lombok.Data;
@Data
public class meta {
private String msg;
private Integer status;
}
HttpResponse.java
package com.vueshop.manager.controller.http.response.base; import lombok.Data; @Data public class HttpResponse{ private T data; private meta meta; public HttpResponse() { } public HttpResponse(meta meta) { this.meta = meta; } }
用户请求实体类和用户响应实体类
UserInfoResponse.java
package com.vueshop.manager.controller.http.response;
import lombok.Data;
@Data
public class UserInfoResponse {
private Long id;
private Long rid;
private String username;
private String mobile;
private String email;
private String token;
private String password;
private String createtime;
private String updatetime;
}
UserInfoRequest.java
package com.vueshop.manager.controller.http.request;
import lombok.Data;
@Data
public class UserInfoRequest {
private Long id;
private String username;
private String password;
private Integer status;
private String email;
private String mobile;
private Integer rid;
}
LoginController.java
@RestController
@RequestMapping("api/private/v1/")
@Slf4j
public class LoginController {
@Autowired
private LoginService loginService;
@PostMapping("login")
public HttpResponse login(HttpServletRequest request,
@RequestBody UserInfoRequest userInfoRequest){
HttpResponse httpResponse=new HttpResponse<>(new meta());
try {
UserInfoResponse userInfoResponse = loginService.queryUserInfo(userInfoRequest);
if (userInfoResponse == null || !userInfoResponse.getPassword().equals(userInfoRequest.getPassword())) {
httpResponse.getmeta().setMsg("登录失败");
httpResponse.getmeta().setStatus(400);
return httpResponse;
}
httpResponse.setData(userInfoResponse);
httpResponse.getmeta().setMsg("登录成功");
httpResponse.getmeta().setStatus(200);
} catch (Exception e) {
log.error(e.getMessage());
httpResponse.getmeta().setMsg("登录失败");
httpResponse.getmeta().setStatus(400);
}
return httpResponse;
}
LoginServiceImpl.java
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
@Autowired
private UserInfoDao userInfoDao;
@Autowired
private Map redisCache;
@Autowired
private MenuInfoDao menuInfoDao;
@Override
public UserInfoResponse queryUserInfo(UserInfoRequest userInfoRequest) {
UserInfo userInfo = userInfoDao.queryUserInfo(userInfoRequest.getUsername());
if(userInfo==null){
return null;
}
List menuInfos = menuInfoDao.queryMenuInfoByRoleId(userInfo.getRid());
UserInfoResponse userInfoResponse=new UserInfoResponse();
BeanUtils.copyProperties(userInfo,userInfoResponse);
String token= UUID.randomUUID().toString().replace("-","");
userInfoResponse.setToken(token);
AuthInfoDto authInfoDto=new AuthInfoDto();
authInfoDto.setUserInfo(userInfo);
authInfoDto.setMenuInfos(menuInfos);
redisCache.put(token,authInfoDto);
return userInfoResponse;
}
}
UserInfoDaoMapper.xml
id, rid, username, mobile, email, token, password, status, createtime, updatetime
MenuInfoDaoMapper.xml
id, auth_name, path, pid, status, display, level, createtime, updatetime
拦截器
AuthInterceptor.java
@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
protected Map redisCache;
private static final List menuWhiteList = Arrays.asList("home", "menus", "login");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
AuthInfoDto authInfoDto = loginAuthorizationCheck(request);
if (authInfoDto.isNotAuth()) {
HttpResponse httpResponse = new HttpResponse();
meta meta = new meta();
meta.setMsg(authInfoDto.getErrMsg());
meta.setStatus(400);
httpResponse.setmeta(meta);
response.setHeader("Content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(JSON.toJSONString(httpResponse));
return false;
}
return true;
}
public AuthInfoDto loginAuthorizationCheck(HttpServletRequest request) {
AuthInfoDto authInfoDto = redisCache.get(request.getHeader("Authorization"));
if (authInfoDto == null) {
authInfoDto = new AuthInfoDto();
authInfoDto.setErrMsg("未登录");
authInfoDto.setNotAuth(true);
return authInfoDto;
}
boolean isAccept = false;
String requestURI = request.getRequestURI();
for (MenuInfo menuInfo : authInfoDto.getMenuInfos()) {
if (menuInfo.getPath() == null) {
continue;
}
if (requestURI.contains(menuInfo.getPath())) {
isAccept = true;
break;
}
}
for (String uri : menuWhiteList) {
if (requestURI.contains(uri)) {
isAccept = true;
break;
}
}
if (!isAccept) {
authInfoDto.setErrMsg("没有权限访问该路径");
authInfoDto.setNotAuth(true);
}
return authInfoDto;
}
}
InterceptorConfig.java
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/private/v1
{
"data": {
"id": 503,
"username": "admin3",
"role_id": 0,
"mobile": "111",
"email": "123@123.com"
},
"meta": {
"msg": "更新成功",
"status": 200
}
}
后端实现
UsersController.java
@PutMapping("users/{id}")
@ResponseBody
public HttpResponse updateUserInfoById(HttpServletRequest request, @PathVariable long id,
@RequestBody UserInfoRequest userInfoRequest) {
HttpResponse httpResponse = new HttpResponse<>(new meta());
userInfoRequest.setId(id);
if (userInfoRequest.getStatus() == null) {
userInfoRequest.setStatus(0);
}
UserInfoResponse userInfoResponse = usersService.updateUserInfoById(userInfoRequest);
if (userInfoResponse == null) {
httpResponse.getmeta().setMsg("更新失败");
httpResponse.getmeta().setStatus(400);
return httpResponse;
}
httpResponse.setData(userInfoResponse);
httpResponse.getmeta().setMsg("更新成功");
httpResponse.getmeta().setStatus(200);
return httpResponse;
}
UsersServiceImpl.java
@Override
public UserInfoResponse updateUserInfoById(UserInfoRequest userInfoRequest) {
UserInfoResponse userInfoResponse = new UserInfoResponse();
try {
userInfoDao.updateUserInfo(userInfoRequest);
} catch (Exception e) {
log.error("更新失败", e.getMessage());
return null;
}
BeanUtils.copyProperties(userInfoRequest, userInfoResponse);
return userInfoResponse;
}
UserInfoDaoMapper.xml
3.6. 删除单个用户UPDATE user_info WHERe id =#{userInfo.id} rid =#{userInfo.rid}, mobile =#{userInfo.mobile}, email =#{userInfo.email}, password =#{userInfo.password}, status =#{userInfo.status}, updatetime = now()
- 请求路径:users/:id
- 请求方法:delete
- 请求参数
| 参数名 | 参数说明 | 备注 |
|---|---|---|
| id | 用户 id | 不能为空参数是url参数:id |
- 响应参数
- 响应数据
{
"data": null,
"meta": {
"msg": "删除成功",
"status": 200
}
}
后端实现
UsersController.java
@DeleteMapping("users/{id}")
@ResponseBody
public HttpResponse deleteUserById(HttpServletRequest request, @PathVariable long id) {
HttpResponse httpResponse = new HttpResponse<>(new meta());
UserInfoResponse userInfoResponse = usersService.deleteUserById(id);
if (userInfoResponse == null) {
httpResponse.getmeta().setMsg("删除失败");
httpResponse.getmeta().setStatus(400);
return httpResponse;
}
httpResponse.setData(userInfoResponse);
httpResponse.getmeta().setMsg("删除成功");
httpResponse.getmeta().setStatus(200);
return httpResponse;
}
UsersServiceImpl.java
@Override
public UserInfoResponse deleteUserById(Long id) {
UserInfoResponse userInfoResponse = new UserInfoResponse();
try {
userInfoDao.deleteUserById(id);
} catch (Exception e) {
log.error("删除失败", e.getMessage());
return null;
}
return userInfoResponse;
}
UserInfoDaoMapper.xml
3.7. 分配用户角色DELETE FROM user_info WHERe id = #{id}
- 请求路径:users/:id/role
- 请求方法:put
- 请求参数
| 参数名 | 参数说明 | 备注 |
|---|---|---|
| id | 用户 ID | 不能为空参数是url参数:id |
| rid | 角色 id | 不能为空参数body参数 |
- 响应参数
| 参数名 | 参数说明 | 备注 |
|---|---|---|
| id | 用户 ID | |
| role_id | 角色 ID | |
| mobile | 手机号 | |
| 邮箱 |
- 响应数据
{
"data": {
"id": 508,
"rid": "30",
"username": "asdf1",
"mobile": "123123",
"email": "adfsa@qq.com"
},
"meta": {
"msg": "设置角色成功",
"status": 200
}
}
后端实现
UsersController.java
@PutMapping("users/{id}/role")
@ResponseBody
public HttpResponse updateUserStateById(HttpServletRequest request, @PathVariable long id, @RequestBody AssignRoleRequest assignRoleRequest) {
HttpResponse httpResponse = new HttpResponse<>(new meta());
String rid = assignRoleRequest.getRid();
UserInfoRequest userInfoRequest = new UserInfoRequest();
userInfoRequest.setId(id);
userInfoRequest.setRid(Integer.parseInt(rid));
UserInfoResponse userInfoResponse = usersService.updateUserInfoById(userInfoRequest);
if (userInfoResponse == null) {
httpResponse.getmeta().setMsg("设置角色成功");
httpResponse.getmeta().setStatus(400);
return httpResponse;
}
httpResponse.setData(userInfoResponse);
httpResponse.getmeta().setMsg("设置角色失败");
httpResponse.getmeta().setStatus(200);
return httpResponse;
}
UsersServiceImpl.java
@Override
public UserInfoResponse updateUserInfoById(UserInfoRequest userInfoRequest) {
UserInfoResponse userInfoResponse = new UserInfoResponse();
try {
userInfoDao.updateUserInfo(userInfoRequest);
} catch (Exception e) {
log.error("更新失败", e.getMessage());
return null;
}
BeanUtils.copyProperties(userInfoRequest, userInfoResponse);
return userInfoResponse;
}
UserInfoDaoMapper.xml
UPDATE user_info WHERe id =#{userInfo.id} rid =#{userInfo.rid}, mobile =#{userInfo.mobile}, email =#{userInfo.email}, password =#{userInfo.password}, status =#{userInfo.status}, updatetime = now()



