SpringBoot敏捷開發 使用動軟程式碼生成器 搞定三層架構程式碼
阿新 • • 發佈:2018-12-24
前言
首先介紹一下 我是一個寫過很多年.net 程式碼的程式設計師
2010年才轉的JAVA開發
所以一直對@李天平 .net大神級人物 心生崇拜
此人部落格地址為 https://blog.csdn.net/litp/
提到這個人 就不得不提起 動軟程式碼生成器 真乃神器也
但是JAVA web開發中 一直沒有一款順手的 程式碼生成器
後來公司胡總寫了一個 但是修改起來 非得有很強的技術實力不可
於是想到用這個動軟程式碼生成器來逆向生成SpringBoot 程式碼
具體模板使用方法請參考官方解釋
https://blog.csdn.net/litp/article/details/6445672
Entity模板
所有表名為 t_ 開頭 使用者表就是 t_user
<#@ template language="c#" HostSpecific="True" #> <#@ output extension= ".java" #> <# TableHost host = (TableHost)(Host); host.Fieldlist.Sort(CodeCommon.CompareByintOrder); boolean hasDefaultValue = true; #> import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Lob; import org.springframework.data.rest.core.annotation.RestResource; import com.fasterxml.jackson.annotation.JsonIgnore; @Entity @Table(name="<#= host.GetModelClass(host.TableName) #>") public class <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>{ <# foreach (ColumnInfo c in host.Fieldlist) { #> <# if(c.IsPrimaryKey ){#>@Id @GeneratedValue(strategy = GenerationType.AUTO)<#}#><#= c.TypeName=="longtext" ? @"@Lob //不建議在主表放置大型文字欄位 如果有 推薦使用 一對一關聯表存放" : "" #> private <#= typeConvert(c.TypeName)#> <#= c.ColumnName.ToString()#><#=hasDefaultValue?getDefaultValueByType(c.TypeName):""#>; <#}#> <# foreach (ColumnInfo c in host.Fieldlist) { #> public <#= typeConvert(c.TypeName)#> get<#= c.ColumnName.ToString().Substring(0,1).ToUpper()#><#= c.ColumnName.ToString().Substring(1)#>() { return <#= c.ColumnName.ToString()#>; } public void set<#= c.ColumnName.ToString().Substring(0,1).ToUpper()#><#= c.ColumnName.ToString().Substring(1)#>(<#= typeConvert(c.TypeName)#> <#= c.ColumnName.ToString()#>) { this.<#= c.ColumnName.ToString()#> = <#= c.ColumnName.ToString()#>; } <#}#> } <#+ // private string getClassNameByTableName(string tname){ string str2 = ""; tname = tname.Replace("t_",""); for (int i = 0; i < tname.Length; i++) { string temp = tname.Substring(i, 1); if (temp == "_") { temp = tname.Substring(i+1, 1).ToUpper(); i++; } if(i==0){ temp = temp.ToUpper(); } str2 += temp; } return str2; } //mysql to java //include varchar char longtext int bigint float double bit date real //default type String private string typeConvert(string type){ string str2 = "String"; if(type=="int"||type=="mediumint"||type=="integer"||type=="smallint"||type=="tinyint"){ str2 = "Integer"; }else if(type=="float"){ str2 = "Float"; }else if(type=="double"||type=="real"){ str2 = "Double"; }else if(type=="bigint"){ str2 = "Long"; }else if(type=="bit"){ str2 = "Boolean"; }else if(type=="date"||type=="datetime"||type=="timestamp"){ str2 = "Date"; } return str2; } private string getDefaultValueByType(string type){ string str2 = " = \"\""; if(type=="int"||type=="mediumint"||type=="integer"||type=="smallint"||type=="tinyint"){ str2 = " = 0"; }else if(type=="float"){ str2 = " = 0f"; }else if(type=="double"||type=="real"){ str2 = " = 0d"; }else if(type=="bigint"){ str2 = " = 0l"; }else if(type=="bit"){ str2 = " = false"; }else if(type=="date"||type=="datetime"||type=="timestamp"){ str2 = " = new Date()"; } return str2; } #>
Repository
生成 幾行程式碼而已啦 包含的Entity包名需要更改
<#@ template language="c#" HostSpecific="True" #> <#@ output extension= ".java" #> <# TableHost host = (TableHost)(Host); #> import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import com.avicsafety.webapp.entity.<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>; //請自行修改 @Repository public interface <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>Repository extends JpaRepository<<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>, Long> { } <#+ private string getClassNameByTableName(string tname){ string str2 = ""; tname = tname.Replace("t_",""); for (int i = 0; i < tname.Length; i++) { string temp = tname.Substring(i, 1); if (temp == "_") { temp = tname.Substring(i+1, 1).ToUpper(); i++; } if(i==0){ temp = temp.ToUpper(); } str2 += temp; } return str2; } #>
Service 層程式碼
我寫了個介面和類 來對應JPA常用方法
import java.io.Serializable;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
/**
* 基礎的Service 介面 繼承次介面 就有了 JPA了大部分方法
* @author shili
*
*/
public interface IService<T,ID extends Serializable> {
/**
* <p>
* 插入一條記錄 返回這個物件的實體
* </p>
*
* @param entity 實體物件
* @return T
*/
T insert(T entity);
/**
* <p>
* 插入多個實體
* </p>
*
* @param entityList 實體物件列表
* @return List
*/
List<T> insert(List<T> entityList);
/**
* <p>
* 更新操作 通過id
* </p>
* @param entity 實體物件列表
* @param id
* @return 這個物件
*/
T update(T entity, ID id);
/**
* <p>
* 更新操作 通過條件批量更新
* </p>
* @param 需要更新成啥樣 這個裡面是update 語句中 set部分
* @param 給定的條件是一個實體 實體中的欄位就是條件 這個是條件 不要弄反了 這個就是update 語句中 where部分
* @return 影響的條目數
*/
Integer update(T entity,T where);
/**
* <p>
* 根據 ID 刪除
* </p>
*
* @param id 主鍵ID
* @return boolean
*/
void delete(ID id);
/**
* <p>
* 根據 實體 刪除 符合這個實體中欄位條件的 都刪除
* </p>
*
* @param 給定的條件是一個實體 實體中的欄位就是條件
* @return 刪除的條目數
*/
Integer deleteByBody(T where);
/**
* <p>
* 通過條件批量刪除
* </p>
*
* @param id 主鍵ID
* @return T
*/
T findOne(ID id);
/**
* <p>
* 查詢(根據ID 批量查詢)
* </p>
*
* @param idList 主鍵ID列表
* @return List<T>
*/
List<T> findByIds(Iterable<ID> ids);
/**
* <p>
* 列出所有
* </p>
*
* @return List<T>
*/
List<T> findAll();
/**
* <p>
* 列出所有
* </p>
*
* @return Page<T>
*/
Page<T> findAll(Pageable pageable);
/**
* <p>
* 查詢(根據 Body 條件)
* </p>
*
* @param Body 物件實體
* @return List<T>
*/
List<T> findByBody(T t);
/**
* <p>
* 查詢(根據 Body)
* </p>
*
* @param Body 物件實體
* @return Page<T>
*/
Page<T> findByBody(T t,Pageable pageable);
/**
* <p>
* 查詢總記錄數
* </p>
*
* @param wrapper 實體物件
* @return Long
*/
Long count();
/**
* <p>
* 根據 Body 條件,查詢總記錄數
* </p>
*
* @param wrapper 實體物件
* @return Long
*/
Long count(T t);
}
實現
import java.io.Serializable;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import com.avicsafety.webapp.base.service.IService;
/**
* 其實Service 繼承他就很好了
* @author shili
*
* @param Repository
* @param entity
* @param 主鍵型別
*/
public class ServiceImpl<M extends JpaRepository<T,ID>,T,ID extends Serializable> implements IService<T,ID> {
@Autowired
protected M dao;
@Override
public T insert(T entity) {
return dao.save(entity);
}
@Override
public List<T> insert(List<T> entities) {
return dao.save(entities);
}
@Override
public T update(T entity, ID id) {
T t= dao.findOne(id);
BeanUtils.copyProperties(entity, t);
return dao.save(t);
}
@Override
public void delete(ID id) {
dao.delete(id);;
}
@Override
public T findOne(ID id) {
return dao.findOne(id);
}
@Override
public List<T> findByIds(Iterable<ID> ids) {
return dao.findAll(ids);
}
@Override
public List<T> findAll() {
return dao.findAll();
}
@Override
public Page<T> findAll(Pageable pageable) {
return dao.findAll(pageable);
}
@Override
public Long count() {
return dao.count();
}
@Override
public Long count(T t) {
return dao.count(Example.of(t));
}
@Override
public List<T> findByBody(T t) {
return dao.findAll(Example.of(t));
}
@Override
public Page<T> findByBody(T t,Pageable pageable) {
return dao.findAll(Example.of(t), pageable);
}
@Override
public Integer update(T entity, T where) {
List<T> _list = findByBody(where);
for(T t:_list) {
BeanUtils.copyProperties(entity, t);
}
dao.save(_list);
return _list.size();
}
@Override
public Integer deleteByBody(T where) {
List<T> _list = findByBody(where);
dao.delete(_list);
return _list.size();
}
}
生成程式碼模板 就超級簡單了 首先是介面
<#@ template language="c#" HostSpecific="True" #>
<#@ output extension= ".java" #>
<#
TableHost host = (TableHost)(Host);
#>
public interface <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>Service extends IService<<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>,Long> {
}
<#+
private string getClassNameByTableName(string tname){
string str2 = "";
tname = tname.Replace("t_","");
for (int i = 0; i < tname.Length; i++) {
string temp = tname.Substring(i, 1);
if (temp == "_") {
temp = tname.Substring(i+1, 1).ToUpper();
i++;
}
if(i==0){
temp = temp.ToUpper();
}
str2 += temp;
}
return str2;
}
#>
然後是實現
<#@ template language="c#" HostSpecific="True" #>
<#@ output extension= ".java" #>
<#
TableHost host = (TableHost)(Host);
#>
import org.springframework.stereotype.Service;
public class <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>ServiceImpl extends ServiceImpl<<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>Repository,<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>,Long> implements IStockService{
}
<#+
private string getClassNameByTableName(string tname){
string str2 = "";
tname = tname.Replace("t_","");
for (int i = 0; i < tname.Length; i++) {
string temp = tname.Substring(i, 1);
if (temp == "_") {
temp = tname.Substring(i+1, 1).ToUpper();
i++;
}
if(i==0){
temp = temp.ToUpper();
}
str2 += temp;
}
return str2;
}
#>
Controller 層
這裡是 resful 風格 好吧 對付著用吧<#@ template language="c#" HostSpecific="True" #>
<#@ output extension= ".java" #>
<#
TableHost host = (TableHost)(Host);
#>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>Controller {
@Autowired
<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>Service <#= getNameByTableName(host.GetModelClass(host.TableName)) #>Service;
@RequestMapping(value = "/public/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>/{id}",method = RequestMethod.GET)
public <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #> findOne(@PathVariable("id") Long id) {
return <#= getNameByTableName(host.GetModelClass(host.TableName)) #>Service.findOne(id);
}
@RequestMapping(value = "/public/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>",method = RequestMethod.GET)
public Page<<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>> findAll(Pageable pageable) {
return <#= getNameByTableName(host.GetModelClass(host.TableName)) #>Service.findAll(pageable);
}
//按照規範 應該使用GET方式 但是POSTMAN不方便測試
@RequestMapping(value = "/public/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>/search/findByBody",method = RequestMethod.POST)
public Page<<#= getClassNameByTableName(host.GetModelClass(host.TableName)) #>> findByBody(@RequestBody <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #> entity,Pageable pageable) {
return <#= getNameByTableName(host.GetModelClass(host.TableName)) #>Service.findByBody(entity, pageable);
}
@RequestMapping(value = "/public/goods",method = RequestMethod.POST)
public <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #> insert(@RequestBody <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #> entity) {
return <#= getNameByTableName(host.GetModelClass(host.TableName)) #>Service.insert(entity);
}
@RequestMapping(value = "/public/goods",method = RequestMethod.PUT)
public <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #> update(@RequestBody <#= getClassNameByTableName(host.GetModelClass(host.TableName)) #> entity) {
return <#= getNameByTableName(host.GetModelClass(host.TableName)) #>Service.update(entity,entity.getId()); //獲取主鍵值的方法 請自行修改
}
@RequestMapping(value = "/public/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>/{id}",method = RequestMethod.DELETE)
public void delete(@PathVariable("id") Long id) {
<#= getNameByTableName(host.GetModelClass(host.TableName)) #>Service.delete(id);
}
}
<#+
private string getClassNameByTableName(string tname){
string str2 = "";
tname = tname.Replace("t_","");
for (int i = 0; i < tname.Length; i++) {
string temp = tname.Substring(i, 1);
if (temp == "_") {
temp = tname.Substring(i+1, 1).ToUpper();
i++;
}
if(i==0){
temp = temp.ToUpper();
}
str2 += temp;
}
return str2;
}
private string getNameByTableName(string tname){
return tname.Replace("t_","");
}
#>
頁面
前臺使用Bootstrap + Vue 具體點應該說是AdminLET
html部分
<#@ template language="c#" HostSpecific="True" #>
<#@ output extension= ".java" #>
<#
TableHost host = (TableHost)(Host);
host.Fieldlist.Sort(CodeCommon.CompareByintOrder);
#>
<<#= getChar() #>include "../../template/layout.html"/>
<@title>
列表
</@title>
<@html>
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
列表
</h1>
<ol class="breadcrumb">
<li><a href="../index/home.html"><i class="fa fa-dashboard"></i> 首頁</a></li>
<li class="active">列表</li>
</ol>
</section>
<!-- Main content -->
<section class="content" v-cloak>
<div class="row">
<div class="col-md-12">
<div class="pull-left">
<button type="button" class="btn btn-primary" @click="openPanle(0)">新建</button>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<div class="box-body no-padding">
<v-table
is-horizontal-resize
style="width:100%"
:columns="columns"
:table-data="list"
@on-custom-comp="table_opera"
:paging-index="(pageIndex)*pageSize"
row-hover-color="#eee"
even-bg-color="#f2f2f2"
:show-vertical-border="false"></v-table>
</div>
<div class="box-footer">
<v-pagination @page-change="pageChange" :total="totalElements" :page-size="pageSize" :layout="['total', 'prev', 'pager', 'next', 'jumper']"></v-pagination>
</div>
<!-- /.box body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-md-12">
<div class="pull-left">
<button type="button" class="btn btn-primary bottom10px" @click="openPanle(0)">新建</button>
</div>
</div>
</div>
</section>
<!-- /.content -->
<!-- 模態框(Modal) -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form id="myform">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
×
</button>
</div>
<!-- /.modal-header -->
<div class="modal-body">
<# foreach (ColumnInfo c in host.Fieldlist){ #>
<div class="form-group">
<label ><#= c.ColumnName.ToString()#></label>
<input type="text" class="form-control" id="<#= c.ColumnName.ToString()#>" name="<#= c.ColumnName.ToString()#>" placeholder="<#= c.ColumnName.ToString()#>" v-model='info.<#= c.ColumnName.ToString()#>'>
</div>
<#}#>
</div>
<!-- /.modal-body -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">關閉</button>
<button type="button" class="btn btn-primary" @click="save">儲存</button>
</div>
<!-- /.modal-footer -->
</form>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
</@html>
<@myscript>
<script src="../../js/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>.js"></script>
</@myscript>
<#+
private string getClassNameByTableName(string tname){
string str2 = "";
tname = tname.Replace("t_","");
for (int i = 0; i < tname.Length; i++) {
string temp = tname.Substring(i, 1);
if (temp == "_") {
temp = tname.Substring(i+1, 1).ToUpper();
i++;
}
if(i==0){
temp = temp.ToUpper();
}
str2 += temp;
}
return str2;
}
private string getNameByTableName(string tname){
return tname.Replace("t_","");
}
private string getChar(){
return "#";
}
#>
js部分
<#@ template language="c#" HostSpecific="True" #>
<#@ output extension= ".java" #>
<#
TableHost host = (TableHost)(Host);
host.Fieldlist.Sort(CodeCommon.CompareByintOrder);
#>
var vm = new Vue({
el: '#content',
data: {
index:0,
info:{},
list:[],
page:0,
columns: [
<# foreach (ColumnInfo c in host.Fieldlist){ #>
{field: '<#= c.ColumnName.ToString()#>', title:'<#= c.ColumnName.ToString()#>', width: 100, titleAlign: 'center',columnAlign:'center', isResize:true},
<#}#>
{field: 'custome-adv', title: '操作', width: 100, titleAlign: 'center',columnAlign:'center',componentName:'table-operation'}
],
pageIndex: 0,
pageSize:14,
totalElements:0,
totalPages:0
},
methods: {
init: function () {
this.load();
},
load:function(){
this.$http.get(HOST_NAME+'/api/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>',
{params:{page:this.pageIndex,size:this.pageSize,sort:"id,desc"}}).then(function (response) {
vm.list = response.data.content;
vm.totalPages = response.data.totalPages;
vm.totalElements = response.data.totalElements;
},function (error) {
layer.open({ontent: '與伺服器通訊出錯',btn: '確定'});
});
},
openPanle:function(type){
if(type==0){
this.info={};
}else{
this.info=this.list[this.index];
}
$('#myModal').modal('show');
},
save:function(){
if(!this.info.id){
this.$http.post(HOST_NAME+'/api/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>',this.info)
.then(function(response){
this.list[this.index].push(response.data);
$('#myModal').modal('hide');
layer.open({content:"操作成功!",btn:"確認"});
},function(response){
layer.open({content:"訪問伺服器出錯,請稍後再試!",btn:"確定"});
});
}else{
this.$http.put(HOST_NAME+'/api/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>',this.info)
.then(function(response){
this.list[this.index] = response.data;
$('#myModal').modal('hide');
layer.open({content:"操作成功!",btn:"確認"});
},function(response){
layer.open({content:"訪問伺服器出錯,請稍後再試!",btn:"確定"});
});
}
},
del:function(index,id){
layer.open({
content: '真的要刪除嗎?'
,btn: ['確定', '取消']
,yes: function(e){
layer.close(e);
var url = HOST_NAME + '/api/<#= getNameByTableName(host.GetModelClass(host.TableName)) #>/'+id;
Vue.http.delete(url).then(function (response) {
vm.list.splice(index, 1);
layer.open({content: '成功',btn:"確認"});
}, function (response) {
layer.open({content:"訪問伺服器出錯,請稍後再試!",btn:"確認"});
});
}
});
},
table_opera(params){
console.log(params);
if (params.type === 'delete'){ // do delete operation
this.del(params.index,params.rowData["id"]);
}else if (params.type === 'edit'){ // do edit operation
this.index = params.index;
this.openPanle(1);
}
},
pageChange:function(pageIndex){
this.pageIndex = pageIndex-1;
this.load();
},
pageSizeChange:function(pageSize){
this.pageIndex = 0;
this.pageSize = pageSize;
this.load();
}
}
});
vm.init();
// 自定義列元件
Vue.component('table-operation',{
template:`<span>
<a href="" @click.stop.prevent="edit(rowData,index)">修改</a>
<a href="" @click.stop.prevent="deleteRow(rowData,index)">刪除</a>
</span>`,
props:{
rowData:{
type:Object
},
field:{
type:String
},
index:{
type:Number
}
},
methods:{
edit(){
let params = {type:'edit',index:this.index,rowData:this.rowData};
this.$emit('on-custom-comp',params);
},
deleteRow(){
let params = {type:'delete',index:this.index,rowData:this.rowData};
this.$emit('on-custom-comp',params);
}
}
})
<#+
private string getNameByTableName(string tname){
return tname.Replace("t_","");
}
#>
如果本文對您有幫助 請留言