spingboot

SpringBoot+Gradle+ MyBatisPlus3.

2020-08-16  本文已影响0人  爱学习的蹭蹭

1、技术选型

2、Spring Boot 发展路线简要描述

3 SpringBoot插件使用

4、fastJson

5、Hutool

6、Gradle

7、工程结构

结构图1 结构图2

8、Gradle配置

plugins {
    id 'java'
    id 'idea'
}

/**
 * 使用Groovy语言语法定义版本号变量
 */
def spring_boot_version = "2.1.5.RELEASE"
def mybatis_plus_version = "3.1.2"
def mysql_version = "8.0.21"
def druid_version = "1.1.23"
def logback_version = "1.2.1"
def fastjson_version = "1.2.73"
def lombok_version = "1.18.12"
def lang_version = "3.4"
def io_version = "2.6"
def guava_version = "18.0"
def hutool_version = "5.3.10"

group = 'com.flong'
version = '0.0.1-SNAPSHOT'

//jdk版本
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

repositories {
    //指定阿里云镜像
    maven {
        url 'http://maven.aliyun.com/nexus/content/groups/public/'
    }
    mavenLocal()
    mavenCentral()
}

/**
 * 1、implementation 履行 、compile 编译
 * 2、Gradle使用双引号可 ${变量}可以放入引号里面,单引号是不可以的。
 * 3、Gragle使用lombok需要引入annotationProcessor注解,否则不能使用lombok.
 * 4、mybatis-plus3.2.x以上版本引用了Kotlin的支持
 * 5、高版本Springboogt在spring-boot-dependencies-2.3.0.RELEASE.pom里面引入了mysql8.0.2的`<mysql.version>8.0.20</mysql.version>`配置
 */
dependencies {

    implementation "org.springframework.boot:spring-boot-starter:${spring_boot_version}"
    //排除tomcat使用undertow
    compile("org.springframework.boot:spring-boot-starter-web:${spring_boot_version}") {
        exclude module: "spring-boot-starter-tomcat"
    }
    compile "org.springframework.boot:spring-boot-starter-undertow:${spring_boot_version}"

    //runtime group: 'mysql', name: 'mysql-connector-java', version: '5.1.42'
    compile "org.springframework.boot:spring-boot-devtools:${spring_boot_version}"
    compile "org.springframework.boot:spring-boot-configuration-processor:${spring_boot_version}"
    compile "org.springframework.boot:spring-boot-starter-test:${spring_boot_version}"
    compile "com.baomidou:mybatis-plus-extension:${mybatis_plus_version}"
    compile "com.baomidou:mybatis-plus-boot-starter:${mybatis_plus_version}"
    compile "mysql:mysql-connector-java:${mysql_version}"
    compile "com.alibaba:druid:${druid_version}"
    compile "ch.qos.logback:logback-classic:${logback_version}"
    compile "com.alibaba:fastjson:${fastjson_version}"
    annotationProcessor "org.projectlombok:lombok:${lombok_version}"
    compileOnly "org.projectlombok:lombok:${lombok_version}"
    //testAnnotationProcessor "org.projectlombok:lombok:${lombok_version}"
    //testCompileOnly "org.projectlombok:lombok:${lombok_version}"
    compile "org.apache.commons:commons-lang3:${lang_version}"
    compile "commons-io:commons-io:${io_version}"
    compile "com.google.guava:guava:${guava_version}"
    compile  "cn.hutool:hutool-all:${hutool_version}"
}

tasks.withType(JavaCompile) {
    options.encoding = "UTF-8"
}

[compileJava, javadoc, compileTestJava]*.options*.encoding = "UTF-8"

9、数据库SQL脚本

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `user_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用户Id主键,IdWork生成',
  `user_name` varchar(255) DEFAULT '' COMMENT '用户名',
  `pass_word` varchar(255) DEFAULT '' COMMENT '密码',
  `del_flag` int(2) unsigned NOT NULL DEFAULT '0' COMMENT '是否删除,0-不删除,1-删除',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`user_id`) USING BTREE,
  UNIQUE KEY `id` (`id`)USING BTREE
)ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

10、SpringBoot与MyBatisPlus3整合分页代码

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}  

11、SpringBoot与MyBatisPlus3分页条件组装器

package com.flong.springboot.core.util;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.flong.springboot.core.vo.Condition;

import java.lang.reflect.Field;
import java.util.List;

import com.flong.springboot.core.enums.JoinType;
import com.flong.springboot.core.exception.BaseException;

/**
 * 将condition数据转换成wrapper
 */
public class BuildConditionWrapper {

    public static <T> QueryWrapper<T> build(List<Condition> conditions, Class<T> clazz) {
        //初始化mybatis条件构造器
        QueryWrapper wrapper = Wrappers.query();
        if (conditions == null || conditions.size() == 0) {
            return wrapper;
        }
        try {
            for (int i = 0; i < conditions.size(); i++) {
                Condition condition = conditions.get(i);

                if (condition.getFieldName() == null) {
                    throw new BaseException("调用搜索接口时,缺少关键字[fieldName]!");
                }
                //列名称
                String columnName = getColumnName(condition.getFieldName(), clazz);

                if (condition == null || condition.getOperation() == null) {
                    throw new BaseException("操作符不能为空!");
                }

                switch (condition.getOperation()) {
                    //等于
                    case EQ:
                        wrapper.eq(columnName, condition.getValue());
                        break;
                    //大于
                    case GT:
                        wrapper.gt(columnName, condition.getValue());
                        break;
                    //小于
                    case LT:
                        wrapper.lt(columnName, condition.getValue());
                        break;
                    //不等于
                    case NEQ:
                        wrapper.ne(columnName, condition.getValue());
                        break;
                    //大于等于
                    case GTANDEQ:
                        wrapper.ge(columnName, condition.getValue());
                        break;
                    //小于等于
                    case LTANDEQ:
                        wrapper.le(columnName, condition.getValue());
                        break;
                    case LIKE:
                        wrapper.like(columnName, condition.getValue());
                        break;
                    case ISNULL:
                        wrapper.isNull(columnName);
                        break;
                    case IN:
                        //value :1,2,3,4,5,6
                        wrapper.inSql(columnName, condition.getValue());
                        break;
                    default:
                        break;
                }
                if (condition.getJoinType() == JoinType.OR && i < conditions.size() - 1) {
                    //下个条件为or连接且非最后一个条件,使用or进行连接
                    wrapper.or();
                }
            }
            return wrapper;
        } catch (Exception e) {
            throw new BaseException("查询条件不存在");
        }
    }

    /**
     * @Descript 此条件构建包装器方法是支持多个表组装成SQL字段的虚拟表,不支持实际存在的表
     * @Date 2019/6/21 13:32
     * @Author liangjl
     */
    public static <T> QueryWrapper<T> buildWarpper(List<Condition> conditions) {
        //初始化mybatis条件构造器
        QueryWrapper wrapper = Wrappers.query();
        if (conditions == null || conditions.size() == 0) {
            return wrapper;
        }
        try {
            for (int i = 0; i < conditions.size(); i++) {
                Condition condition = conditions.get(i);
                if (condition.getFieldName() == null) {
                    throw new BaseException("调用搜索接口时,缺少关键字[fieldName]!");
                }
                //列名称
                String columnName = condition.getFieldName();
                if (condition == null || condition.getOperation() == null) {
                    throw new BaseException("操作符不能为空!");
                }
                switch (condition.getOperation()) {
                    //等于
                    case EQ:
                        wrapper.eq(columnName, condition.getValue());
                        break;
                    //大于
                    case GT:
                        wrapper.gt(columnName, condition.getValue());
                        break;
                    //小于
                    case LT:
                        wrapper.lt(columnName, condition.getValue());
                        break;
                    //不等于
                    case NEQ:
                        wrapper.ne(columnName, condition.getValue());
                        break;
                    //大于等于
                    case GTANDEQ:
                        wrapper.ge(columnName, condition.getValue());
                        break;
                    //小于等于
                    case LTANDEQ:
                        wrapper.le(columnName, condition.getValue());
                        break;
                    case LIKE:
                        wrapper.like(columnName, condition.getValue());
                        break;
                    case IN:
                        //value :1,2,3,4,5,6
                        wrapper.inSql(columnName, condition.getValue());
                        break;
                    default:
                        break;
                }
                if (condition.getJoinType() == JoinType.OR && i < conditions.size() - 1) {
                    //下个条件为or连接且非最后一个条件,使用or进行连接
                    wrapper.or();
                }
            }
            return wrapper;
        } catch (Exception e) {
            throw new BaseException("查询条件不存在");
        }
    }

    /***
     * @Descript 获取指定实体Bean的字段属性
     * @Date 2019/6/19 14:51
     * @Author liangjl
     */
    public static String getColumnName(String fieldName, Class clazz) {
        try {
            //获取泛型类型字段
            Field field = clazz.getDeclaredField(fieldName);
            TableField tableFieldAnno = field.getAnnotation(TableField.class);
            String columnName = "";
            //获取对应数据库字段
            if (tableFieldAnno != null && StrUtil.isNotBlank(tableFieldAnno.value())) {
                //已定义数据库字段,取定义值
                columnName = tableFieldAnno.value();
            } else {
                //未指定数据库字段,默认驼峰转下划线
                columnName = NamingStrategyUtils.camelToUnderline(field.getName());
            }
            return columnName;
        } catch (NoSuchFieldException e) {
            throw new BaseException("查询条件不存在");
        }
    }

}

12、 实体


import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.*;

import java.io.Serializable;
import java.util.Date;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper=false)
@TableName("t_user")
public class User extends Model<User> implements Serializable {

    @TableId(type = IdType.ID_WORKER)
    private Long userId;

    /**
     * 用户名
     */

    private String userName;
    /**
     * 密码
     */
    private String passWord;
    /**
     * 逻辑删除(0-未删除,1-已删除)
     */
    @TableLogic
    private String delFlag;

    /**
     * 创建时间,允许为空,让数据库自动生成即可
     */
    private Date createTime;
}

13、 Mapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.flong.springboot.modules.entity.User;

public interface UserMapper extends BaseMapper<User> {

}

14、 Service


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.flong.springboot.modules.entity.User;
import com.flong.springboot.modules.mapper.UserMapper;
import org.springframework.stereotype.Service;

@Service
public class UserService extends ServiceImpl<UserMapper, User> {

}

15 、controller

package com.flong.springboot.modules.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flong.springboot.modules.entity.User;
import com.flong.springboot.modules.mapper.UserMapper;
import com.flong.springboot.modules.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.flong.springboot.core.vo.Conditions;
import com.flong.springboot.core.util.BuildConditionWrapper;

import java.util.List;

/**
 * @Author:liangjl
 * @Date:2020-08-16
 * @Description:用户控制层
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

    /**
     * 添加
     */
    @RequestMapping("/add")
    public void add() {
        userMapper.insert(User.builder().userName("周伯通").passWord("123456").build());
    }

    /**
     * 修改
     * @param user
     */
    @PutMapping("/updateById")
    public void updateById(@RequestBody User user) {
        userMapper.updateById(user);
    }
    /**
     * 删除通过多个主键Id进行删除
     * @param ids
     */
    @DeleteMapping("/deleteByIds")
    public void deleteByIds(@RequestBody List<String> ids) {
        userMapper.deleteBatchIds(ids);
    }

    /**
     * 通过指定Id进行查询
     *
     * @param userId
     */
    @GetMapping("/getOne/{userId}")
    public void getOne(@PathVariable("userId") Long userId) {
        User user = userMapper.selectById(userId);
        System.out.println(JSON.toJSON(user));

    }

    /**
     * 用户分页,参数有多个使用下标索引进行处理.如果有两个参数(如用户名和地址):conditionList[0].fieldName=userName、 conditionList[0].fieldName=address
     * 未转码请求分页地址: http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=周
     * 已转码请求分页地址: http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=%E5%91%A8
     * @param page
     * @param conditions 条件
     * @return
     */
    @GetMapping("/page")
    public IPage<User> page(Page page, Conditions conditions) {
        QueryWrapper<User> build = BuildConditionWrapper.build(conditions.getConditionList(), User.class);
        //通过lambda反射找到User实体类的createTime自动进行排序
        build.lambda().orderByDesc(User::getCreateTime);
        return userService.page(page, build);
    }

}

16、WebCofig工具类统一处理配置


@Configuration
@ConditionalOnClass(WebMvcConfigurer.class)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class WebConfig implements WebMvcConfigurer {

  @Bean
  public HttpMessageConverters customConverters() {
    //创建fastJson消息转换器
    FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
    //创建配置类
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    //修改配置返回内容的过滤
    fastJsonConfig.setSerializerFeatures(
        // 格式化
        SerializerFeature.PrettyFormat,
        // 可解决long精度丢失 但会有带来相应的中文问题
        //SerializerFeature.BrowserCompatible,
        // 消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
        SerializerFeature.DisableCircularReferenceDetect,
        // 是否输出值为null的字段,默认为false
        SerializerFeature.WriteMapNullValue,
        // 字符类型字段如果为null,输出为"",而非null
        SerializerFeature.WriteNullStringAsEmpty,
        // List字段如果为null,输出为[],而非null
        SerializerFeature.WriteNullListAsEmpty
    );
    // 日期格式
    fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
    // long精度问题
    SerializeConfig serializeConfig = SerializeConfig.globalInstance;
    serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
    serializeConfig.put(Long.class, ToStringSerializer.instance);
    serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
    fastJsonConfig.setSerializeConfig(serializeConfig);
    //处理中文乱码问题
    List<MediaType> fastMediaTypes = new ArrayList<>();
    fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
    fastJsonConverter.setSupportedMediaTypes(fastMediaTypes);
    fastJsonConverter.setFastJsonConfig(fastJsonConfig);
    //将fastjson添加到视图消息转换器列表内
    return new HttpMessageConverters(fastJsonConverter);
  }

  /**
   * 拦截器
   */
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    //registry.addInterceptor(logInterceptor).addPathPatterns("/**");
    //registry.addInterceptor(apiInterceptor).addPathPatterns("/**");
  }

  /**
   * cors 跨域支持 可以用@CrossOrigin在controller上单独设置
   */
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
        //设置允许跨域请求的域名
        .allowedOrigins("*")
        //设置允许的方法
        .allowedMethods("*")
        //设置允许的头信息
        .allowedHeaders("*")
        //是否允许证书 不再默认开启
        .allowCredentials(Boolean.TRUE);
  }
}

17、运行结果

add 分页.png

18、工程代码与说明

上一篇 下一篇

猜你喜欢

热点阅读