【SpringBoot+Vue】全网最简单但实用的前后端分离项目实战笔记 - 后端

这篇具有很好参考价值的文章主要介绍了【SpringBoot+Vue】全网最简单但实用的前后端分离项目实战笔记 - 后端。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

配套视频地址:https://www.bilibili.com/video/BV1dG4y1T7yp/

如果您需要原版笔记,请up喝口水,可以上我的淘宝小店 青菜开发资料 购买,或点击下方链接直接购买:
源码+PDF版本笔记
源码+原始MD版本笔记

感谢支持!

后端

1. 项目初始化

  1. 创建springboot项目:2.7.8

  2. pom依赖

    <!-- web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- mysql -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
    </dependency>
    <!-- mybatis-plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.5.2</version>
    </dependency>
    <!-- freemarker -->
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
    </dependency>
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    
  3. yml

    server:
      port: 9999
    
    spring:
      datasource:
        username: root
        password: 123456
        url: jdbc:mysql:///xdb
    
    logging:
      level:
        com.lantu: debug
    
  4. 测试

2. Mybatis-plus代码生成

  1. 编写代码生成器

    public static void main(String[] args) {
            String url = "jdbc:mysql:///xdb";
            String username = "root";
            String password = "123456";
            String author = "laocai";
            String outputDir = "D:\\tmp\\spring\\x-admin\\src\\main\\java";
            String basePackage = "com.lantu";
            String moduleName = "sys";
            String mapperLocation = "D:\\tmp\\spring\\x-admin\\src\\main\\resources\\mapper\\" + moduleName;
            String tableName = "x_user,x_menu,x_role,x_role_menu,x_user_role";
            String tablePrefix = "x_";
            FastAutoGenerator.create(url, username, password)
                    .globalConfig(builder -> {
                        builder.author(author) // 设置作者
                                .enableSwagger() // 开启 swagger 模式
                                //.fileOverride() // 覆盖已生成文件
                                .outputDir(outputDir); // 指定输出目录
                    })
                    .packageConfig(builder -> {
                        builder.parent(basePackage) // 设置父包名
                                .moduleName(moduleName) // 设置父包模块名
                                .pathInfo(Collections.singletonMap(OutputFile.xml, mapperLocation)); // 设置mapperXml生成路径
                    })
                    .strategyConfig(builder -> {
                        builder.addInclude(tableName) // 设置需要生成的表名
                                .addTablePrefix(tablePrefix); // 设置过滤表前缀
                    })
                    .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                    .execute();
        }
    
  2. 启动类加注解

    @MapperScan("com.lantu.*.mapper")
    
  3. 测试

3. 公共响应类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
    private Integer code;
    private String message;
    private T data;

    public static<T>  Result<T> success(){
        return new Result<>(20000,"success",null);
    }

    public static<T>  Result<T> success(T data){
        return new Result<>(20000,"success",data);
    }

    public static<T>  Result<T> success(T data, String message){
        return new Result<>(20000,message,data);
    }

    public static<T>  Result<T> success(String message){
        return new Result<>(20000,message,null);
    }

    public static<T>  Result<T> fail(){
        return new Result<>(20001,"fail",null);
    }

    public static<T>  Result<T> fail(Integer code){
        return new Result<>(code,"fail",null);
    }

    public static<T>  Result<T> fail(Integer code, String message){
        return new Result<>(code,message,null);
    }

    public static<T>  Result<T> fail( String message){
        return new Result<>(20001,message,null);
    }

}

4. 登录相关接口

4.1 登录

接口属性
url /user/login
method post
请求参数 username
password
返回参数 【SpringBoot+Vue】全网最简单但实用的前后端分离项目实战笔记 - 后端

controller

@PostMapping("/login")
public Result<Map<String,Object>> login(@RequestBody User user){
    Map<String,Object> data = userService.login(user);
    if(data != null){
        return Result.success(data);
    }
    return Result.fail(20002,"用户名或密码错误");
}

service

public Map<String, Object> login(User user) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper();
    wrapper.eq(User::getUsername,user.getUsername());
    wrapper.eq(User::getPassword,user.getPassword());
    User loginUser = this.getOne(wrapper);
    if(loginUser != null){
        Map<String, Object> data = new HashMap<>();
        String key = "user::" + UUID.randomUUID();
        data.put("token", key);    // 待优化,最终方案jwt
        loginUser.setPassword(null);
        redisTemplate.opsForValue().set(key,loginUser,30, TimeUnit.MINUTES);
        return data;
    }
    return null;
}

整合redis

  1. pom

    <!-- redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. yml

    spring:
      redis:
        host: localhost
        port: 6379
    
  3. 配置类

    @Configuration
    public class MyRedisConfig {
        @Resource
        private RedisConnectionFactory factory;
    
        @Bean
        public RedisTemplate redisTemplate(){
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(factory);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
    
            Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
            redisTemplate.setValueSerializer(serializer);
    
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
            om.setTimeZone(TimeZone.getDefault());
            om.configure(MapperFeature.USE_ANNOTATIONS, false);
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            om.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
            om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
            om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            serializer.setObjectMapper(om);
    
            return redisTemplate;
        }
    }
    

4.2 获取用户信息

接口属性
url /user/info?token=xxx
method get
请求参数 token
返回参数 【SpringBoot+Vue】全网最简单但实用的前后端分离项目实战笔记 - 后端

controller

@GetMapping("/info")
    public Result<?> getUserInfo(@Param("token") String token){
        Map<String,Object> data = userService.getUserInfo(token);
        if(data != null){
            return Result.success(data);
        }
        return Result.fail(20003,"用户信息获取失败");
    }

service

public Map<String, Object> getUserInfo(String token) {
    // 从redis查询token
    Object obj = redisTemplate.opsForValue().get(token);
    // 反序列化
    User user = JSON.parseObject(JSON.toJSONString(obj),User.class);
    if(user != null){
        Map<String, Object> data =  new HashMap<>();
        data.put("name",user.getUsername());
        data.put("avatar",user.getAvatar());
        List<String> roleList = this.getBaseMapper().getRoleNamesByUserId(user.getId());
        data.put("roles", roleList);
        return data;
    }
    return null;
}

mapper.xml

<select id="getRoleNamesByUserId" parameterType="Integer" resultType="String">
    SELECT
    b.role_name
    FROM x_user_role a,x_role b
    WHERE a.`user_id` = #{userId}
    AND a.`role_id` = b.`role_id`
</select>

4.3 注销

接口属性
url /user/logout
method post
请求参数
返回参数 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DwV5GD4c-1675952251553)(C:\Users\dacai\AppData\Roaming\Typora\typora-user-images\image-20230203171855151.png)]

controller

@PostMapping("/logout")
public Result<?> logout(@RequestHeader("X-Token") String token){
    userService.logout(token);
    return Result.success("注销成功");
}

service

public void logout(String token) {
    redisTemplate.delete(token);
}

6. 跨域处理

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter(){
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //1) 允许的域,不要写*,否则cookie就无法使用了
        config.addAllowedOrigin("http://localhost:8888"); //这里填写请求的前端服务器
        //2) 是否发送Cookie信息
        config.setAllowCredentials(true);
        //3) 允许的请求方式
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        // 4)允许的头信息
        config.addAllowedHeader("*");

        //2.添加映射路径,我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        //3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}

7. 用户管理接口

接口 说明
查询用户列表 分页查询
新增用户
根据id查询用户
修改用户
删除用户 逻辑删除

7.1 查询用户列表

  1. controller

    @GetMapping("/list")
    public Result<?> getUserListPage(@RequestParam(value = "username", required = false) String username,
                                     @RequestParam(value = "phone", required = false) String phone,
                                     @RequestParam("pageNo") Long pageNo,
                                     @RequestParam("pageSize") Long pageSize) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper();
        wrapper.eq(username != null, User::getUsername, username);
        wrapper.eq(phone != null, User::getPhone, phone);
        Page<User> page = new Page<>(pageNo, pageSize);
        userService.page(page, wrapper);
    
        Map<String, Object> data = new HashMap<>();
        data.put("total", page.getTotal());
        data.put("rows", page.getRecords());
    
        return Result.success(data);
    }
    
  2. 分页拦截器

    @Configuration
    public class MpConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
    }
    

7.2 新增用户

密码加密处理,用BCryptPasswordEncoder,涉及登录逻辑改动

7.3 修改用户

此处不提供密码更新,大家自行扩展,可以去实现前端右上角菜单的个人信息功能

7.4 删除用户

利用MyBatisPlus做逻辑删除处理文章来源地址https://www.toymoban.com/news/detail-444856.html

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: delete
      logic-delete-value: 1
      logic-not-delete-value: 0

到了这里,关于【SpringBoot+Vue】全网最简单但实用的前后端分离项目实战笔记 - 后端的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于SpringBoot+SpringCloud+Vue前后端分离项目实战 --开篇

    如何高效学习Java? 毕业设计项目应该怎么做?入门实战项目应该怎么做? 做Java开发都应该学习哪些框架技术?到底应该往哪个方向努力? 📢 这是专栏的第一篇文章,我想来跟你聊聊 为什么要学习此专栏 ?我们经常说,看一个事儿千万不要直接陷入细节里,你应该 先鸟瞰

    2024年02月03日
    浏览(48)
  • SpringBoot + Vue前后端分离项目实战 || 五:用户管理功能后续

    系列文章: SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计 SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接 SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接 SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现 SpringBoot + Vue前后

    2024年02月16日
    浏览(68)
  • SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现

    系列文章: SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计 SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接 SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接 SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现 SpringBoot + Vue前后

    2024年02月11日
    浏览(59)
  • SpringBoot + Vue前后端分离项目实战 || 六:Jwt加密整合配置

    在之前的系统中,我们利用 UUID 配合 Redis 以达到角色登录的功能。 当前整个系统存在一个问题:人为 修改token值 后,用户仍然能在前端进行数据库操作,后台没有校验当前用户 token 就允许一些请求,导致系统存在 安全漏洞 。 解决方法: Jwt签名验证 。整合 Jwt 后,前端发

    2024年02月15日
    浏览(48)
  • SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接

    系列文章: SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计 SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接 SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接 SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现 SpringBoot + Vue前后

    2024年02月12日
    浏览(71)
  • 【Docker】docker部署springboot+vue+mysql+nginx前后端分离项目【部署实战篇】

    安装docker: https://blog.csdn.net/qq_39900031/article/details/121666892 springboot-vue前后端分离项目:https://gitee.com/ma-haojie/springboot-vue-demo.git https://jackwei.blog.csdn.net/article/details/110227719 或者 --restart=always 参数能够使我们 在重启docker时,自动启动相关容器 。 Docker容器的重启策略如下: no,默认

    2024年02月13日
    浏览(49)
  • 【项目实战】手把手教你搭建前后端分离项目 SpringBoot + Vue + Element UI + Mysql

    👉 博主介绍 : 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO TOP红人 Java知识图谱点击链接: 体系化学习Java(Java面试专题) 💕💕 感兴趣的同学可以收藏关注下 , 不然下次找不到哟

    2024年02月16日
    浏览(57)
  • SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接

    系列文章: SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计 SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接 SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接 SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现 SpringBoot + Vue前后

    2024年02月11日
    浏览(66)
  • Vue加SpringBoot实现项目前后端分离

    首先需要搭建一个Vue的脚手架项目(已经放在gitee里面了,下面是gitee网址,可以直接拉) (vue-web: 这个是Vue项目模板,没有后台数据) 那么接下来就是实现前后端分离的步骤 首先我们需要有一个登录页面 登录的点击事件利用axios提交到后台去,代码放在后面(没有样式也可以

    2024年02月06日
    浏览(57)
  • SpringBoot+Vue前后端分离项目国际化支持

    i18n.js文件 language.en_US.js文件 language.zh_CN.js文件 messages_en_US.properties文件 messages_zh_CN.properties文件

    2024年02月04日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包