目录
2.后端工程的application.properties配置文件
- <!--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>
- spring.application.name=back
- spring.profiles.active=dev
- logging.config=classpath:log.xml
- 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
创建在src/main/java/com.example.shopback中
config (配置类包)
controller (控制器包)
entity (实体类包)
exception (全局异常处理包)
interceptor (拦截器包)
mapper (mybatisplus接管的mapper层接口包)
page (自定义的分页器包)
response (自定义的统一返回数据格式包)
service (业务层包)
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>
这个配置类的作用是配置分页的时候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;
- }
- }
- @Configuration
- public class CrossOriginConfig implements WebMvcConfigurer {
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**")
- .allowedOrigins("*")
- .allowedHeaders("*")
- .allowedMethods("*")
- .allowCredentials(true);
- WebMvcConfigurer.super.addCorsMappings(registry);
- }
- }
- @Configuration
- public class InterceptorConfig implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
-
- }
- }
信息代码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;
- }
- }
这个类用于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;
- }
- }
这个类中有一个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;
- }
- }
这个类使用了@RestControllerAdvice注解, 该注解是基于AOP面向切面, 代理了全局任意地方的异常捕捉和处理, 也就说, 无论是娜个拦截器,控制器,Srevice,Mapper, ......中任何方法中出现了异常,都会被这个类捕捉到
那么有了这个全局异常处理器, 我们就可以优雅的处理程序中的异常, 不需要自己写try...catch
也不需要throws向上抛出
这个类中有两个方法
customExceptionHandler() 这个方法用于捕捉和处理我们自定义的异常CustomException
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);
- }
- }
- }
注意: 需要安装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;
- }
- }
- 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");
- }
- }
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注解进行名称映射,如果不满足规范,需要添加注解映射
其他实体类省略........
UserMapper接口
- public interface UserMapper extends BaseMapper<User> {
- }
UserMapper.xml文件 (通过namespace与接口绑定)
- "1.0" encoding="UTF-8" ?>
- 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()注解
UserService接口
- public interface UserService {
- }
UserServiceImpl实现类
添加Service注解让IoC发现
添加@Resource注解注入userMapper对象
- @Service
- public class UserServiceImpl implements UserService {
- @Resource
- private UserMapper userMapper;
- }
UserController控制器类
前后端分离, 所有的控制器全部使用@RestController (前后端不分离使用@Controller)
所有的控制器类上使用@RequestMapper绑定的url地址, 全部以"/api"为前缀
例如, 用户控制器类的url是 "/api/user"
商品控制器类的url是 "/api/product"
api有两个意思:
某些三方库里面的接口,类可以称为 "xxx框架的API",或者官方JDK里面的接口,类可以称为"官方JDK API"
后端程序的请求地址,可以称为"xxx数据接口api"
这里说的api自然是第二种意思, 就是数据接口的意思
- @RestController
- @RequestMapping("/api/user")
- public class UserController {
- @Resource
- private UserService userService;
- }
其他控制器省略......
UserPage分页器类
继承MyBatisPlus提供的Page分页器类
自定义成员变量, 用于接收查询参数
- @Data
- public class UserPage extends Page
{ - private String username;
- private String idCode;
- private String mobile;
- }
其他分页器类省略.......