后端开发基本步骤(未完成继续写中)

1.使用spring initializr创建项目

请添加图片描述

注意:然后低下提供的依赖可用可不用,先不用,后边Maven统一配置依赖,注意:不要用3.0, 3.0需要用java17, 所以使用2x版本
请添加图片描述

2.导入依赖

<!-- 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

如果没有yml就自己在资源包建造一个

请添加图片描述

server:
  port: 9999

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///xdb

logging:
  level:
    com.lantu: debug

注意: url: jdbc:mysql:///xdb 这里的第三个斜杠 代替了localhost (是一种简写)

4.Mybatis-plus代码生成

下面是一个例子,不过可以通用,
当然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>

    public static void main(String[] args) {
        String url = "jdbc:mysql:///xdb";
        String username = "root";
        String password = "123456";
        String author = "mu";
        String outputDir = "D:\\Code\\x-admin\\src\\main\\java";
        String basePackage = "com.mu";
        String moduleName = "sys";
        String mapperLocation = "D:\\Code\\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();
    }

使用mybatisplus代码生成器问题

Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.1.0:exec (default-cli) on project x-admin: Command execution failed.

请添加图片描述

原因是因为,在官方的测试文档目录下
请添加图片描述
是禁止使用这种格式的代码的,标准格式应该是
请添加图片描述
和测试相关的函数
这个up解释的非常好,使用maven方式构建spring项目。在test里面创建了一个main方法测试IOC的基本使用。但是运行时候报错

快速解决方法,把他放进java,文件下去使用(用完之后删除,可以减少打包负担),要么按照up的方法改成test方法的函数,而不是main方法
请添加图片描述

4.1

如果mapper类上,没有注解,要在启动类上加一个扫描注解
请添加图片描述
请添加图片描述

5.写接口

注意返回数据是json用@RestController注解
请添加图片描述

5.1写一个结果返回类 或者叫做公共响应类

请添加图片描述

注解意思
@Data 生成get set 方法
@NoArgsConstructor 生成 无参构造方法
@AllArgsConstructor 生成 有参构造方法

@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);
    }


}

5.2 使用mybatis-plus的分页查询,要先配置mybatis-plus拦截器

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

5.3登录接口

请添加图片描述

controller

注意:这里可以先写controller层,虽然 service的login没写会报错,不用管,报错之后可以快速定位到没写的地方,可以直接生成代码架构然后再补充,更加方便

@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;
}

6.整合redis

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

  1. yml
spring:
  redis:
    host: localhost
    port: 6379

  1. 配置类
@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;
    }
}

7.获取用户信息

请添加图片描述

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>

8.注销

请添加图片描述
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);
}

9.跨域处理

这里注意,前后端都有跨域的处理方案,而且只用一端就行
这里是后端

@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);
    }
}

10.用户管理接口

请添加图片描述

10.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);
}

11.0分页拦截器

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

12.删除用户的逻辑删除

只需要配置一下mybatis-plus就行
然后再在数据库列里加上一个表示数据就行,例如 列名叫 delete 数据有 1 和0

logic-delete-field: delete 这个是列名
logic-delete-value: 1 删除时的值是
logic-not-delete-value: 0 没删除的值是

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

12.Swagger整合

Swagger-UI可以动态地根据注解生成在线API文档。

3.0比2更只能不用单个加注解,直接全显示

注意:可能会被jwt拦截器拦截,建议可以设置放行,不过在测试的时候可以以直接关闭jwt的拦截器,就把嘴上面的注解注释就行,不测试时再打开

常用注解

@Api:用于修饰Controller类,生成Controller相关文档信息
@ApiOperation:用于修饰Controller类中的方法,生成接口方法相关文档信息
@ApiParam:用于修饰接口中的参数,生成接口参数相关文档信息
@ApiModelProperty:用于修饰实体类的属性,当实体类是请求参数或返回结果时,直接生成相关文档信息
整合步骤:

添加依赖

<!--Swagger文档工具-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

swagger配置类

@Configuration
@EnableOpenApi
@EnableWebMvc
public class SwaggerConfig {
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.mu"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("神盾局特工管理系统接口文档")
                .description("全网最简单的SpringBoot+Vue前后端分离项目实战")
                .version("1.0")
                .contact(new Contact("qqcn", "http://www.qqcn.cn", "qqcn@aliyun.com"))
                .build();
    }
}

控制器根据需要添加swagger注解

测试:http://localhost:9999/swagger-ui/index.html

A1前端接口与后端关联调用流程

1首先前端写了一个点击按钮
请添加图片描述

请添加图片描述
2点击后调用

openEditUI函数

请添加图片描述

<script>
import userApi from "@/api/userManage";
export default {
  data() {
    return {
      formLabelWidth: "130px",
      userForm: {},
      dialogFormVisible: false,
      title: "",
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 10,
      },
      userList: [],
      rules: {
        username: [
          { required: true, message: "请输入用户名", trigger: "blur" },
          {
            min: 1,
            max: 50,
            message: "长度在 1 到 50 个字符",
            trigger: "blur",
          },
        ],
        password: [
          { required: true, message: "请输入初始密码", trigger: "blur" },
          {
            min: 1,
            max: 16,
            message: "长度在 1 到 16 个字符",
            trigger: "blur",
          },
        ],

        email: [{ required: true, message: "请输入电子邮件", trigger: "blur" }],
      },
    };
  },
  methods: {
    saveUser() {
      //触发验证
      this.$refs.userFormRef.validate((valid) => {
        if (valid) {
          //如果验证成功数据提交给后台

          //then(Response,回调后端返回的数据,前端已经把数据传给后端后,前端下一步该干什么
          userApi.addUser(this.userForm).then((Response) => {
            //成功提示
            this.$message({
              message: Response.message,
              type: "success",
            });
            //关闭对话框
              this.dialogFormVisible=false;
            //刷新显示表格
            this.getUserList();
          });
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
    cleraForm() {
      this.userForm = {};
      this.$refs.userFormRef.clearValidate();
    },
    openEditUI(id) {
      if (id==null) {
         this.title = "新增用户";
      }else{
        this.title = "修改用户";
        //根据用户id查询数据
        userApi.getUserById(id).then(Response =>{
          this.userForm=Response.data;
        })
      }
     
      this.dialogFormVisible = true;
    },
    handleSizeChange(pageSize) {
      this.searchModel.pageSize = pageSize;
      this.getUserList();
    },
    handleCurrentChange(pageNo) {
      this.searchModel.pageNo = pageNo;
      this.getUserList();
    },
    getUserList() {
      userApi.getUserList(this.searchModel).then((Response) => {
        this.userList = Response.data.rows;
        this.total = Response.data.total;
      });
    },
  },
  created() {
    this.getUserList();
  },
};
</script>

3前端输完数据,传给函数
请添加图片描述

请添加图片描述
请添加图片描述
请添加图片描述

userManage.js

import request from '@/utils/request'



export default {
  getUserList(searchModel) {
    return request({
      url: '/user/list',
      method: 'get',
      params: {
        pageNo: searchModel.pageNo,
        pageSize: searchModel.pageSize,
        username: searchModel.username,
        phone: searchModel.phone
      }
    });
  },
  addUser(user) {
    return request({
      url: '/user',
      method: 'post',
     data: user
    });
  },
  updateUser(user) {
    return request({
      url: '/user',
      method: 'put',
     data: user
    });
  },
  getUserById(id) {
    return request({
      url:`/user/${id}`,
      method: 'get'
    });
  },
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木心Fx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值