一. 内容简介
实现java后端用户管理接口,数据库使用msyql。
二. 软件环境
2.1 java 1.8
2.2 mysql Ver 8.0.13 for Win64 on x86_64 (MySQL Community Server - GPL)
2.3 IDEA ULTIMATE 2019.3
2.4 Visual Studio Code 1.75.0
2.5 SQLyog v12.09(64 bit)
2.6 PDMan-win64_v2.1.6
下载链接 https://pan.baidu.com/s/1OpfQcgpijzYwHg2H-PxKPQ?pwd=1234
三.主要流程
3.1 创建数据库,创建数据表,添加数据
3.2 开始编写接口,并测试
四.具体步骤
4.1 创建数据库,创建数据表,添加数据
用pdman创建用户表结构,
然后pdman可以生成对应语言的代码
对应的mysql代码为
CREATE TABLE users(
user_id VARCHAR(64) NOT NULL COMMENT '主键id 用户id' ,
username VARCHAR(32) NOT NULL COMMENT '用户名 用户名' ,
password VARCHAR(64) NOT NULL COMMENT '密码 密码' ,
nickname VARCHAR(32) COMMENT '昵称 昵称' ,
realname VARCHAR(128) COMMENT '真实姓名 真实姓名' ,
user_img VARCHAR(1024) NOT NULL COMMENT '头像 头像' ,
user_mobile VARCHAR(32) COMMENT '手机号 手机号' ,
user_email VARCHAR(32) COMMENT '邮箱地址 邮箱地址' ,
user_sex CHAR(1) COMMENT '性别 M(男) or F(女)' ,
user_birth DATE COMMENT '生日 生日' ,
user_regtime DATETIME NOT NULL COMMENT '注册时间 创建时间' ,
user_modtime DATETIME NOT NULL COMMENT '更新时间 更新时间' ,
PRIMARY KEY (user_id)
) COMMENT = '用户 ';
# comment为注释
放入SQLyog 运行后
然后添加数据
INSERT INTO `users` VALUES (1, 'zhangsan', 'f379eaf3c831b04de153469d1bec345e', NULL, NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-15 16:10:53', '2021-04-15 16:10:53');
INSERT INTO `users` VALUES (2, 'aaaa', '1111', NULL, NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-16 11:10:01', '2021-04-16 11:10:01');
INSERT INTO `users` VALUES (3, 'wahaha', '4297f44b13955235245b2497399d7a93', NULL, NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-16 15:36:52', '2021-04-16 15:36:52');
INSERT INTO `users` VALUES (4, 'heihei', '4297f44b13955235245b2497399d7a93', '二狗', NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-16 15:38:49', '2021-04-16 15:38:49');
INSERT INTO `users` VALUES (5, 'Tony', '4297f44b13955235245b2497399d7a93', '托尼', NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-23 10:25:04', '2021-04-23 10:25:04');
INSERT INTO `users` VALUES (6, 'hanmeimei', 'f379eaf3c831b04de153469d1bec345e', NULL, NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-23 10:30:52', '2021-04-23 10:30:52');
INSERT INTO `users` VALUES (7, 'lilei123', '4297f44b13955235245b2497399d7a93', NULL, NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-23 10:33:03', '2021-04-23 10:33:03');
INSERT INTO `users` VALUES (8, 'tom123123', '4297f44b13955235245b2497399d7a93', NULL, NULL, 'img/default.png', NULL, NULL, NULL, NULL, '2021-04-23 10:34:49', '2021-04-23 10:34:49');
4.2 开始编写接口,并测试
4.2.1 更改mybatis配置信息
第一步先更改mapper中的application.yml,链接上自己数据库
spring:
datasource:
druid:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/server_java?characterEncoding=utf-8
username: root
password: 1234
mybatis:
mapper-locations: classpath:mappers/*Mapper.xml
type-aliases-package: com.qfedu.fmmall.entity
logging:
level:
io.swagger.models.parameters.AbstractSerializableParameter: error
4.2.2 实现DAO操作
有了数据表以后,DAO操作就根据数据表自动生成,这里使用的是tkMapper插件,第一就是添加依赖
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>3.4.4</version>
</dependency>
然后在resources文件下,创建tpMapper的配置文件,修改为自己的就可以了。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 引入数据库连接配置 -->
<!-- <properties resource="jdbc.properties"/>-->
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 配置 GeneralDAO -->
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.qfedu.fmmall.general.GeneralDAO"/>
</plugin>
<!-- 配置数据库连接 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/server_java"
userId="root" password="admin123">
</jdbcConnection>
<!-- 配置实体类存放路径 -->
<javaModelGenerator targetPackage="com.qfedu.fmmall.entity" targetProject="src/main/java"/>
<!-- 配置 XML 存放路径 -->
<sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>
<!-- 配置 DAO 存放路径 -->
<javaClientGenerator targetPackage="com.qfedu.fmmall.dao" targetProject="src/main/java" type="XMLMAPPER"/>
<!-- 配置需要指定生成的数据库和表,% 代表所有表 -->
<table tableName="shopping_cart"></table>
</context>
</generatorConfiguration>
最后将配置文件添加到逆向工程的插件中
<configuration><configurationFile>${basedir}/src/main/resources/genetator/generatorConfig.xml</configurationFile>
</configuration>
最后在插件中运行即可,就可以自动生成实体类,以及dao。
4.2.2 实现service业务
package com.qfedu.fmmall.service.impl;
import com.qfedu.fmmall.dao.UsersMapper;
import com.qfedu.fmmall.entity.Users;
import com.qfedu.fmmall.service.UserService;
import com.qfedu.fmmall.utils.Base64Utils;
import com.qfedu.fmmall.utils.MD5Utils;
import com.qfedu.fmmall.vo.ResStatus;
import com.qfedu.fmmall.vo.ResultVO;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UsersMapper usersMapper;
@Transactional
public ResultVO userResgit(String name, String pwd) {
synchronized (this) {
//1.根据用户查询,这个用户是否已经被注册
Example example = new Example(Users.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("username", name);
List<Users> users = usersMapper.selectByExample(example);
//2.如果没有被注册则进行保存操作
if (users.size() == 0) {
String md5Pwd = MD5Utils.md5(pwd);
Users user = new Users();
user.setUsername(name);
user.setPassword(md5Pwd);
user.setUserImg("img/default.png");
user.setUserRegtime(new Date());
user.setUserModtime(new Date());
int i = usersMapper.insertUseGeneratedKeys(user);
if (i > 0) {
return new ResultVO(ResStatus.OK, "注册成功!", user);
} else {
return new ResultVO(ResStatus.NO, "注册失败!", null);
}
} else {
return new ResultVO(ResStatus.NO, "用户名已经被注册!", null);
}
}
}
@Override
public ResultVO checkLogin(String name, String pwd) {
Example example = new Example(Users.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("username", name);
List<Users> users = usersMapper.selectByExample(example);
if(users.size() == 0){
return new ResultVO(ResStatus.NO,"登录失败,用户名不存在!",null);
}else{
String md5Pwd = MD5Utils.md5(pwd);
if(md5Pwd.equals(users.get(0).getPassword())){
return new ResultVO(ResStatus.OK,"登录成功,密码正确!",users.get(0));
}else{
return new ResultVO(ResStatus.NO,"登录失败,密码错误!",null);
}
}
}
}
由于才用前后端分离开发,用户认证将使用jwt-token实现用户认证,同时也将使用jwt拦截器功能对访问先进行登录验证。
public ResultVO checkLogin(String name, String pwd) {
Example example = new Example(Users.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("username", name);
List<Users> users = usersMapper.selectByExample(example);
if(users.size() == 0){
return new ResultVO(ResStatus.NO,"登录失败,用户名不存在!",null);
}else{
String md5Pwd = MD5Utils.md5(pwd);
if(md5Pwd.equals(users.get(0).getPassword())){
//如果登录验证成功,则需要生成令牌token(token就是按照特定规则生成的字符串)
//使用jwt规则生成token字符串
JwtBuilder builder = Jwts.builder();
HashMap<String,Object> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
String token = builder.setSubject(name) //主题,就是token中携带的数据
.setIssuedAt(new Date()) //设置token的生成时间
.setId(users.get(0).getUserId() + "") //设置用户id为token id
.setClaims(map) //map中可以存放用户的角色权限信息
.setExpiration(new Date(System.currentTimeMillis() + 24*60*60*1000)) //设置token过期时间
.signWith(SignatureAlgorithm.HS256, "QIANfeng6666") //设置加密方式和加密密码
.compact();
return new ResultVO(ResStatus.OK,token,users.get(0));
}else{
return new ResultVO(ResStatus.NO,"登录失败,密码错误!",null);
}
}
}
4.2.3 完成api接口
在api文件中创建UserController文件,完成接口创建,前边的注释主要让swagger生成接口文档
package com.qfedu.fmmall.controller;
import com.qfedu.fmmall.entity.Users;
import com.qfedu.fmmall.service.UserService;
import com.qfedu.fmmall.utils.Base64Utils;
import com.qfedu.fmmall.vo.ResStatus;
import com.qfedu.fmmall.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@RequestMapping("/user")
@Api(value = "提供用户的登录和注册接口",tags = "用户管理")
@CrossOrigin
public class UserController {
@Resource
private UserService userService;
private Logger logger = LoggerFactory.getLogger(UserController.class);
@ApiOperation("用户登录接口")
@ApiImplicitParams({
@ApiImplicitParam(dataType = "string",name = "username", value = "用户登录账号",required = true),
@ApiImplicitParam(dataType = "string",name = "password", value = "用户登录密码",required = true)
})
@GetMapping("/login")
public ResultVO login(@RequestParam("username") String name,
@RequestParam(value = "password") String pwd){
ResultVO resultVO = userService.checkLogin(name, pwd);
logger.info(resultVO.getMsg());
return resultVO;
}
@ApiOperation("用户注册接口")
@ApiImplicitParams({
@ApiImplicitParam(dataType = "string",name = "username", value = "用户注册账号",required = true),
@ApiImplicitParam(dataType = "string",name = "password", value = "用户注册密码",required = true)
})
@PostMapping("/regist")
public ResultVO regist(@RequestBody Users user){
ResultVO resultVO = userService.userResgit(user.getUsername(), user.getPassword());
return resultVO;
}
@ApiOperation("校验token是否过期接口")
@GetMapping("/check")
public ResultVO userTokencheck(@RequestHeader("token") String token){
return new ResultVO(ResStatus.OK,"success",null);
}
}
同时在api文件下创建jwt拦截器,对有需要的访问进行登录认证,
package com.qfedu.fmmall.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qfedu.fmmall.vo.ResStatus;
import com.qfedu.fmmall.vo.ResultVO;
import io.jsonwebtoken.*;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Component
public class CheckTokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String method = request.getMethod();
if("OPTIONS".equalsIgnoreCase(method)){
return true;
}
String token = request.getHeader("token");
if(token == null){
ResultVO resultVO = new ResultVO(ResStatus.LOGIN_FAIL_NOT, "请先登录!", null);
doResponse(response,resultVO);
}else{
try {
JwtParser parser = Jwts.parser();
parser.setSigningKey("QIANfeng6666"); //解析token的SigningKey必须和生成token时设置密码一致
//如果token正确(密码正确,有效期内)则正常执行,否则抛出异常
Jws<Claims> claimsJws = parser.parseClaimsJws(token);
return true;
}catch (ExpiredJwtException e){
ResultVO resultVO = new ResultVO(ResStatus.LOGIN_FAIL_OVERDUE, "登录过期,请重新登录!", null);
doResponse(response,resultVO);
}catch (UnsupportedJwtException e){
ResultVO resultVO = new ResultVO(ResStatus.LOGIN_FAIL_NOT, "Token不合法,请自重!", null);
doResponse(response,resultVO);
}catch (Exception e){
ResultVO resultVO = new ResultVO(ResStatus.LOGIN_FAIL_NOT, "请先登录!", null);
doResponse(response,resultVO);
}
}
return false;
}
private void doResponse(HttpServletResponse response,ResultVO resultVO) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
String s = new ObjectMapper().writeValueAsString(resultVO);
out.print(s);
out.flush();
out.close();
}
}
设置需要拦截的访问
package com.qfedu.fmmall.config;
import com.qfedu.fmmall.interceptor.CheckTokenInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private CheckTokenInterceptor checkTokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(checkTokenInterceptor)
.addPathPatterns("/shopcart/**")
.addPathPatterns("/orders/**")
.addPathPatterns("/useraddr/**")
.addPathPatterns("/user/check");
}
}