Vue学习第四天(9月7号)

前后端分离开发之Rest风格的后端数据接口工程

  1. 后端工程的pom文件

<!--springboot工程web开发启动器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatisplus开发启动器-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>
<!--devtools热启动工具(修改Java代码后无需重启, 只需maven编译即可)-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>
<!--mysql驱动包, 降低版本到5.1.47-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
    <scope>runtime</scope>
</dependency>
<!--lombok (实体类注解, @Sl4j日志注解)-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<!--jwt (创建和校验token令牌)-->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
</dependency>
<!--springboot单元测试依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

  1. 后端工程的application.properties配置文件

application.properties

spring.application.name=back
spring.profiles.active=dev
logging.config=classpath:log.xml

application-dev.properties

server.port=8888
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.name=defaultDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.type-aliases-package=com.example.back.entity
mybatis-plus.configuration.auto-mapping-behavior=full

application-prod.properties


  1. 准备日志的配置文件

  1. 创建工程子包

创建在src/main/java/com.example.shopback中

  1. config (配置类包)

  2. controller (控制器包)

  3. entity (实体类包)

  4. exception (全局异常处理包)

  5. interceptor (拦截器包)

  6. mapper (mybatisplus接管的mapper层接口包)

  7. page (自定义的分页器包)

  8. response (自定义的统一返回数据格式包)

  9. service (业务层包)

  10. util (工具包)

创建在src/main/resources中

mapper (用来编写SQL语句的mapper.xml文件目录)

添加src/main/resources目录中的xml文件打包的配置

<build>
    ..........
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
    </resources>
</build>

  1. 创建配置类

创建MyBatisPlusConfig配置类

这个配置类的作用是配置分页的时候SQL语句使用MySQL的limit语法

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

创建CrossOriginConfig跨域配置类

@Configuration
public class CrossOriginConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowCredentials(true);
        WebMvcConfigurer.super.addCorsMappings(registry);
    }
}

创建InterceptorConfig拦截器配置类

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        
    }
}

  1. 创建统一返回数据相关类

创建响应信息枚举类ResponseMsg

信息代码code和信息内容msg参考了《阿里巴巴开发手册》

枚举类型ResponseMsg可以作为变量的数据类型

SUCCESS("000000", "一切ok") 这行代码等同于

public static final ResponseMsg SUCCESS = new ResponseMsg("000000", "一切ok");

public enum ResponseMsg {
    SUCCESS("000000", "一切ok"),
    USER_ALREADY_EXIST("A0111","用户名已存在"),
    USER_NOT_EXIST("A0201","用户账户不存在"),
    PASSWORD_ERROR("A0210","用户密码错误"),
    TOKEN_ERROR("A0220","用户令牌失效"),
    SYSTEM_ERROR("B0001","系统执行出错"),
    DATABASE_ERROR("C0300","数据库服务出错");

    private String code;
    private String msg;

    ResponseMsg(String code, String msg){
        this.code = code;
        this.msg = msg;
    }

    public String getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

创建统一响应数据封装类ResponseData

这个类用于Rest风格的控制器中方法的返回值类型

也就是说所有的Rest风格的控制器中的方法全部统一返回ResponseData类型

因为Rest风格的控制器不做转发和重定向,只需返回json格式的数据给前端的ajax

这个相对于用ResponseData类统一了json数据的格式

该类有三个成员变量

code 信息代码

msg 信息内容

data 响应数据

该类有两个静态方法

success() 接收一个Object类型的任意对象作为参数(改参数就是返回的数据), 返回一个请求成功的结果, 携带数据, json格式大概是这样的

{
    "code": "000000",
    "msg" "一切ok",
    "data": 任意类型的数据
}

failure() 接收一个枚举类型ResponseMsg作为参数(该类型包含code和msg), 返回一个请求失败的结果, 携带错误信息, json格式大概是这样的

{
    "code": 枚举的任意信息代码,
    "msg" 枚举的任意信息内容
}

@Data
public class ResponseData {
    private String code;
    private String msg;
    private Object data;
    public static ResponseData success(Object data){
        ResponseData responseData = new ResponseData();
        responseData.setCode(ResponseMsg.SUCCESS.getCode());
        responseData.setMsg(ResponseMsg.SUCCESS.getMsg());
        responseData.setData(data);
        return responseData;
    }
    public static ResponseData failure (ResponseMsg responseMsg){
        ResponseData responseData = new ResponseData();
        responseData.setCode(responseMsg.getCode());
        responseData.setMsg(responseMsg.getMsg());
        return responseData;
    }
}

创建统一的自定义运行时异常类CustomException

这个类中有一个ResponseMsg枚举类型的成员变量

提供构造方法和get方法

public class CustomException extends RuntimeException{
    private ResponseMsg responseMsg;
    public CustomException(ResponseMsg responseMsg){
        super(responseMsg.getCode() + ":" + responseMsg.getMsg());
        this.responseMsg = responseMsg;
    }
    public ResponseMsg getResponseMsg() {
        return responseMsg;
    }
}

  1. 创建统一的全局异常处理器类

这个类使用了@RestControllerAdvice注解, 该注解是基于AOP面向切面, 代理了全局任意地方的异常捕捉和处理, 也就说, 无论是娜个拦截器,控制器,Srevice,Mapper, ......中任何方法中出现了异常,都会被这个类捕捉到

那么有了这个全局异常处理器, 我们就可以优雅的处理程序中的异常, 不需要自己写try...catch

也不需要throws向上抛出

这个类中有两个方法

  1. customExceptionHandler() 这个方法用于捕捉和处理我们自定义的异常CustomException

  2. globalExceptionHandler() 这个方法用于捕捉和处理除了我们自定义的异常之外所有的其他异常

@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvice {
    @ExceptionHandler({CustomException.class})
    public ResponseData customExceptionHandler(CustomException e) {
        e.printStackTrace();
        return ResponseData.failure(e.getResponseMsg());
    }

    @ExceptionHandler({Exception.class})
    public ResponseData globalExceptionHandler(Exception e) {
        log.error(e.getMessage(), e);
        if (e instanceof SQLException){
            return ResponseData.failure(ResponseMsg.DATABASE_ERROR);
        }else {
            return ResponseData.failure(ResponseMsg.SYSTEM_ERROR);
        }
    }
}

  1. 创建用户身份令牌工具类TokenUtil

注意: 需要安装jwt依赖

需要有User实体类 (包含id和username属性即可)

public class TokenUtil {
    private static final String secret = "!A@B#F$G%K^U&E*L";
    private static Algorithm getAlg(){
        return Algorithm.HMAC256(secret);
    }
    public static String getToken(User user){
        System.out.println(user);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND,60 * 30);
        return JWT.create()
                .withClaim("id", user.getId())
                .withClaim("username", user.getUsername())
                .withExpiresAt(calendar.getTime())
                .sign(getAlg());
    }
    public static User verityToken(String token){
        User user = new User();
        DecodedJWT jwt = JWT.require(getAlg()).build().verify(token);
        user.setId(Integer.parseInt(jwt.getClaim("id").asString()));
        user.setUsername(jwt.getClaim("username").asString());
        return user;
    }
}

  1. 创建用户身份令牌拦截器类

public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        try {
            TokenUtil.verityToken(token);
        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException(ResponseMsg.TOKEN_ERROR);
        }
        return true;
    }
}

用户身份令牌拦截器类创建好以后, 要去拦截器配置类中配置一下拦截地址和放行地址

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TokenInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/user/login");
    }
}

  1. 创建实体类

BaseEntity 实体类父类

@Data
public class BaseEntity {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private Integer isDelete;
    private String createDate;
    private String modifyDate;
}

User 用户实体类继承BaseEntity

@Data
public class User extends BaseEntity{
    private String username;
    private String sex;
    private String mobile;
    private String idCode;
    private String avatar;
    private String password;
    private String idCardFront;
    private String idCardBack;
    @TableField(exist = false)
    private String token;
}

实体类中的命名与数据库表中的命名满足驼峰和全小写加_连字符的规范, 就不需要添加

@TableField注解进行名称映射,如果不满足规范,需要添加注解映射

其他实体类省略........

  1. 创建Mapper接口和Mapper.xml文件

UserMapper接口

public interface UserMapper extends BaseMapper<User> {
}

UserMapper.xml文件 (通过namespace与接口绑定)

<?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.example.back.mapper.UserMapper">
</mapper>

其他Mapper接口和Mapper.xml文件省略........

注意: 启动类上添加@MapperScan()注解

  1. 创建Srevice接口和ServiceImpl实现类

UserService接口

public interface UserService {
}

UserServiceImpl实现类

  1. 添加Service注解让IoC发现

  2. 添加@Resource注解注入userMapper对象

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
}

  1. 创建Rest风格的控制器类

UserController控制器类

  1. 前后端分离, 所有的控制器全部使用@RestController (前后端不分离使用@Controller)

  2. 所有的控制器类上使用@RequestMapper绑定的url地址, 全部以"/api"为前缀

例如, 用户控制器类的url是 "/api/user"

商品控制器类的url是 "/api/product"

api有两个意思:

  1. 某些三方库里面的接口,类可以称为 "xxx框架的API",或者官方JDK里面的接口,类可以称为"官方JDK API"

  2. 后端程序的请求地址,可以称为"xxx数据接口api"

这里说的api自然是第二种意思, 就是数据接口的意思

@RestController
@RequestMapping("/api/user")
public class UserController {
    @Resource
    private UserService userService;
}

其他控制器省略......

  1. 创建自定义的分页器类

UserPage分页器类

  1. 继承MyBatisPlus提供的Page分页器类

  2. 自定义成员变量, 用于接收查询参数

@Data
public class UserPage extends Page<User> {
    private String username;
    private String idCode;
    private String mobile;
}

其他分页器类省略.......

15. Postman API测试工具的使用

介绍

Postman是一款用于模拟http请求的工具,常用于测试后端数据接口

我们可以用Postman攻击古创建HTTP请求,并发送给后端接口,然后接受后端返回的结果,并展示,以此在前后端分离开发的模式下测试后端API接口

官网地址

Download Postman | Get Started for Free

找到Collections

Collections代表所有的测试项目的集合

找到New Collection

创建一个测试项目,Collection的名字可以设置为“shop-back后端API测试”

Collections里面可以创建多个Collection,一个Collection用于测试一个项目

Collection里面可以创建多个Request,一个Request对应一个Http请求测试

在当前的Collection里面找到Add Request

并给这个Request去一个名字为"测试/api/user/list接口", 当然, 懒人可以随意

Request面板

16. API接口文档

API接口文档是前后端程序员之间交流的凭据

一般情况下API接口文档会由后端程序员编写,然后写好后给前端程序员

前端程序员可以从API接口文档中得到以下信息

  1. 某个功能的数据接口的url地址是什么

  2. 请求方式是什么

  3. 需要携带什么请求参数,哪些是必须携带的,哪些不是必须携带的,不是必须携带的参数后端会给出什么样的默认值

  4. 后端响应的json数据格式是什么

基础的后端url地址

http://localhost:8888/api

多条件分页查询用户

url

/user/list

method

get

param

可选 current 默认1

可选 size 默认10

可选 username 默认null

可选 idCode 默认null

可选 mobile 默认null

response

{

"code": "000000",

"msg": "一切ok",

"data": page对象

}

后端响应的json数据合适

前端使用ajax请求后端,然后如果操作后端返回的数据
$.get("url", param, function(data){
    data.code 取出 "000000"
    data.msg 取出 "一切ok"
    data.data 取出分页器数据对象
    data.data.total 取出分区器对象中的 9992
    data.data.size 取出分区器对象中的 10
    data.data.current 取出分区器对象中的 1
    data.data.pages 取出分区器对象中的 1000
    data.data.records 取出分区器对象中的list (在前端相对于数组)
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!很高兴回答您关于学习Vue 3的问题。Vue 3是一种流行的JavaScript框架,用于构建用户界面。它具有许多令人兴奋的新特性和改进,可以让您更轻松地开发可维护和可扩展的应用程序。 如果您已经掌握了Vue 2,那么学习Vue 3将会比较容易。以下是您可以开始学习Vue 3的一些建议: 1. 先了解Vue 3的新特性:Vue 3引入了一些重要的变化,例如Composition API(组合式API)和Teleport(传送门),这些新特性可以提升您的开发效率和代码组织能力。阅读官方文档并了解这些新特性的用法和优势是一个不错的开始。 2. 尝试使用Vue CLI创建一个新项目Vue CLI是一个命令行工具,可以帮助您快速搭建Vue项目并提供一些常用的配置和插件。使用Vue CLI创建一个新项目可以让您更好地了解Vue 3的工作流程和项目结构。 3. 参考官方文档和教程:Vue官方文档提供了非常详细和完善的介绍,包括基础概念、API参考和实例等。您可以从官方文档学习Vue 3的核心知识。此外,还有许多优秀的在线教程和视频资源可供参考,可以帮助您更深入地理解Vue 3的用法和最佳实践。 4. 练习和实践:学习理论知识只是第一步,更重要的是将所学知识应用于实际项目。尝试编写一些小型的Vue 3应用程序,并逐渐增加复杂度。通过实践,您可以更好地理解Vue 3的各种概念和技术。 希望这些建议对您有所帮助!如果您有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值