springboot+mybatis+mysql (用户登录实例)

需求

   登录

  1. 数据库中存在用户名、密码
  2. 前端发送登录请求,返回登录结果(成功则返回用户信息)

数据结构

   用户表

CREATE TABLE `user` (
  `id` varchar(32) NOT NULL COMMENT '用户编号(登录账号)',
  `password` varchar(32) NOT NULL COMMENT '密码',
  `name` varchar(128) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';

在这里插入图片描述

报文结构

请求报文

{
    "version": "1.0",
    "data": {
        "id": "lhc",
        "pwd": "123456"
    }
}

响应报文

成功报文:
{
    "code": 0,
    "desc": "成功",
    "data": {
        "id": "lhc",
        "pwd": "",
        "name": "令狐冲"
    }
}
用户名或密码不存在:
{
    "code": 1,
    "desc": "用户名密码不可为空",
    "data": null
}
用户名密码错误:
{
    "code": 2,
    "desc": "用户名或密码错误",
    "data": null
}

创建项目

在这里插入图片描述
在这里插入图片描述

   pom.xml

  1. 添加druid(数据库连接池)依赖
  2. 添加阿里fastjson依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ssy</groupId>
    <artifactId>restful-user</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>restful-user</name>
    <description>Demo restful-user api</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.9</version>
        </dependency>

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.32</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

配置文件

   application.yml

server:
  port: 9999

spring:
  profiles:
    active: pro
  servlet:
    multipart:
      max-file-size: 30MB
      max-request-size: 30MB
  devtools:
    restart:
      enabled: true

mybatis:
  mapper-locations: classpath:mapper/*.xml  #注意:一定要对应mapper映射xml文件的所在路径
  type-aliases-package: com.catail.restfuluser.bean  # 注意:对应实体类的路径

   application-pro.yml

logging:
  level:
    root: error
    com.ssy: info
    com.catail.restfuluser.dao: debug
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      filters: stat #监控统计拦截的filters
      driver-class-name: com.mysql.cj.jdbc.Driver
      #基本属性
      url: jdbc:mysql://xxx.xx.xx.xx:3306/restfil-user?useAffectedRows=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=UTC
      username: root
      password: xxxxxx
      initial-size: 1 #初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
      min-idle: 5 #最小连接池数量
      max-active: 50 #最大连接池数量
      max-wait: 60000 #获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降
      time-between-eviction-runs-millis: 60000 #间隔多久进行一次检测,检测需要关闭的空闲连接
      min-evictable-idle-time-millis: 30000 #配置一个连接在池中最小生存的时间,单位是毫秒
      validation-query: SELECT 'x' #用来检测连接是否有效的sql,要求是一个查询语句。
      test-while-idle: true #建议配置为true,不影响性能,并且保证安全性。
      test-on-borrow: false #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
      test-on-return: false #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      #打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
      pool-prepared-statements: false #是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
      max-pool-prepared-statement-per-connection-size: 20

RestfulUserApplication类中添加到层的扫描路径

在这里插入图片描述

添加实体类

   用户实体(User)

注意:添加包路径要与配置文件中一致
在这里插入图片描述

package com.ssy.restfuluser.bean;

public class User {

    private String id;
    private String pwd;//此处成员变量名称与数据库表中不同,方便查看mybatis resultmap的作用
    private String name;

    //getter and setter.....
}

   请求包实体类(ReqPack)

package com.ssy.restfuluser.bean;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ReqPack {

    private static final Logger logger = LoggerFactory.getLogger(ReqPack.class);

    private String version;
    private JSONObject data;

    // getter and setter....
}

   响应包实体类(RespPack)

package com.ssy.restfuluser.bean;


public class RespPack<T> {

    private int code;
    private String desc;
    private T data;

	// getter and setter .......
    
    //*******************************************************************
    public static RespPack respPackSuc(Object data) {

        RespPack respPack = new RespPack();
        respPack.setCode(0);
        respPack.setDesc("成功");
        respPack.setData(data);

        return respPack;
    }

    public static RespPack respPackSuc() {

        return respPackSuc(null);
    }

    public static RespPack respPackFail(int code, String desc, Object data) {

        RespPack respPack = new RespPack();
        respPack.setCode(code);
        respPack.setDesc(desc);
        respPack.setData(data);

        return respPack;
    }

    public static RespPack respPackFail(int code, String desc) {

        return respPackFail(code, desc, null);
    }
}

添加统一异常类UnifiedException

package com.ssy.restfuluser.exception;

public class UnifiedException extends RuntimeException {
    private int code;
    private String msgDetail;
    private Object data;

    public UnifiedException(int code, String message) {
        super(message);
        this.code = code;
    }

    public UnifiedException(int code, String message, Object obj) {
        super(message);
        this.code = code;
        this.data = obj;
    }

   // getter and setter....

    public static UnifiedException create(int code, String msg, String lineInfo) {
        UnifiedException unifiedException = new UnifiedException(code, msg);
        unifiedException.setMsgDetail(lineInfo + msg);
        return unifiedException;
    }

	public static UnifiedException create(int code, String msg, String lineInfo, Object obj) {
        UnifiedException unifiedException = new UnifiedException(code, msg, obj);
        unifiedException.setMsgDetail(lineInfo + msg);
        return unifiedException;
    }
}

添加统一异常处理类UnifiedExceptionHandle

package com.ssy.restfuluser.exception;

import com.ssy.restfuluser.bean.RespPack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class UnifiedExceptionHandle {

    private static final Logger logger = LoggerFactory.getLogger(UnifiedExceptionHandle.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public RespPack hanle(Exception e) {

        if (e instanceof UnifiedException) {
            UnifiedException exception = (UnifiedException) e;
            logger.error(((UnifiedException) e).getMsgDetail());
            return RespPack.respPackFail(exception.getCode(), exception.getMessage(), exception.getData());
        }

        logger.error("系统异常:" + e);
        return RespPack.respPackFail(99, e + "");
    }

}

添加获取当前行号方法(getCurLineInfo)

package utils;

public class SysUtil {

    public static String getCurLineInfo() {

        int originStackIndex = 2;
        
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        StackTraceElement element = stackTrace[originStackIndex];

        String retStr = "【文件】" + element.getFileName() + "【类】" + element.getClassName() +
                "【方法】" + element.getMethodName() + "【行号】" + element.getLineNumber() + "\n";

        return retStr;
    }
}

添加Dao层

注意:添加包路径要与RestfulUserApplication类中dao的扫描路径一致
在这里插入图片描述

package com.ssy.restfuluser.dao;

import com.ssy.restfuluser.bean.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface UserDao {

    User getUserbyToken(@Param("id") String id, @Param("pwd") String pwd);

}

添加mapper文件

注意:mapper文件的路径要与配置文件中相对应
在这里插入图片描述
在这里插入图片描述
UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.ssy.restfuluser.dao.UserDao">

    <resultMap id="user" type="com.ssy.restfuluser.bean.User">
        <result property="id" column="id"/>
        <result property="pwd" column="password"/>
        <result property="name" column="name"/>
    </resultMap>


    <select id="getUserbyToken" resultMap="user">
        select * from user
        <where>
            <if test="id != null and id.length() > 0">user.id= #{id}</if>
            <if test="pwd != null and pwd.length() > 0">and user.password=#{pwd}</if>
        </where>
    </select>
</mapper>

添加service层

此处service接口和实现不做分离了
UserService

package com.ssy.restfuluser.service;


import com.ssy.restfuluser.bean.User;
import com.ssy.restfuluser.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    UserDao userDao;

    User getUserbyToken(String id, String pwd) {

        if (id == null || id.length() <= 0 || pwd == null || pwd.length() <= 0)
            return null;

        return userDao.getUserbyToken(id, pwd);
    }

}

添加controller层

UserController

package com.ssy.restfuluser.controller;

import com.ssy.restfuluser.bean.ReqPack;
import com.ssy.restfuluser.bean.RespPack;
import com.ssy.restfuluser.bean.User;
import com.ssy.restfuluser.exception.UnifiedException;
import com.ssy.restfuluser.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import utils.SysUtil;

@RestController
@RequestMapping(value = "/user")
public class UserController {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    UserService userService;

    @PostMapping("/login")
    Object login(@RequestBody ReqPack reqPack) {

        String id;
        String pwd;

        try {
            id = reqPack.getData().getString("id");
            pwd = reqPack.getData().getString("pwd");
        } catch (Exception e) {
            throw UnifiedException.create(1, "参数异常", SysUtil.getCurLineInfo());
        }

        if (id == null || id.length() <= 0 || pwd == null || pwd.length() <= 0) {
            throw UnifiedException.create(1, "用户名密码不可为空", SysUtil.getCurLineInfo());
        }

        //业务
        User user = userService.getUserbyToken(id, pwd);
        if (user == null) {
            throw UnifiedException.create(2, "用户名或密码错误", SysUtil.getCurLineInfo());
        }

        user.setPwd("");
        return RespPack.respPackSuc(user);
    }
}

测试

使用postman工具进行测试
在这里插入图片描述

代码地址

https://gitee.com/blog_pro/restful-user.git

  • 4
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值