tio-boot-案例 - 用户登录和注册
本章节使用 tio-boot 开发一个用户注册和登录系统 首先会在 mysql 中创建一张表 然后使用 java-db 连接 mysql 使用 sa-token 将用户信息保存到 reids 1.1.创建表
CREATE TABLE IF NOT EXISTS `sys_user_info` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`app_id` INT NOT NULL COMMENT '应用id',
`username` VARCHAR(32) NULL COMMENT '用户id',
`password` VARCHAR(64) NULL COMMENT '登录密码',
`area_code` VARCHAR(8) NULL COMMENT '手机区号',
`phone` VARCHAR(16) NULL COMMENT '手机号码',
`email` VARCHAR(64) NULL COMMENT '邮箱',
`wx_open_id` VARCHAR(32) NULL COMMENT '微信openid',
`wx_user_info` JSON NULL COMMENT '微信用户信息',
`facebook_id` VARCHAR(64) NULL,
`facebook_user_info` JSON NULL,
`user_channel` INT NOT NULL COMMENT '用户注册渠道,网页,安卓APP,IOS APP,小程序等',
`user_from` INT NOT NULL COMMENT '用户来源,email,手机号,第三方授权等',
`user_level` INT NOT NULL COMMENT '用户级别',
`name` VARCHAR(32) NULL COMMENT '名字',
`nick_name` VARCHAR(32) NULL COMMENT '昵称',
`sex` INT NULL COMMENT '性别',
`header_pic_id` BIGINT NULL COMMENT '头像图片id',
`config_info` JSON NULL COMMENT '配置信息',
`status` INT NOT NULL COMMENT '账号状态',
`add_time_long` BIGINT NOT NULL COMMENT '添加时间',
`update_time_long` BIGINT NOT NULL COMMENT '更新时间',
`locale` VARCHAR(6) NULL COMMENT '语系编码',
`v` INT NOT NULL COMMENT '版本号',
PRIMARY KEY (`id`))
1.2.添加依赖 添加的依赖有
- tio-boot
- slf4j-api
- lombok
- hotswap-classloader
- ApiTable
- mysql-connector-java
- HikariCP
- sa-token-core
- java-db
- jedis
- fst
- junit
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<graalvm.version>23.1.1</graalvm.version>
<tio.boot.version>1.3.6</tio.boot.version>
<lombok-version>1.18.30</lombok-version>
<hotswap-classloader.version>1.2.1</hotswap-classloader.version>
<final.name>web-hello</final.name>
</properties>
<dependencies>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>tio-boot</artifactId>
<version>${tio.boot.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok-version}</version>
<optional>true</optional>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>hotswap-classloader</artifactId>
<version>${hotswap-classloader.version}</version>
</dependency>
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>ApiTable</artifactId>
<version>1.2.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
<!-- Sa-Token 核心库 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>
<version>1.37.0</version>
</dependency>
<!-- JFinal 插件,用于与 Redis 交互 -->
<dependency>
<groupId>com.litongjava</groupId>
<artifactId>java-db</artifactId>
<version>1.0.5</version>
</dependency>
<!-- Jedis,Redis 的 Java 客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.6.3</version>
</dependency>
<!-- FST 序列化工具,用于对象和字节流间的转换 -->
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>2.57</version> <!-- 注意:更高版本不支持 JDK 8 -->
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
1.3.配置文件 app.properties
server.port=9204
server.context-path=/pen-api
# 或 prod
app.env=dev
app-dev.properties
jdbc.url=jdbc:mysql://192.168.3.9/enote?characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=UTC
jdbc.user=root
jdbc.pswd=robot_123456#
jdbc.MaximumPoolSize=2
redis.host=127.0.0.1
redis.port=6379
redis.password=
redis.database=2
redis.timeout=15000
i18n_en_US.properties
The_username_or_password_cannot_be_empty=The username or password cannot be empty
The_locale_cannot_be_empty=The locale cannot be empty
The_userChannel_cannot_be_empty=The userChannel cannot be empty
The_appId_cannot_be_empty=The appId cannot be empty
The_userFrom_cannot_be_empty=The userFrom cannot be empty
The_v_cannot_be_empty=The v cannot be empty
The_username_at_least_6_characters=The username at least 6 characters
The_password_at_least_8_characters=The password at least 8 characters
The_password_should_contain_uppercase_letters,_lowercase_letters_and_numbers=The password should contain uppercase letters, lowercase letters and numbers
The_locale_at_least_5_characters=The locale at least 5 characters
The_username_exists=The username exists
i18n_zh_CN.properties
The_username_or_password_cannot_be_empty=用户名或者密码不能为空
The_locale_cannot_be_empty=locale不能为空
The_userChannel_cannot_be_empty=The userChannel不能为空
The_appId_cannot_be_empty=The appId不能为空
The_userFrom_cannot_be_empty=The userFrom不能为空
The_v_cannot_be_empty=The v不能为空
The_username_at_least_6_characters=username至少6个字符
The_password_at_least_8_characters=password至少8个字符
The_password_should_contain_uppercase_letters,_lowercase_letters_and_numbers=password需要包含大写字母,小写字母和数字
The_locale_at_least_5_characters=locale至少5个字符
The_username_exists=用户名已经存在
1.4.启动类
import com.litongjava.hotswap.wrapper.tio.boot.TioApplicationWrapper;
import com.litongjava.jfinal.aop.annotation.AComponentScan;
@AComponentScan
public class MaLiangPenAiServerApp {
public static void main(String[] args) {
long start = System.currentTimeMillis();
TioApplicationWrapper.run(MaLiangPenAiServerApp.class, args);
//TioApplication.run(MaLiangPenAiServerApp.class, args);
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
}
}
1.5.连接 mysql
package com.enoleap.manglang.pen.api.server.config;
import javax.sql.DataSource;
import com.jfinal.template.Engine;
import com.jfinal.template.source.ClassPathSourceFactory;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.jfinal.aop.annotation.ABean;
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.litongjava.jfinal.plugin.activerecord.OrderedFieldContainerFactory;
import com.litongjava.tio.boot.constatns.ConfigKeys;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.utils.environment.EnvUtils;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@AConfiguration
public class DbConfig {
@ABean(priority = 1)
public DataSource dataSource() {
String jdbcUrl = EnvUtils.get("jdbc.url");
String jdbcUser = EnvUtils.get("jdbc.user");
String jdbcPswd = EnvUtils.get("jdbc.pswd");
int maximumPoolSize = EnvUtils.getInt("jdbc.MaximumPoolSize", 2);
HikariConfig config = new HikariConfig();
// 设定基本参数
config.setJdbcUrl(jdbcUrl);
config.setUsername(jdbcUser);
config.setPassword(jdbcPswd);
config.setMaximumPoolSize(maximumPoolSize);
HikariDataSource hikariDataSource = new HikariDataSource(config);
TioBootServer.addDestroyMethod(hikariDataSource::close);
return hikariDataSource;
}
/*
*
* config ActiveRecordPlugin
*/
@AInitialization
public ActiveRecordPlugin activeRecordPlugin() throws Exception {
DataSource dataSource = Aop.get(DataSource.class);
String property = EnvUtils.get(ConfigKeys.APP_ENV);
ActiveRecordPlugin arp = new ActiveRecordPlugin(dataSource);
arp.setContainerFactory(new OrderedFieldContainerFactory());
Engine engine = arp.getEngine();
engine.setSourceFactory(new ClassPathSourceFactory());
engine.setCompressorOn(' ');
engine.setCompressorOn('\n');
if ("dev".equals(property)) {
arp.setDevMode(true);
engine.setDevMode(true);
}
arp.addSqlTemplate("/sql/all_sqls.sql");
arp.start();
TioBootServer.addDestroyMethod(arp::stop);
return arp;
}
}
1.6.连接 reids
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.jfinal.plugin.redis.Cache;
import com.litongjava.jfinal.plugin.redis.Redis;
import com.litongjava.jfinal.plugin.redis.RedisPlugin;
import com.litongjava.tio.boot.server.TioBootServer;
import com.litongjava.tio.utils.environment.EnvUtils;
@AConfiguration
public class RedisPluginConfig {
@AInitialization
public RedisPlugin redisPlugin() {
String redisHost = EnvUtils.get("redis.host", "127.0.0.1");
int redisPort = EnvUtils.getInt("redis.port", 6379);
String redisPassword = EnvUtils.getStr("redis.password");
int redistimeout = EnvUtils.getInt("redis.timeout", 60);
int redisDatabase = EnvUtils.getInt("redis.database", 0);
// 创建并启动 Redis 插件
RedisPlugin redisPlugin = new RedisPlugin("main", redisHost, redisPort, redistimeout, redisPassword, redisDatabase);
redisPlugin.start();
TioBootServer.addDestroyMethod(redisPlugin::stop);
// 测试连接
Cache cache = Redis.use("main");
cache.getJedis().connect();
return redisPlugin;
}
}
1.7.注册 注册的业务逻辑是获取请求信息,验证请求信息,验证通过插入到数据库
1.7.1.UserRegisterVO
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class UserRegisterVO {
private String username;
private String password;
private String locale;
private Integer appId;
//1 Android App,2 IOS App 3 小程序 4 网页
private Integer userChannel;
//用户来源:1:手机号,2:email,3:第三方授权等,4:用户名
private Integer userFrom;
//版本号
private Integer v;
}
1.7.2.UserRegisterController
import com.litongjava.jfinal.aop.annotation.AAutowired;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.utils.resp.RespVo;
@RequestPath("/user/register")
public class UserRegisterController {
@AAutowired
private UserRegisteValidator userRegisteValidator;
@AAutowired
private UserRegisterService userRegisterService;
@RequestPath
public RespVo index(UserRegisterVO reqVo) {
RespVo respVo = userRegisteValidator.index(reqVo);
if (respVo != null) {
return respVo;
}
return userRegisterService.index(reqVo);
}
}
1.7.3.UserRegisteValidator
package com.enoleap.manglang.pen.api.server.validator;
import com.enoleap.manglang.pen.api.server.model.UserRegisterVO;
import com.enoleap.manglang.pen.api.server.services.SysUserInfoService;
import com.jfinal.kit.StrKit;
import com.litongjava.jfinal.aop.annotation.AAutowired;
import com.litongjava.tio.boot.i18n.I18n;
import com.litongjava.tio.boot.i18n.I18nLocale;
import com.litongjava.tio.boot.i18n.Res;
import com.litongjava.tio.utils.resp.RespVo;
public class UserRegisteValidator {
@AAutowired
private SysUserInfoService sysUserInfoService;
public RespVo index(UserRegisterVO reqVo) {
String username = reqVo.getUsername();
String password = reqVo.getPassword();
String locale = reqVo.getLocale();
Integer userChannel = reqVo.getUserChannel();
Integer appId = reqVo.getAppId();
Integer userFrom = reqVo.getUserFrom();
Integer v = reqVo.getV();
Res res = null;
if (I18nLocale.ZH_CN.equals(locale)) {
res = I18n.use(I18nLocale.ZH_CN);
} else {
res = I18n.use(I18nLocale.EN_US);
}
// 验证username
if (StrKit.isBlank(username)) {
String string = res.get("The_username_or_password_cannot_be_empty");
return RespVo.fail(string);
}
if (StrKit.isBlank(password)) {
return RespVo.fail(res.get("The_username_or_password_cannot_be_empty"));
}
if (StrKit.isBlank(locale)) {
return RespVo.fail(res.get("The_locale_cannot_be_empty"));
}
if (userChannel == null) {
return RespVo.fail(res.get("The_userChannel_cannot_be_empty"));
}
if (appId == null) {
return RespVo.fail(res.get("The_appId_cannot_be_empty"));
}
if (userFrom == null) {
return RespVo.fail(res.get("The_userFrom_cannot_be_empty"));
}
if (v == null) {
return RespVo.fail(res.get("The_v_cannot_be_empty"));
}
if (username.length() < 6) {
return RespVo.fail("The_username_at_least_6_characters");
}
if (password.length() < 8) {
return RespVo.fail("The_password_at_least_8_characters");
}
// 至少包含大小,小写和数字
if (!PasswordValidator.validatePassword(password)) {
return RespVo.fail(res.get("The_password_should_contain_uppercase_letters,_lowercase_letters_and_numbers"));
}
if (locale.length() < 5) {
return RespVo.fail(res.get("The_locale_at_least_5_characters"));
}
// 判断用户名是否存在
if (sysUserInfoService.existsUsername(username)) {
return RespVo.fail(res.get("The_username_exists"));
}
return null;
}
}
1.7.4.SysUserInfoService
import com.litongjava.jfinal.plugin.activerecord.Db;
public class SysUserInfoService {
/**
* 判断用户是否存在
* @param username
* @return
*/
public boolean existsUsername(String username) {
String sql = "select count(1) from sys_user_info where username=?";
Long size = Db.queryLong(sql, username);
if (size > 0) {
return true;
} else {
return false;
}
}
}
1.7.5.UserRegisterService
import com.litongjava.jfinal.plugin.activerecord.Db;
import com.litongjava.tio.utils.resp.RespVo;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class UserRegisterService {
public RespVo index(UserRegisterVO reqVo) {
Integer appId = reqVo.getAppId();
String username = reqVo.getUsername();
String password = reqVo.getPassword();
Integer userChannel = reqVo.getUserChannel();
Integer userFrom = reqVo.getUserFrom();
Integer userLevel = 1;
Integer status = 1;
long addTime = System.currentTimeMillis();
long updateTime = addTime;
Integer v = reqVo.getV();
String locale = reqVo.getLocale();
String sql = "insert into sys_user_info(app_id,username,password,user_channel,user_from,user_level,status,add_time_long,update_time_long,v,locale)"
+ " value(?,?,?,?,?,?,?,?,?,?,?)";
boolean success = false;
try {
//在事务内进行操作
success = Db.tx(() -> {
int update = Db.update(sql, appId, username, password, userChannel, userFrom, userLevel, status, addTime,
updateTime, v, locale);
log.info("update result:{}", update);
return true;
});
} catch (Exception e) {
e.printStackTrace();
return RespVo.fail(e.getMessage());
}
if (success) {
return RespVo.ok();
} else {
return RespVo.fail();
}
}
}
1.8.单元测试注册 1.8.1.TioBootTest
import java.util.List;
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.tio.boot.constatns.ConfigKeys;
import com.litongjava.tio.utils.environment.EnvUtils;
import com.litongjava.tio.utils.environment.PropUtils;
import com.litongjava.tio.utils.hutool.ResourceUtil;
public class TioBootTest {
public static void before() throws Exception {
String env = EnvUtils.get("app.env");
if (ResourceUtil.getResource(ConfigKeys.DEFAULT_CONFIG_FILE_NAME) != null) {
PropUtils.use(ConfigKeys.DEFAULT_CONFIG_FILE_NAME, env);
} else {
if (env != null) {
PropUtils.use("app-" + env + ".properties");
}
}
List<Class<?>> scannedClasses = Aop.scan(MaLiangPenAiServerApp.class);
Aop.initAnnotation(scannedClasses);
}
}
1.8.2.SysUserInfoServiceTest
import org.junit.Before;
import org.junit.Test;
import com.litongjava.jfinal.aop.Aop;
public class SysUserInfoServiceTest {
@Before
public void before() throws Exception {
TioBootTest.before();
}
@Test
public void test() {
boolean existsUsername = Aop.get(SysUserInfoService.class).existsUsername("litong");
System.out.println(existsUsername);
}
}
1.8.3.UserRegisterServiceTest
import org.junit.Before;
import org.junit.Test;
import com.litongjava.tio.utils.resp.RespVo;
public class UserRegisterServiceTest {
@Before
public void before() throws Exception {
TioBootTest.before();
}
@Test
public void test() {
UserRegisterService userRegisterService = new UserRegisterService();
UserRegisterVO reqVo = UserRegisterVO.builder().username("litong").password("Litong2516").locale("zh_CN")
.userChannel(1).appId(1).userFrom(4).v(1)
//
.build();
RespVo respVo = userRegisterService.index(reqVo);
if (!respVo.isOk()) {
System.out.println(respVo.getMsg());
}
}
}
1.8.4.UserRegisteValidatorTest
import org.junit.Test;
import com.jfinal.kit.StrKit;
import com.litongjava.tio.boot.i18n.I18n;
import com.litongjava.tio.boot.i18n.I18nLocale;
import com.litongjava.tio.boot.i18n.Res;
public class UserRegisteValidatorTest {
@Test
public void test() {
String locale = I18nLocale.ZH_CN;
String username = null;
Res res = null;
if (I18nLocale.ZH_CN.equals(locale)) {
res = I18n.use(I18nLocale.ZH_CN);
} else {
res = I18n.use(I18nLocale.EN_US);
}
// 验证username
String string = null;
if (StrKit.isBlank(username)) {
string = res.get("The_username_or_password_cannot_be_empty");
}
System.out.println(string);
}
}
1.9.整合 sa-token 1.9.1.SaTokenConfiguration
// 导入必要的类和注解
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.jfinal.plugin.satoken.SaTokenDaoRedis;
import com.litongjava.tio.boot.satoken.SaTokenContextForTio;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaCookieConfig;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.util.SaTokenConsts;
@AConfiguration
public class SaTokenConfiguration {
@AInitialization
public void config() {
// 初始化 Sa-Token 上下文
SaTokenContext saTokenContext = new SaTokenContextForTio();
// 设置 Cookie 配置,例如启用 HttpOnly 属性
SaCookieConfig saCookieConfig = new SaCookieConfig();
saCookieConfig.setHttpOnly(true);
// 初始化和配置 Sa-Token 主配置
SaTokenConfig saTokenConfig = new SaTokenConfig();
saTokenConfig.setTokenStyle(SaTokenConsts.TOKEN_STYLE_SIMPLE_UUID);
saTokenConfig.setActiveTimeout(50 * 60); // 设置活动超时时间为 50 分钟
saTokenConfig.setIsShare(false);
saTokenConfig.setTokenName("token"); // 设置 token 的名称
saTokenConfig.setIsWriteHeader(true); // 将 token 写入响应头
saTokenConfig.setIsReadHeader(true); // 从请求头中读取 token
saTokenConfig.setCookie(saCookieConfig);
// 应用配置到 Sa-Token 管理器
SaManager.setConfig(saTokenConfig);
SaManager.setSaTokenContext(saTokenContext);
// 在 Sa-Token 配置类中添加
SaManager.setSaTokenDao(new SaTokenDaoRedis("main"));
}
}
1.9.2.InterceptorConfiguration
// 导入必要的类和注解
import com.litongjava.jfinal.aop.annotation.AConfiguration;
import com.litongjava.jfinal.aop.annotation.AInitialization;
import com.litongjava.tio.boot.http.interceptor.HttpServerInterceptorModel;
import com.litongjava.tio.boot.satoken.SaTokenInterceptor;
import com.litongjava.tio.boot.server.TioBootServer;
@AConfiguration
public class InterceptorConfiguration {
@AInitialization
public void config() {
// 创建 SaToken 拦截器实例
SaTokenInterceptor saTokenInterceptor = new SaTokenInterceptor();
HttpServerInterceptorModel model = new HttpServerInterceptorModel();
model.setInterceptor(saTokenInterceptor);
model.addblockeUrl("/**"); // 拦截所有路由
model.addAlloweUrls("/status","/user/register", "/auth/*"); // 设置例外路由
// 将拦截器配置添加到 Tio 服务器
TioBootServer.getServerInteceptorConfigure().add(model);
}
}
1.10.登录 1.10.1.AuthController
import java.util.HashMap;
import java.util.Map;
import com.litongjava.jfinal.aop.annotation.AAutowired;
import com.litongjava.tio.boot.http.TioControllerContext;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.annotation.RequestPath;
import com.litongjava.tio.http.server.util.Resps;
import com.litongjava.tio.utils.resp.RespVo;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
@RequestPath("/auth")
@Slf4j
public class AuthController {
@AAutowired
private AuthValidator authValidator;
@AAutowired
private AuthService authService;
public HttpResponse doLogin(String username, String password, String locale) {
log.info("username:{}", username);
RespVo respVo = authValidator.doLogin(username, password, locale);
if (respVo != null) {
return Resps.json(TioControllerContext.getResponse(), respVo);
}
respVo = authService.doLogin(username, password);
return Resps.json(TioControllerContext.getResponse(), respVo);
}
public HttpResponse logout() {
StpUtil.logout();
HttpResponse response = TioControllerContext.getResponse();
return Resps.json(response, RespVo.ok());
}
public RespVo validateToken() {
try {
StpUtil.checkActiveTimeout();
return RespVo.ok();
} catch (Exception e) {
return RespVo.fail();
}
}
public RespVo getUserId() {
String tokenValue = StpUtil.getTokenValue();
Object loginId = StpUtil.getLoginId();
long tokenTimeout = StpUtil.getTokenTimeout();
Map<String, Object> map = new HashMap<>();
map.put("token", tokenValue);
map.put("userId", loginId);
map.put("tokenTimeout", tokenTimeout);
return RespVo.ok(map);
}
}
1.10.2.AuthValidator
import com.jfinal.kit.StrKit;
import com.litongjava.tio.boot.i18n.I18n;
import com.litongjava.tio.boot.i18n.I18nLocale;
import com.litongjava.tio.boot.i18n.Res;
import com.litongjava.tio.utils.resp.RespVo;
public class AuthValidator {
public RespVo doLogin(String username, String password,String locale) {
Res res = null;
if (I18nLocale.ZH_CN.equals(locale)) {
res = I18n.use(I18nLocale.ZH_CN);
} else {
res = I18n.use(I18nLocale.EN_US);
}
if (StrKit.isBlank(locale)) {
return RespVo.fail(res.get("The_locale_cannot_be_empty"));
}
if(StrKit.isBlank(username) || StrKit.isBlank(password)) {
String string = res.get("The_username_or_password_cannot_be_empty");
return RespVo.fail(string);
}
return null;
}
}
1.10.3.AuthService
import com.litongjava.jfinal.plugin.activerecord.Db;
import com.litongjava.tio.utils.resp.RespVo;
import cn.dev33.satoken.stp.StpUtil;
public class AuthService {
public RespVo doLogin(String username, String password) {
String sql = "select id from sys_user_info where username=? and password=?";
Long result = Db.queryLong(sql, username, password);
if (result > 0) {
//登录
StpUtil.login(result);
return RespVo.ok();
} else {
return RespVo.fail();
}
}
}
1.11.发送请求测试 1.11.1.注册
curl --location --request POST 'http://localhost:9204/pen-api/user/register' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Accept: */*' \
--header 'Host: localhost:9204' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=litong' \
--data-urlencode 'password=Litong2516' \
--data-urlencode 'locale=zh_CN' \
--data-urlencode 'userChannel=1' \
--data-urlencode 'appId=1' \
--data-urlencode 'userFrom=4' \
--data-urlencode 'v=1'
1.11.2.登录
curl --location --request POST 'http://localhost:9204/pen-api/auth/doLogin' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Accept: */*' \
--header 'Host: localhost:9204' \
--header 'Connection: keep-alive' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=litong' \
--data-urlencode 'password=Litong2516' \
--data-urlencode 'locale=zh_CN'
响应头中保护 token 响应体如下
{
"ok": true
}
1.11.3.验证 token 是否有效
curl --location --request GET 'http://localhost:9204/pen-api/auth/validateToken' \
--header 'token: 4eb6ac726a7d4f42bb10fe365823f9f7' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Accept: */*' \
--header 'Host: localhost:9204' \
--header 'Connection: keep-alive' \
1.11.4.获取用户 id
curl --location --request GET 'http://localhost:9204/pen-api/auth/getUserId' \
--header 'token: 4eb6ac726a7d4f42bb10fe365823f9f7' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Accept: */*' \
--header 'Host: localhost:9204' \
--header 'Connection: keep-alive'
{
"data": {
"tokenTimeout": 2591819,
"userId": "35",
"token": "4eb6ac726a7d4f42bb10fe365823f9f7"
},
"ok": true
}
1.11.5.登出
curl --location --request GET 'http://localhost:9204/pen-api/auth/logout' \
--header 'token: 4eb6ac726a7d4f42bb10fe365823f9f7' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Accept: */*' \
--header 'Host: localhost:9204' \
--header 'Connection: keep-alive'