itliwei / mvcorm

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

##一、功能介绍

基于DDD模型,设计domain,自动生成数据库SQL脚本、DO、VO、Dao、Service、Controller以及基于ElementUI的前端页面与JS代码。 生成后,根据自己的业务需要修改调整对应的DO、VO以及Service、Controller逻辑。实现DDD设计模型,domain变更后,可重新生成,无任何影响。 让用户,解放双手,不需要做一些乏味的增删改查和实体定义,从而只关心自己的业务代码实现,提高生产力。

主要功能如下:

1、统一的代码架构规范

2、基于Springboot统一API日志输出

3、基于Springboot统一异常处理

4、基于Springboot、Swagger统一接口文档

5、基于Springboot统一返回结果响应码

6、Controller提供最基本的根据ID查询、分页条件查询、修改、新增、删除API

7、基于Mybatis自实现CORM框架,无需生成Mapper文件,提供基本SQL语句查询,也支持自定义SQL语句

8、数据库主从分离

##二、技术介绍

1、Springboot

2、SpringAOP

3、Spring Advice

4、Mybatis

5、Freemarker

##三、使用方式 1、引入jar包

<dependency>
    <groupId>io.github.itliwei</groupId>
    <artifactId>mvcorm-spring-boot-starter</artifactId>
    <version>0.0.2-RELEASE</version>
</dependency>

2、定义实体

package io.github.itliwei.mvcorm.entity;


import io.github.itliwei.mvcorm.generator.annotation.Field;
import io.github.itliwei.mvcorm.generator.annotation.Type;
import io.github.itliwei.mvcorm.generator.annotation.controller.ControllerClass;
import io.github.itliwei.mvcorm.generator.annotation.elementui.ElementClass;
import io.github.itliwei.mvcorm.generator.annotation.query.Query;
import io.github.itliwei.mvcorm.generator.annotation.query.QueryModel;
import io.github.itliwei.mvcorm.generator.annotation.service.ServiceClass;
import io.github.itliwei.mvcorm.generator.annotation.view.View;
import io.github.itliwei.mvcorm.generator.annotation.view.ViewObject;
import io.github.itliwei.mvcorm.orm.IdEntity;
import io.github.itliwei.mvcorm.orm.annotation.Table;
import io.github.itliwei.mvcorm.orm.opt.Condition;
import lombok.*;

import javax.persistence.Entity;

import static io.github.itliwei.mvcorm.entity.User.SIMPLE_DTO;
import static io.github.itliwei.mvcorm.entity.User.SIMPLE_VO;

/**
 * 用户表
 * Created by liwei on 17/9/14.
 */
@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Type(label = "用户")
@QueryModel
@Table(value = "tmp_user")
@ServiceClass
@ControllerClass(path = "api/user",desc = "用户接口")
@ElementClass
@ViewObject(groups = {SIMPLE_VO,SIMPLE_DTO})
public class User extends IdEntity {

    public static final String SIMPLE_VO = "ApplicationVo";

    public static final String SIMPLE_DTO = "ApplicationDto";

    @Field(label = "姓名")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO,SIMPLE_DTO})
    private String username;

    @Field(label = "jobId")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO})
    private Long jobId;

    @Field(label = "年龄")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO})
    private Integer age;

    @Field(label = "地址")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO})
    private String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Long getJobId() {
        return jobId;
    }

    public void setJobId(Long jobId) {
        this.jobId = jobId;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", jobId=" + jobId +
                "} " + super.toString();
    }
}

注解介绍:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
以上5个为lombok注解,无需过多介绍

@Entity
@Type(label = "用户")
@Table(value = "tmp_user")
这三个为基本注解,主要是用来生成mapper,生成数据库

@QueryModel
生成queryModel对象
@ViewObject(groups = {SIMPLE_VO,SIMPLE_DTO})
生成基本的VO(viewObject 视图层对象)Dto(Data Transiation Objece 数据转化对象) 
@ServiceClass
生成service,继承baseService,提供基本的增删改查,只生成一次
@ControllerClass(path = "api/user",desc = "用户接口")
生成controller,提供基本的增删改查接口,只生成一次
@ElementClass
生成ElementUi的基本文件,配合elementUi Template(暂未上传)使用

3、定义generator的main方法

package io.github.itliwei;

import io.github.itliwei.mvcorm.generator.generator.Config;
import io.github.itliwei.mvcorm.generator.generator.Generator;
import io.github.itliwei.mvcorm.generator.generator.handler.*;

import java.io.File;
import java.nio.file.Paths;

/**
 * @author : liwei
 * @date : 2019/05/21 21:50
 */
public class GeneratorTest {
    private static final String S = File.separator;

    public static void main(String[] args) {
        String projectPath = new File("").getAbsolutePath();
        Config config = new Config();
        //定义的实体对象的路径,会扫描该路径下的文件
        config.setEntityPackage("io.github.itliwei.mvcorm.entity");
        config.setGenLogFile(Paths.get(System.getProperty("user.home"), "gen.log").toString());
        //数据库相关配置,如果不反向生成数据库表,可无需
        config.setUrl("jdbc:mysql://127.0.0.1:3306/test?useSSL=false");

        config.setUsername("root");
        config.setPassword("root");
        config.setUseLombok(true);

        config.setElementPackage("/Users/vince/myproject/mvcorm/vue");
        config.setElementPath("/Users/vince/myproject/mvcorm/vue");

        Generator.generate(config
              , new VoHandler()
                , new QueryModelHandler()
                , new ServiceHandler()
                , new ControllerHandler()
                , new ElementHandler()
//               , new MysqlHandler(true) 
        );

    }
}

介绍:

VoHandler : 生成vo和dto
QueryModelHandler:生成querymodel
ServiceHandler:生成service
ControllerHandler:生成controller
ElementHandler:生成emement用的index,js
MysqlHandler:生成mysql数据库表结构

4、执行main方法

5、实例展示

1、定义实体

package io.github.itliwei.mvcorm.entity;


import io.github.itliwei.mvcorm.generator.annotation.Field;
import io.github.itliwei.mvcorm.generator.annotation.Type;
import io.github.itliwei.mvcorm.generator.annotation.controller.ControllerClass;
import io.github.itliwei.mvcorm.generator.annotation.elementui.ElementClass;
import io.github.itliwei.mvcorm.generator.annotation.query.Query;
import io.github.itliwei.mvcorm.generator.annotation.query.QueryModel;
import io.github.itliwei.mvcorm.generator.annotation.service.ServiceClass;
import io.github.itliwei.mvcorm.generator.annotation.view.View;
import io.github.itliwei.mvcorm.generator.annotation.view.ViewObject;
import io.github.itliwei.mvcorm.orm.IdEntity;
import io.github.itliwei.mvcorm.orm.annotation.Table;
import io.github.itliwei.mvcorm.orm.opt.Condition;
import lombok.*;

import javax.persistence.Entity;

import static io.github.itliwei.mvcorm.entity.User.SIMPLE_DTO;
import static io.github.itliwei.mvcorm.entity.User.SIMPLE_VO;

/**
 * 用户表
 * Created by liwei on 18/6/14.
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Type(label = "用户")
@Table(value = "tmp_user")
@QueryModel
@ServiceClass
@ControllerClass(path = "api/user",desc = "用户接口")
@ElementClass
@ViewObject(groups = {SIMPLE_VO,SIMPLE_DTO})
public class User extends IdEntity {

    public static final String SIMPLE_VO = "UserVo";

    public static final String SIMPLE_DTO = "UserDto";

    @Field(label = "姓名")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO,SIMPLE_DTO})
    private String username;

    @Field(label = "jobId")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO})
    private Long jobId;

    @Field(label = "年龄")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO})
    private Integer age;

    @Field(label = "地址")
    @Query({Condition.Operator.eq, Condition.Operator.in})
    @View(groups = {SIMPLE_VO})
    private String address;
}


2、手写GeneratorTest类
package io.github.itliwei;



import io.github.itliwei.mvcorm.generator.generator.Config;
import io.github.itliwei.mvcorm.generator.generator.Generator;
import io.github.itliwei.mvcorm.generator.generator.handler.*;

import java.io.File;
import java.nio.file.Paths;

/**
 * @author : liwei
 * @date : 2019/05/21 21:50
 */
public class GeneratorTest {
    private static final String S = File.separator;

    public static void main(String[] args) {
        String projectPath = new File("").getAbsolutePath();
        Config config = new Config();
        config.setGenLogFile(Paths.get(System.getProperty("user.home"), "gen.log").toString());
        config.setUrl("jdbc:mysql://106.13.146.82:3306/test?useSSL=false");
        config.setEntityPackage("io.github.itliwei.mvcorm.entity");

        config.setUsername("root");
        config.setPassword("Mysql2ol9");
        config.setUseLombok(true);

        config.setElementPackage("/Users/vince/myproject/mvcorm/vue");
        config.setElementPath("/Users/vince/myproject/mvcorm/vue");

        Generator.generate(config
                , new VoHandler()
                , new QueryModelHandler()
                , new ServiceHandler()
                , new ControllerHandler()
                , new ElementHandler()
//               , new MysqlHandler(true)//这里不再演示
        );

    }
}


3、执行main方法后的代码

VO对象

package io.github.itliwei.mvcorm.entity.vo;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import io.github.itliwei.mvcorm.generator.annotation.Field;


@Getter
@Setter
public class UserDto implements Serializable {
	@Field(label = "ID")
	private Long id;
	@Field(label = "姓名")
	private String username;


}

Dto对象

package io.github.itliwei.mvcorm.entity.vo;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import io.github.itliwei.mvcorm.generator.annotation.Field;


@Getter
@Setter
public class UserDto implements Serializable {
	@Field(label = "ID")
	private Long id;
	@Field(label = "姓名")
	private String username;


}

queryModel对象

package io.github.itliwei.mvcorm.entity.query;

import java.io.Serializable;

import io.github.itliwei.mvcorm.orm.opt.QueryModel;

import lombok.Getter;
import lombok.Setter;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserQueryModel  extends QueryModel implements Serializable {
	private Long idEQ;

	private String usernameEQ;

	private String usernameIN;

	private Long jobIdEQ;

	private Long jobIdIN;

	private Integer ageEQ;

	private Integer ageIN;

	private String addressEQ;

	private String addressIN;

}

service对象

package io.github.itliwei.mvcorm.service;


import io.github.itliwei.mvcorm.entity.*;
import io.github.itliwei.mvcorm.orm.BaseService;
import org.springframework.stereotype.Service;


@Service
public class UserService extends BaseService<User> {
}


controller对象

package io.github.itliwei.mvcorm.controller;


import io.github.itliwei.mvcorm.entity.*;
import org.springframework.beans.factory.annotation.Autowired;
import io.github.itliwei.mvcorm.mvc.Resp;
import io.github.itliwei.mvcorm.service.UserService;
import io.github.itliwei.mvcorm.entity.query.UserQueryModel;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;
import io.swagger.annotations.*;
import io.github.itliwei.mvcorm.orm.opt.Page;



@Slf4j
@RestController
@RequestMapping("api/user")
@Api(value = "用户接口",description = "用户接口")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/info/{id}")
    @ApiOperation(value = "根据ID查找",httpMethod = "GET")
    public Resp<User> getById(@PathVariable long id) {
        User result = userService.findById(id);
       return Resp.success(result);
    }


    @PostMapping("/page/query")
    @ApiOperation(value = "分页查找内容",httpMethod = "POST")
    public Resp<Page<User>> pageQuery(UserQueryModel queryModel) {
        Page<User> result = userService.findPage(queryModel);
        return Resp.success(result);
    }

    @PostMapping("/save")
    @ApiOperation(value = "保存",httpMethod = "POST")
    public Resp<User> save(User user) {
        User result = userService.save(user);
        return Resp.success(result);
    }

    @PostMapping("/update")
    @ApiOperation(value = "保存",httpMethod = "POST")
    public Resp<User> update(User user) {
        User result = userService.update(user);
        return Resp.success(result);
    }

    @GetMapping("/delete/{id}")
    @ApiOperation(value = "根据ID删除",httpMethod = "GET")
    public Resp<Integer> delete(@PathVariable long id) {
        int result = userService.delete(id);
        return Resp.success(result);
    }
}


Element文件

import request from '@/utils/request'

export function getList(params) {
    return request({
        url: '/page/query',
        method: 'POST',
        params
    })
}

export function getInfo(id) {
    return request({
        url: '/info/'+id,
        method: 'GET',
    })
}


export function update(params) {
    return request({
        url: '/update',
        method: 'POST',
        params
    })
}

export function add(params) {
    return request({
        url: '/add',
        method: 'POST',
        params
    })
}

export function del(id){
    return request({
        url: '/info/'+id,
        method: 'GET',
    })
}


<template>
    <div class="user-container">
        <el-col :span="24" class="toolbar">
            <el-form :inline="true" :model="userQueryModel"  size="mini">
                <el-form-item :span="6" label="姓名">
                    <el-input v-model="userQueryModel.username" placeholder=""></el-input>
                </el-form-item>
                <el-form-item :span="6" label="jobId">
                    <el-input v-model="userQueryModel.jobId" placeholder=""></el-input>
                </el-form-item>
                <el-form-item :span="6" label="年龄">
                    <el-input v-model="userQueryModel.age" placeholder=""></el-input>
                </el-form-item>
                <el-form-item :span="6" label="地址">
                    <el-input v-model="userQueryModel.address" placeholder=""></el-input>
                </el-form-item>
            <el-form-item :span="6" >
                <el-button type="primary" v-on:click="getList" size="mini">查询</el-button>
            </el-form-item>
            </el-form>
        </el-col>
        <div>
            <el-button type="danger" @click="addVisible=true" size="mini">添加</el-button>
        </div>

        <el-table :data="tableData" highlight-current-row v-loading="listLoading" style="width: 100%;" size="mini">
            <el-table-column type="index" width="50"></el-table-column>
                <el-table-column prop="username" label="姓名"></el-table-column>
                <el-table-column prop="jobId" label="jobId"></el-table-column>
                <el-table-column prop="age" label="年龄"></el-table-column>
                <el-table-column prop="address" label="地址"></el-table-column>
            <el-table-column
                    label="操作"
                    width="100">
                <template slot-scope="scope">
                    <el-button @click="getInfo(scope.row.id)" type="text" size="mini">查看</el-button>
                    <el-button @click="updateDialog(scope.row)" type="text" size="mini">修改</el-button>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination  style="float:right" background
                        @current-change="handleCurrentChange"
                        layout="prev, pager, next"
                        :total="total">
        </el-pagination>

        <el-dialog title="添加" :visible.sync="addVisible" >
            <el-form :model="userDtoAdd" label-width="80px" ref="addForm" :rules="addFormRules" size="mini">
                    <el-form-item label="姓名" prop="姓名">
                        <el-input v-model="userDtoAdd.username" ></el-input>
                    </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="handleClose('addForm')" size="mini">取 消</el-button>
                <el-button type="primary" @click="handlerSubmit('addForm')" size="mini">确 定</el-button>
            </div>
        </el-dialog>

        <el-dialog title="修改" :visible.sync="updateVisible" >
            <el-form :model="userDtoUpdate" label-width="80px" ref="form" :rules="updateFormRules">
                    <el-form-item label="姓名" prop="姓名">
                        <el-input v-model="userDtoUpdate.username" ></el-input>
                    </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="handleClose('updateForm')" size="mini">取 消</el-button>
                <el-button type="primary" @click="handlerSubmit('updateForm')" size="mini">确 定</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
    import { mapGetters } from 'vuex'
    import { Message, MessageBox } from 'element-ui'
    import {getInfo,add,update,delete,getList} from '@/api/user'
    import Axios from  'axios'

    const tableData = []
    export default {
        name: 'Org',
        data() {
            return {
                tableData,
                total : 0,
                addVisible: false,
                updateVisible: false,
                listLoading: false,
                userQueryModel:{
                    username,
                    jobId,
                    age,
                    address,
                    pageNumber: 1,
                    pageSize: 10,
                },
                userDtoAdd:{
                        username,
                },
                userDtoUpdate:{
                        username,
                },
                addFormRules: {
//                    ownerCode: [
//                        {required: true, message: '不能为空', trigger: 'blur'},
//                    ],

                },
                updateFormRules: {
    //                    ownerCode: [
    //                        {required: true, message: '不能为空', trigger: 'blur'},
    //                    ],

                },
            }
        },

        created () {
            this.init()
        },

        methods:{
            init() {
                this.getList();
            },

            getList(){
                this.tableData = [];
                this.listLoading = true;
                getList(this.userQueryModel).then((res) => {
                    res.data.data.forEach(item => {
                        this.tableData.push(item)
                    })
                    this.total = res.data.total;
                    this.listLoading = false;
                });
            },

            getInfo(id){
                this.$router.push({path: '/user/info',query: {id: id}})

            },

            handleCurrentChange(val) {
                this.userQueryModel.pageNumber = val;
                this.getList();
            },

            updateDialog(val){
                this.updateVisible = true;
            },

            handlerSubmit(formName){
                this.$refs[formName].validate((valid) => {
                    if (valid){
                        if (formName ==="updateForm"){
                            update(this.userDtoUpdate).then(response => {
                                Message({
                                    message: "修改成功",
                                    type: 'success',
                                });
                            });
                            this.init();
                        }else if (formName === "addForm"){
                            add(this.userDtoAdd).then(response => {
                                Message({
                                    message: "添加成功",
                                    type: 'success',
                                });
                            });
                            this.init();
                        }

                    }
                });
            },

            handleClose(formName) {
                this.addVisible = false;
                this.updateVisible = false;
                this.$refs[formName].resetFields();//将form表单重置
                this.$refs[formName].clearValidate();//将form表单重置
            },

        }
    }
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
    .applicaton {
    &-container {
         margin: 30px;
     }
    &-text {
         font-size: 30px;
         line-height: 46px;
     }
    }
</style>

6、application.properties

支持读写分离,需要配置两个数据源

   spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver
   spring.datasource.master.url=jdbc:mysql://127.0.0.1:3306/cas_db?useUnicode=true
   spring.datasource.master.username=111
   spring.datasource.master.password=111
   
   spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
   spring.datasource.slave.url=jdbc:mysql://127.0.0.1:3306/cas_db?useUnicode=true
   spring.datasource.slave.username=111
   spring.datasource.slave.password=111

6、拓展

如果有些文件需要修改,比如controller,service对外接口一般会有一些自定义的。可以在生成后进行修改,重新生成不会覆盖

7、访问地址

应用起来后,可以通过: IP:port/doc.html 查看swagger接口文档!

About


Languages

Language:Java 89.8%Language:FreeMarker 10.2%