文章目录
- 技术栈
- 编辑器
- 数据库
- 切换数据库
- 创建数据表
- 初始化数据
- 后端代码
- 实现UserEntity代码
- 实现UserMapper代码
- 创建userMapper.xml文件
- 实现UserVo代码
- 实现UserService代码
- 实现UserLoginDto代码
- 实现UserController代码
- 解决跨域的问题
- 前端代码
- 实现portConfig.ts代码
- 修改api.ts文件
- 启动项目
- 解决ant design pro登录成功无法跳转的问题
- 分析问题
- 解决问题
- 修改前端代码
- 修改后端代码
- 最终效果
技术栈
实现前后单登录的接口,使用到的技术栈如下:
- 前端
- ant desigin pro
- react
- typescript(ts)
- es
- 后端
- spring boot
- mysql
- jdk1.8
编辑器
- 前端
- web storm
- 后端
- idea
数据库
切换数据库
mysql> use superjson;
Database changed
创建数据表
mysql> create table core_user(
-> id int(11) PRIMARY key not null auto_increment comment '自增主键',
-> username varchar(50) not null comment '用户名',
-> password VARCHAR(50) not null comment '密码',
-> avatar VARCHAR(512) NOT NULL comment '头像',
-> nick_name VARCHAR(255) comment '昵称'
-> ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.04 sec)
初始化数据
在初始化admin
数据时,没有将密码加密,因为只是使用ant design pro
模拟登录,没有做这么复杂。
在实际工作中,我们应该以密文的形式存储密码。
mysql> INSERT INTO core_user ( username, PASSWORD, avatar, nick_name )VALUES(
-> 'admin',
-> 'ant.design',
-> 'https://himg.bdimg.com/sys/portraitn/item/public.1.8a548439.18Y_0tyMCA-PRvCGNzwL6w',
-> '念兮为美'
-> );
Query OK, 1 row affected (0.01 sec)
后端代码
实现UserEntity代码
从数据库中查询出的用户【user】被装载到实体类【userEntity】中
package com.superjson.superjsonmanager.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 念兮为美
* @datetime 2022/8/8 15:21
* @desc 从数据库中查询出的用户【user】被装载到实体类【userEntity】中
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class UserEntity {
private Long id;
private String password;
private String username;
private String nickName;
private String avatar;
}
实现UserMapper代码
package com.superjson.superjsonmanager.mapper;
import com.superjson.superjsonmanager.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @author 念兮为美
* @datetime 2022/8/8 15:20
* @desc user映射器
*/
@Mapper
public interface UserMapper {
/**
* 使用账户名和密码查询用户
*
* @author 念兮为美
* @datetime 2022/8/8:15:41
* @param username 账户名
* @param password 密码
*/
UserEntity getByUsernameAndPassword(@PathVariable String username, @PathVariable String password);
}
创建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.superjson.superjsonmanager.mapper.UserMapper">
<select id="getByUsernameAndPassword" resultType="com.superjson.superjsonmanager.entity.UserEntity">
select id,username,password,nick_name as nickName,avatar from core_user where username =#{username} and password = #{password} limit 1
</select>
</mapper>
实现UserVo代码
userEntity的数据映射到userVo对象中
package com.superjson.superjsonmanager.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 念兮为美
* @datetime 2022/8/8 16:31
* @desc userEntity的数据映射到userVo对象中
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class UserVo {
private String name;
private String currentAuthority;
private String status;
private String type;
private String avatar;
}
实现UserService代码
package com.superjson.superjsonmanager.service;
import com.alibaba.fastjson.JSONObject;
import com.superjson.superjsonmanager.entity.UserEntity;
import com.superjson.superjsonmanager.mapper.UserMapper;
import com.superjson.superjsonmanager.vo.UserVo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author 念兮为美
* @datetime 2022/8/8 15:47
* @desc 用户服务类
*/
@Service
public class UserService {
@Resource private UserMapper userMapper;
/**
* @author 念兮为美
* @datetime 2022/8/8:16:35
* @param username 账户名
* @param password 密码
* @desc 使用账户名和密码查询用户
*/
public JSONObject getByUsernameAndPassword(String username, String password, String type) {
UserEntity userEntity = userMapper.getByUsernameAndPassword(username, password);
UserVo userVo = new UserVo();
userVo.setAvatar(userEntity.getAvatar());
userVo.setName(userEntity.getNickName());
userVo.setCurrentAuthority("admin");
userVo.setType(type);
userVo.setStatus("ok");
return (JSONObject) JSONObject.toJSON(userVo);
}
}
实现UserLoginDto代码
用户登录请求参数
package com.superjson.superjsonmanager.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 念兮为美
* @datetime 2022/8/5 21:34
* @desc 用户登录请求参数
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class UserLoginDto {
private String password;
private String type;
private String username;
}
实现UserController代码
package com.superjson.superjsonmanager.controller;
import com.alibaba.fastjson.JSONObject;
import com.superjson.superjsonmanager.dto.UserLoginDto;
import com.superjson.superjsonmanager.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author 念兮为美
* @datetime 2022/8/5 21:30
* @desc 用户登录控制器
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired private UserService userService;
@PostMapping("/login")
public JSONObject login(@RequestBody UserLoginDto userLogin) {
return userService.getByUsernameAndPassword(
userLogin.getUsername(), userLogin.getPassword(), userLogin.getType());
}
}
解决跨域的问题
这是解决跨域的问题,如下图所示:
package com.superjson.superjsonmanager.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author 念兮为美
* @datetime 2022/8/5 22:32
* @desc 解决跨域的过滤器
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//是否发送Cookie
.allowCredentials(true)
//设置放行哪些原始域 SpringBoot2.4.4下低版本使用.allowedOrigins("*")
.allowedOriginPatterns("*")
//放行哪些请求方式
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
//.allowedMethods("*") //或者放行全部
//放行哪些原始请求头部信息
.allowedHeaders("*")
//暴露哪些原始请求头部信息
.exposedHeaders("*");
}
}
前端代码
实现portConfig.ts代码
/**
* 这是api端口号的配置
*/
const portConfigs = {
dev: {
baseUrl: 'http://127.0.0.1:8088',
},
test: {},
prd: {
baseUrl: 'http://https://www.superjson.com/api',
},
};
export const portConfig: { baseUrl: string } = portConfigs['dev']
修改api.ts文件
- 打开
src -> services -> ant-design-pro ->
目录下的api.ts
文件。 - 找到login方法
- 将login方法中的
/api/login/account
修改为`${portConfig.baseUrl}/user/login` - 如下代码所示:
/** 登录接口 POST /api/login/account */
export async function login(body: API.LoginParams, options?: { [key: string]: any }) {
return request<API.LoginResult>(`${portConfig.baseUrl}/user/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: body,
...(options || {}),
});
}
启动项目
- 启动spring boot项目,如下图所示:
- 使用
npm run start
启动 ant design pro项目 - 输入用户名、密码,点击登录,如下图所示:
满心欢喜地点击登录,也出现了登录成功的弹出框,但页面就是没有跳转过去,为什么会出现这种情况呢?
解决ant design pro登录成功无法跳转的问题
分析问题
明明是登录成功了,为什么没有跳转呢?
于是,使用F12
打开调试面板,发现/api/currentUser
接口报错了,错误信息是没有授权,如下图所示:
而且,请求地址是http://127.0.0.1:8001/
,并非我定义的后端地址http://127.0.0.1:8088
。
解决问题
修改前端代码
因而,在ant design pro 项目中搜索接口/api/currentUser
,定位到src -> services -> ant-design-pro ->
目录下的 api.ts
文件的currentUser
方法。
于是,将currentUser
中的/api/currentUser
修改为`${portConfig.baseUrl}/user/currentUser` ,如下所示:
/** 获取当前的用户 GET /api/currentUser */
export async function currentUser(options?: { [key: string]: any }) {
return request<{
data: API.CurrentUser;
}>(`${portConfig.baseUrl}/user/currentUser`, {
method: 'GET',
...(options || {}),
});
}
修改后端代码
在UserController
中增加currentUser
方法,将数据库的数据直接返回,没有使用userService
到userMapper
调用的方式,读者可以自行实现这部分代码。
currentUser
方法如下代码:
@GetMapping("/currentUser")
public JSONObject currentUser() {
JSONObject data = new JSONObject();
data.put("name", "念兮为美");
data.put("access", "admin");
data.put("avatar", "https://himg.bdimg.com/sys/portraitn/item/public.1.8a548439.18Y_0tyMCA-PRvCGNzwL6w");
JSONObject body = new JSONObject();
body.put("data", data);
body.put("success", true);
return body;
}
最终效果