【SpringBoot+Vue】后端代码学习记录——登录功能开发

news2024/12/29 9:02:32

参考资料
https://www.cnblogs.com/three-fighter/p/14332288.html

零、前端开发

略。之前有过。

一、后端开发

1、统一结果封装

创建了一个 Result 类,用于异步统一返回的结果封装。一般来说,结果里面有几个要素必要的
是否成功,可用 code 表示(如 200 表示成功,400 表示异常)
结果消息
结果数据

public class Result implements Serializable {
    //响应码
    private Integer code;
    //信息
    private String message;
    //返回数据
    private Object data;

    public Result(Integer code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

实际上由于响应码是固定的,code 属性应该是一个枚举值,这里作了一些简化。

2、登录业务实体类

为了接收前端登录的数据,我们这里创建了一个登录用的业务实体类(LoginDTO)
在这里插入图片描述

public class LoginDTO {
    private String loginName;
    private String password;

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

3、控制层

LoginController,进行业务响应:

package com.test.demo.controller;

import com.test.demo.dto.LoginDTO;
import com.test.demo.result.Result;
import com.test.demo.service.LoginService;
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.RestController;

/**
 *
 *
 * @RestController
 * 在 Spring Boot 中,@Controller 注解是专门用于处理 Http 请求处理的,是以 MVC 为核心的设计思想的控制层。@RestController 则是 @Controller 的衍生注解。
 * Spring Boot 本身就 Spring MVC 的简化版本。是在 Spring MVC 的基础上实现了自动配置,简化了开发人员开发过程。
 *
 *@Autowired
 *
 * 注解基于依赖注入(Dependency Injection,DI)的原理。在Spring容器中,所有的Bean都会被实例化和管理,它们之间的依赖关系由Spring容器来维护。当一个Bean依赖于另一个Bean时,可以使用@Autowired注解来告诉Spring容器自动装配这些依赖。
 *
 * @PostMapping
 * 在 Spring Boot 中,使用 @PostMapping 注解非常简单,只需要将它添加到一个方法的定义上即可
 *我们使用 @PostMapping 注解声明了一个方法 loginr(),这个方法用来处理客户端发送的 POST 请求,并将请求体中的数据转换为 loginDTO 对象(并返回)。
 *
 * */


@RestController
public class LoginController {
    @Autowired
    LoginService loginService;

    @PostMapping(value = "/api/login")
    public Result login(@RequestBody LoginDTO loginDTO){
      return loginService.login(loginDTO);
    }

    @PostMapping(value = "/api/hello")
    public Result hello(){
        return new Result(200,"hello","world");
    }
}

Spring Boot Web 开发@Controller @RestController 使用教程

4、业务层

业务层进行实际的业务处理。

LoginService: service接口

public interface LoginService {
    public Result login(LoginDTO loginDTO);
}

LoginServiceImpl:service接口实现类

@Service
public class LoginServiceImpl implements LoginService {

//    @Autowired 是idea的问题,@Mapper 这个注解是 Mybatis 提供的,而 @Autowried 注解是 Spring 提供的
    @Autowired(required=false)
    private UserMapper userMapper;

    @Override
    public Result login(LoginDTO loginDTO) {
        //判断登录名和密码是否为空:
        //StringUtils 方法的操作对象是 Java.lang.String 类型的对象,是 JDK 提供的 String 类型操作方法的补充

        if (StringUtils.isEmpty(loginDTO.getLoginName())){
            return new Result(400,"账号不能为空","");
        }
        if (StringUtils.isEmpty(loginDTO.getPassword())){
            return new Result(400,"密码不能为空","");
        }

        //通过登录名查询用户
        
        //wrapper.eq("实体类::查询字段", "条件值"); //相当于where条件
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.eq("login_name", loginDTO.getLoginName());
        User uer=userMapper.selectOne(wrapper);
        //比较密码
        if (uer!=null&&uer.getPassword().equals(loginDTO.getPassword())){
            LoginVO loginVO=new LoginVO();
            loginVO.setId(uer.getId());
            //这里token直接用一个uuid
            //使用jwt的情况下,会生成一个jwt token,jwt token里会包含用户的信息
            loginVO.setToken(UUID.randomUUID().toString());
            loginVO.setUser(uer);
            return new Result(200,"",loginVO);
        }
        return new Result(401,"登录失败","");
    }
}

LoginVO
.登录返回接口实体类
数据包:vo
token:返回一段随机字符串


public class LoginVO implements Serializable {
    private Integer id;
    private String token;
    private User user;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

一个登录功能完成了
在这里插入图片描述

登录功能完善

前面虽然实现了登录,但只是一个简单的登录跳转,实际上并不能对用户的登录状态进行判别,接下来我们进一步完善登录功能。

首先开始后端的开发。

1、后端开发
1.1、拦截器
创建 interceptor 包,包下新建拦截器 LoginInterceptor

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

        //从header中获取token
        String token = request.getHeader("token");
        //如果token为空
        if (StringUtils.isBlank(token)) {
            setReturn(response,400,"用户未登录,请先登录");
            return false;
        }
        //在实际使用中还会:
        // 1、校验token是否能够解密出用户信息来获取访问者
        // 2、token是否已经过期

        return true;
    }



    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    }

    //返回json格式错误信息
    private static void setReturn(HttpServletResponse response, Integer code, String msg) throws IOException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtil.getOrigin());
        //UTF-8编码
        httpResponse.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        Result result = new Result(code,msg,"");
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(result);
        httpResponse.getWriter().print(json);
    }

}

为了能给前端返回 json 格式的结果,这里还用到了一个工具类,新建 util 包,util 包下新建工具类 HttpContextUtil

public class HttpContextUtil {
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    public static String getDomain() {
        HttpServletRequest request = getHttpServletRequest();
        StringBuffer url = request.getRequestURL();
        return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
    }

    public static String getOrigin() {
        HttpServletRequest request = getHttpServletRequest();
        return request.getHeader("Origin");
    }
}


1.2、拦截器配置
拦截器创建完成之后,还需要进行配置。

@Configuration
public class DemoWebConfig implements WebMvcConfigurer {


    /**
     * 拦截器配置
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //添加拦截器
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/api/**")
                //放行路径,可以添加多个
                .excludePathPatterns("/api/login");
    }


}

1.3、跨域配置
在之前的后台接口,有一个注解@CrossOrigin ,这个注解是用来跨域的,每个接口都写一遍肯定是不太方便的,这里我们 创建跨域配置类并添加统一的跨域配置:

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //允许源,这里允许所有源访问,实际应用会加以限制
        corsConfiguration.addAllowedOrigin("*");
        //允许所有请求头
        corsConfiguration.addAllowedHeader("*");
        //允许所有方法
        corsConfiguration.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }
}

2.、登录service
这样一来,后端就需要生成一个 token 返回给前端,所以更改 LoginServiceImpl 里的登录方法。

@Service
public class LoginServiceImpl implements LoginService {

//    @Autowired 是idea的问题,@Mapper 这个注解是 Mybatis 提供的,而 @Autowried 注解是 Spring 提供的
    @Autowired(required=false)
    private UserMapper userMapper;

    @Override
    public Result login(LoginDTO loginDTO) {
        //判断登录名和密码是否为空:
        //StringUtils 方法的操作对象是 Java.lang.String 类型的对象,是 JDK 提供的 String 类型操作方法的补充

        if (StringUtils.isEmpty(loginDTO.getLoginName())){
            return new Result(400,"账号不能为空","");
        }
        if (StringUtils.isEmpty(loginDTO.getPassword())){
            return new Result(400,"密码不能为空","");
        }

        //通过登录名查询用户

        //wrapper.eq("实体类::查询字段", "条件值"); //相当于where条件
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.eq("login_name", loginDTO.getLoginName());
        User uer=userMapper.selectOne(wrapper);
        //比较密码
        if (uer!=null&&uer.getPassword().equals(loginDTO.getPassword())){
            LoginVO loginVO=new LoginVO();
            loginVO.setId(uer.getId());
            //这里token直接用一个uuid
            //使用jwt的情况下,会生成一个jwt token,jwt token里会包含用户的信息
            loginVO.setToken(UUID.randomUUID().toString());
            loginVO.setUser(uer);
            return new Result(200,"",loginVO);
        }
        return new Result(401,"登录失败","");
    }
}

其中对返回的data 封装了一个VO:

3.、登录接口测试
在这里插入图片描述
在这里插入图片描述

2、前端开发

实现前端登录器,需要在前端判断用户的登录状态。我们可以像之前那样在组件的 data 中设置一个状态标志,但登录状态应该被视为一个全局属性,而不应该只写在某一组件中。
所以我们需要引入一个新的工具——Vuex,它是专门为 Vue 开发的状态管理方案,我们可以把需要在各个组件中传递使用的变量、方法定义在这里。

  • 访问前端接口自动跳转到login界面

在这里插入图片描述

打开 Application ,在 Session Storage 中看到我们存储的信息-
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1819196.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哪个牌子的儿童护眼灯好?五款平价护眼台灯推荐

护眼台灯在近年来成为家长和长时间使用电子设备人群关注的家电/学生产品。对于家中有孩子或经常面对电子屏幕的人士来说&#xff0c;很多人可能已经对这类产品有所了解并进行了购买。然而&#xff0c;部分家长对护眼台灯的认识还不够深入&#xff0c;因此尚未为孩子选择一款合适…

怎么写自动注册苹果ID的工具,会用到哪些源代码?

在数字化时代&#xff0c;苹果ID成为了连接苹果生态系统中各项服务的关键桥梁&#xff0c;然而&#xff0c;手动注册苹果ID的过程往往繁琐且耗时&#xff0c;因此&#xff0c;开发一款能够自动注册苹果ID的工具成为了许多开发者的追求。 本文将科普如何编写这样的工具&#xf…

每日一练:攻防世界:Misc文件类型

给了一个txt文本文件&#xff0c;因为题目是文件类型&#xff0c;我先开始一直在想关于文件头的知识。 这串数据看着像十六进制数据&#xff0c;我就直接把他转ASCII了 反转一下就是base64&#xff0c;因为base64没有_&#xff0c;所以去掉46ESAB_&#xff0c;base64解码Hex试…

【游戏】一款纯web集前后端为一体的沙盒游戏框架介绍

1.biomes-game是什么&#xff1f; 一款基于MIT协议开源沙盒 MMORPG。游戏中可建造、采集、玩迷你游戏等等&#xff0c;所有操作均可通过浏览器完成。它主要使用React框架&#xff0c;前后端用 Typescript 和 WebAssembly 编写。 2.如何本地体验&#xff1f; 配置&#xff1a;…

简约不简单,建筑装饰演绎现代美学

走在城市的大街小巷&#xff0c;你是否曾被那些独特而精美的建筑装饰所吸引&#xff1f;每一栋建筑都像是艺术家的杰作&#xff0c;通过精美的装饰诉说着它的故事。 我们的建筑装饰&#xff0c;不仅注重外在的美观&#xff0c;更追求内在的品质。从古典的雕花到现代的简约线条&…

干货下载 |《数据治理:数据中台建设与能力提升策略》

在当今这个信息爆炸的时代&#xff0c;数据已经成为企业最宝贵的资产之一。数据不仅能帮助企业洞察市场趋势&#xff0c;还能优化业务流程&#xff0c;提升运营效率&#xff0c;进而在激烈的市场竞争中占据优势地位。然而&#xff0c;如何有效地管理和利用这些数据&#xff0c;…

Qt篇——-1: error: fatal error: no input files问题解决

有时在pro或pri中引用的文件被删除或重命名后&#xff0c;会导致pro或pri文件中自动出现两个连续的//&#xff0c;这将导致我们编译时提示&#xff1a;-1: error: fatal error: no input files。 这是因为qmake 语法里每增加一个源文件或一个配置用一个斜杠结束&#x…

高速直线导轨驱动与控制,精准稳定的运动核心元件

直线导轨在工业生产中&#xff0c;精度和稳定性是至关重要的。而在各种机械设备中&#xff0c;高精度直线导轨是提高设备运动控制精度和平稳性的核心部件&#xff0c;当我们考虑高速运动时&#xff0c;直线导轨的精度和稳定性是非常重要的因素。 直线导轨系统中如何确保高速运动…

计算机网络 —— 运输层(四次挥手)

计算机网络 —— 运输层&#xff08;四次挥手&#xff09; 四次挥手客户端到服务器的关闭第一次挥手第二次挥手 服务器到客户端连接的关闭第三次挥手第四次挥手 等待时间的必要性 我们今天来看TCP协议的四次挥手&#xff1a; 四次挥手 TCP的四次挥手&#xff08;Four-Way Han…

TikTok网红营销指南 | 怎么找到TikTok网红并进行合作?

如果你打算在tiktok上进行营销&#xff0c;忽略与tiktok网红合作无异于错失良机&#xff0c;时尚博主Sophia仅用一条30秒的视频展示了自己从一家新兴品牌购买的连衣裙&#xff0c;视频迅速获得了数百万的点赞和评论&#xff0c;也让该品牌的销量翻了好几倍。 这种与网红合作的策…

TIM—通用定时器高级定时器

通用/高级定时器的功能 在基本定时器功能的基础上新增功能&#xff1a; 通用定时器有4个独立通道&#xff0c;且每个通道都可以用于下面功能。 &#xff08;1&#xff09;输入捕获&#xff1a;测量输入信号的周期和占空比等。 &#xff08;2&#xff09;输出比较&#xff1a;产…

在亚马逊云上部署WordPress:一个完整的LAMP环境安装教程

什么是LAMP LAMP是一个流行的开源软件堆栈&#xff0c;用于网站和网络应用程序的开发和部署。LAMP是几个主要组件的首字母缩写&#xff0c;包括&#xff1a; Linux&#xff1a;操作系统层&#xff0c;LAMP通常部署在Linux操作系统上&#xff0c;但它也可以使用其他类似Unix的…

【软件测试】遇到bug怎么分析,这篇文章值得一看

为什么定位问题如此重要&#xff1f; 可以明确一个问题是不是真的“bug” 很多时候&#xff0c;我们找到了问题的原因&#xff0c;结果发现这根本不是bug。原因明确&#xff0c;误报就会降低 多个系统交互&#xff0c;可以明确指出是哪个系统的缺陷&#xff0c;防止“踢皮球…

Kafka 负载均衡挑战及解决思路

本文转载自 Agoda Engineering&#xff0c;介绍了在实际应用中&#xff0c;如何应对 Kafka 负载均衡所遇到的各种挑战&#xff0c;并提出相应的解决思路。本文简要阐述了 Kafka 的并行性机制、常用的分区策略以及在实际操作中遇到的异构硬件、不均匀工作负载等问题。通过深入分…

ubuntu20.04设置共享文件夹

ubuntu20.04设置共享文件夹 一&#xff0c;简介二&#xff0c;操作步骤1&#xff0c;设置Windows下的共享目录2&#xff0c;挂载共享文件夹3&#xff0c;测试是否挂载成功 一&#xff0c;简介 在公司电脑上&#xff0c;使用samba设置共享文件夹&#xff0c;IT安全部门权限不通…

sql:group by和聚合函数的使用

提示&#xff1a;本文只讲解group by的简单使用和group by和聚合函数组合使用 文章目录 常用聚合函数group by明天继续更新 常用聚合函数 1.MAX&#xff1a;返回某列的最大值 2.MIN(column) 返回某列的最高值 3.COUNT(column) 返回某列的总行数 4.COUNT(*) 返回表的总行数 5.S…

Linux指令(3)

目录 1.上节复习 2.man指令 3.echo指令 4.cp指令 5.mv指令 6.重新认识 7.和文件相关的指令的辨析 8.三大重定向 9.cat指令 10.more命令和less命令 1.上节复习 &#xff08;1&#xff09;我们上次学习了这个和文件的删除以及文件夹的删除的相关的指令&#xff0c;rm …

【网络架构】Nginx

目录 一、I/O模型 1.1 Linux 的 I/O 1.2 零拷贝技术 1.3 网络IO模型 1.3.1 阻塞型 I/O 模型&#xff08;blocking IO&#xff09;​编辑 1.3.2非阻塞型 I/O 模型 (nonblocking IO)​编辑 1.3.3 多路复用 I/O 型 ( I/O multiplexing )​编辑 1.3.4 信号驱动式 I/O 模型 …

React-配置json-server

安装json-server&#xff1a;json-server工具准备后端接口服务环境_jsonserver临时后端-CSDN博客 在package.json文件中的scripts添加&#xff1a; "serve":"json-server json文件路径 --port 端口号" 在终端输入命令npm run serve&#xff0c;就可以启动…

Redis高级特性和应用:慢查询、Pipeline、事务、Lua

Redis提供了许多高级特性&#xff0c;可以帮助优化和管理系统性能。本文将介绍Redis的慢查询、Pipeline、事务和Lua脚本的使用及其相关配置。 Redis的慢查询 慢查询日志是开发和运维人员定位系统慢操作的重要工具。Redis也提供了类似的功能&#xff0c;通过记录超过预设阀值的…