数据库:
项目依赖:
pom.xml文件内的依赖
<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.5version>
<relativePath/>
parent>
<groupId>org.examplegroupId>
<artifactId>reggieartifactId>
<version>1.0-SNAPSHOTversion>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<scope>compilescope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.2version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.20version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.76version>
dependency>
<dependency>
<groupId>commons-langgroupId>
<artifactId>commons-langartifactId>
<version>2.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.23version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>2.4.5version>
plugin>
plugins>
build>
project>
yaml配置文件:
server:
port: 8080
spring:
application:
#应用名称
name: reggie_take_out
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 123456
mybatis-plus:
# 配置xml文件扫描包位置
mapper-locations: classpath:/mappers/*.xml
# 配置实体类扫描包位置,可以给该包内实体类自动起别名
type-aliases-package: com.reggie.entity
configuration:
#address_book->AddressBook
#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: ASSIGN_ID
前端资源:
直接将资料提供的backend
和front
文件夹直接复制到resource
目录下
添加配置类添加静态资源访问目录:
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
addResourceHandler
:添加URL响应地址目录。addResourceLocations
:添加实际资源目录@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始静态资源映射");
// 当"/backend/**"的请求进来,自动响应到静态资源目录"classpath:/backend/"
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
}
配置Knife4j:
引入依赖:
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>knife4j-spring-boot-starterartifactId>
<version>3.0.3version>
dependency>
创建配置类,修改静态资源访问规则:
配置类:Knife4jConfiguration
@Configuration
@EnableOpenApi
// @EnableKnife4j
// @EnableSwagger2
public class Knife4jConfiguration {
@Bean
public Docket docket() {
Docket docket = new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("我的标题")
.description("我的描述")
// .termsOfServiceUrl("http://www.xx.com/")
.contact(new Contact("knife", "https://knife.blog.csdn.net/", "[email protected]"))
.version("1.0")
.build())
// 分组名称
.groupName("all")
.select()
// 这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.reggie.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
修改静态资源配置:WebMVCConfig
@Configuration
public class WebMVCConfig extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
// 添加静态资源放行
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
在启动项目后可以访问localhost:8080/doc.html访问接口文档对接口进行测试
需求:
code
、data
、msg
前端页面 /backend/page/login.html
1.前端根据后端返回的结果内的code 判断是否登录成功
2.data保存的是用户的登录信息
msg保存的是登录失败返回的失败信息
这些都是我们后端需要处理返回给前端的数据
优化思路:等项目大体完成后再次优化
(后面优化可以生成token保存到redis内加快性能,还可以使用SpringSecurity进行权限校验,等后面二次开发的时候优化)
流程:
1.获取请求体内的数据employ
2.将提交的密码进行MD5加密
Spring内部已经封装好内置的方法类了,直接调用即可
String md5Str = DigestUtils.md5DigestAsHex(“原串”.getBytes());
3.根据用户名去数据库内查询用户是否存在并且状态为可登录(status=1)
4.校验密码是否正确
5.将用户信息保存到session内
6.获取用户数据封装到MyResult内返回
employController:
@RestController
@RequestMapping("/employee")
@Api(tags = "employee")
public class employController {
@Autowired
private employServiceImpl employService;
@ApiOperation("登录")
@PostMapping("/login")
public MyResult<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
// 1.MD5加密
String MD5Password = DigestUtils.md5DigestAsHex(employee.getPassword().getBytes());
// 2.根据用户名查询数据库
LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Employee::getUsername,employee.getUsername());
Employee employee1 = employService.getOne(wrapper);
if (employee1==null){
return MyResult.error("查无此人!");
}
// 3.校验密码
if (!employee1.getPassword().equals(MD5Password)){
return MyResult.error("密码错误!");
}
// 校验用户状态是否正常
if (employee1.getStatus()==0){
return MyResult.error("用户账号被禁用!");
}
// 4.将用户id信息保存到session内
request.getSession().setAttribute("employee",employee1.getId());
// 5.封装信息并返回
return MyResult.success(employee1);
}
@PostMapping("/employee/logout")
@ApiOperation("退出登录")
public MyResult logout(HttpServletRequest request){
// 1.清除session内保存的用户id
request.getSession().removeAttribute("employee");
// 2.向前端返回数据
return MyResult.success("退出成功!");
}
}
employServiceImpl:
@Service
public class employServiceImpl extends ServiceImpl implements employService {
}
employMapper:
@Mapper
public interface employMapper extends BaseMapper<Employee> {
}
需要完善的地方:
前面我们已经完成了后台系统的员工登录功能开发,但是还存在一个问题:用户如果不登录,直接访问系统首页面,照样可以正常访问。这种设计并不合理,我们希望看到的效果应该是,只有登录成功后才可以访问系统中的页面,如果没有登录则跳转到登录页面。
那么,具体应该怎么实现呢?
答案就是使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面
后期完善思路:使用SpringSecurity结合JWT生成唯一token保存到redis内进行身份验证,因为如果只是将用户登录身份信息保存到session的话,浏览器会进行缓存,有时候会使用户跳过身份验证直接访问内部页面
实现:
WebMVCConfig
// 配置拦截器
@Override
protected void addInterceptors(InterceptorRegistry registry) {
// 判断用户是否登录拦截器
List<String> excludePathPatterns = new ArrayList<>();
excludePathPatterns.add("/backend/**");
excludePathPatterns.add("/front/**");
excludePathPatterns.add("doc.html");
excludePathPatterns.add("/webjars/**");
excludePathPatterns.add("/employee/login");
excludePathPatterns.add("/employee/logout");
excludePathPatterns.add("/error");
excludePathPatterns.add("/index");
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludePathPatterns);
}
loginInterceptor:
@Slf4j
@Component
public class loginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("拦截请求:"+request.getRequestURI());
Object employee = request.getSession().getAttribute("employee");
if (employee==null) {
// 拦截请求 转发到登录页面
falseResult(response);
return false;
}
log.info("请求放行:"+request.getRequestURI());
return true;
}
public void falseResult(HttpServletResponse response) throws IOException {
response.sendRedirect("/index");
}
}
IndexController:
@Controller
public class indexController {
@RequestMapping("/index")
public String index(){
return "/login.html";
}
}