# iBiz SpringBoot模板

（技术引用链接）

`SpringBoot官方文档`[:arrow_upper_right:](https://spring.io/projects/spring-boot)

`iBizSys模型api文档`[:arrow_upper_right:](https://modelapi.ibizlab.cn/)


## 介绍说明

`SpringBoot`

Spring Boot是由Pivotal团队提供的全新框架，其设计目的是用来简化新Spring应用的初始搭建以及开发过程，通过简单配置就可以轻松地创建独立的、生产级的、基于spring的应用程序。

`iBizSys`

iBizSys 是以 `Model Driven Development(MDD)`作为核心理论依据的开发框架，iBizSys从`2009年`诞生至今已经经历数个版本，构建出一套完整的系统构建模型，包含: `DevOps模型`、`文档模型`、`流程模型`、`测试模型`等。 iBizSys 提倡以`模型`作为主要内容的高级别抽象的开发方法，并结合市面上较为流行的技术框架形成技术模板，通过`模型`+`模板`的方式快速构建出一套生产级并且具备`复杂性`和`变更能力`的系统。



## 快速开始

## 搭建SpringBoot工程  

我们将通过搭建一个简单的SpringBoot工程，我们将为每个实体发布出其对应的Controller用于接收并响应用户请求，在此之前，我们假设您已经：

- **熟悉iBizSys实体建立**

- **熟悉SpringBoot**

- **熟悉FreeMaker**
	

## 建立实体

iBizSys将通过管理数据模型的方式来实现对业务表的管理 [查看更多实体建立小知识](http://bbs.ibizlab.cn/)

![produce](img/quickstart/createEntity.png)

## 建立模板

`编写模板方式`

>在线编辑：`iBizSys` 提供模板在线编辑工具，供大家更高效、便捷的编写模板 [查看iBizSys在线编辑工具](http://bbs.ibizlab.cn/)

>离线编辑：由于`iBizSys`的模板是放在`git`仓库中进行托管，用户可在离线环境下编写模板，编辑完成后再将模板上传至`git`中即可。

### 依赖模板：

在 `pom.xml.ftl` 中引入 SpringBoot 所需的相关依赖

```java

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>


```
 

### 启动类模板：

在 启动类` %PUBPRJ%Main.java.ftl ` 模板中含 ` % % 、${ } `均为动态参数 [查看模板参数](http://bbs.ibizlab.cn/)

```java

@SpringBootApplication
public class ${pub.getCodeName()?lower_case}Main{

	public static void main(String[] args) {
		SpringApplication.run(${pub.getCodeName()?lower_case}Main.class, args);
	}
}


```

### Controller模板：

iBizSys会为每个应用实体发布其对应的Controller

```java

@RestController
public class ${de.codeName}Controller{

    <#assign appReqUrl="/" +app.getPKGCodeName()?lower_case + "/"+de.getPSSystemModule().codeName?lower_case +"/"+de.codeName?lower_case ><#comment>当前实体请求路径</#comment>
    @PostMapping(value="${appReqUrl}")
    public String hello(){
        return  String.format("您好,您目前正在访问[%s]实体","${de.codeName}");
    }
}

```


## 发布模板

您在iBizSys模板工具编写模板后，模板处于暂存状态，若您需要在项目中应用该模板，需要发布该模板。

![produce](img/quickstart/publishFtl.png)

## 发布模型

发布模型的过程即为从模板仓库中获取最新模板合成模型，生产代码的过程。

![produce](img/quickstart/publishSystem.png)

## 查看最终成果物

### 依赖

![produce](img/quickstart/result_pom.png)


### 启动类

![produce](img/quickstart/result_appMain.png)

### Controller

![produce](img/quickstart/result_controller.png)


### 开始使用


添加测试类，进行功能测试，测试类相关代码如下：

```java

@RunWith(SpringRunner.class)
@SpringBootTest(classes = demoMain.class)
public class ApplicationTest {
    private MockMvc mockMvc;
    @Autowired
    private WebApplicationContext webApplicationContext;
    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
    @Test
    public void contextLoads() {
        try {
            MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/demo/springboot/dbet/")).andReturn();
            System.out.println("----正在调用实体controller----");
            System.out.println("controller返回结果为："+mvcResult.getResponse().getContentAsString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

```

控制台输出：

```
----正在调用实体controller----
controller返回结果为：您好,您目前正在访问[DBET]实体
 
```

## 小结

通过以上几个简单的步骤，您已经成功搭建一个SpringBoot项目，并为每个应用实体发布对应的Controller实现了能接收并响应用户请求的功能。并且您也成功了搭建了一套属于您个人的技术模板，您可以在以后的任何项目当中，使用您搭建的这套技术模板。

iBizSys可以帮助您快速搭建并使用您所搭建的技术模板来生产您的项目，想要了解更多iBizSys模板生产体系？那就继续往下看吧！



## 实体服务对象

通过第一章的学习，您已经成功搭建了一个SpringBoot项目，通过Controller来接收并响应用户请求。但在我们实际项目当中，Controller往往仅作为控制层，只负责转发用户的请求到Service，实际的业务是由Service层来处理的。本章就为大家演示通过模板发布服务层代码。


以下示例中将以`表单`的`增`、`删`、`改`、`查` 为例进行演示：

### Controller

Controller层为实体所用到的部件发布对应的restful接口，并调用Service进行处理 `本示例中仅以表单为例进行演示，仅发布出表单对应的行为接口`

```java

@RestController
public class ${de.codeName}Controller{

<#assign appReqUrl="/" +app.getPKGCodeName()?lower_case + "/"+de.getPSSystemModule().codeName?lower_case +"/"+de.codeName?lower_case ><#comment>当前实体请求路径</#comment>
<#comment>注入当前实体的服务对象</#comment>
    @Autowired
    private ${de.codeName}Service ${de.codeName?lower_case}Service;

<#list item.getPSControls() as ctrl><#comment>输出实体所使用到的部件（实体用到的部件可能有：表格、表单、树视图等）</#comment>
    <#if ctrl.getControlType() == 'FORM'><#comment>本示例中只展示表单</#comment>
        <#list ctrl.getPSAjaxControlHandler().getPSAjaxHandlerActions() as action><#comment>输出表单行为：(新建、编辑、删除等)</#comment>
        <#if action.getPSDEAction??  && action.getPSDEAction()??>
            <#assign ctrltype=ctrl.getControlType()>
    @PostMapping(value="${appReqUrl}/${ctrl.getCodeName()?lower_case}${srfclassname(ctrltype)?lower_case}/${action.getPSDEAction().getCodeName()?lower_case}")
    public ${de.codeName}  ${srfmethodname(ctrl.getCodeName())}${srfclassname(ctrltype)}${action.getPSDEAction().getCodeName()}(${de.codeName} entity){
        this.${de.codeName?lower_case}Service.${srfmethodname(action.getPSDEAction().getCodeName())}(entity);
            return entity;
    }
        </#if>
        </#list>
    </#if>
</#list>
}


```


### 服务接口

为每个实体发布服务接口 `%DE%Service.java.ftl`，service中发布该实体所有实体行为 `增`、`删`、`改`、`查`等

```java

/**
 * 实体[${item.codeName}] 服务对象接口
 */
public interface ${item.codeName}Service{

<#if item.getAllPSDEActions()??>
 <#list item.getAllPSDEActions() as deaction>
  <#if (deaction.getActionMode() == "READ") >
    ${item.codeName} ${srfmethodname(deaction.getCodeName())}(${item.codeName} et);
  <#else>
	boolean ${srfmethodname(deaction.getCodeName())}(${item.codeName} et);
  </#if>
 </#list>
</#if>

}


```


### 服务实现类

为每个实体发布服务实现类`%DE%ServiceImpl.java.ftl`，实现类中将对实体 `增`、`删`、`改`、`查` 等行为进行具体实现

```java

/**
 * 实体[${item.codeName}] 服务对象接口实现
 */
@Service
public class ${item.codeName}ServiceImpl  implements ${item.codeName}Service{

<#if item.getAllPSDEActions()??>
 <#list item.getAllPSDEActions() as deaction>
  <#if (deaction.getActionMode() == "READ") >
   @Override
   public ${item.codeName} ${srfmethodname(deaction.getCodeName())}(${item.codeName} et){
      System.out.println(String.format("您当前正在调用[%s]的[%s]方法","${item.codeName}ServiceImpl","${srfmethodname(deaction.getCodeName())}"));
      return  et;
   }
  <#else>
   @Override
   public boolean ${srfmethodname(deaction.getCodeName())}(${item.codeName} et){
      System.out.println(String.format("您当前正在调用[%s]的[%s]方法","${item.codeName}ServiceImpl","${srfmethodname(deaction.getCodeName())}"));
      return true;
   }
  </#if>
 </#list>
</#if>

}


```

### 实体类

循环输出所有实体属性

```java

/**
 * 实体[${item.codeName}] 数据对象
 */
@Data
public class ${item.codeName}{

<#list item.getPSDEFields() as defield>
    private ${srfjavatype(defield.stdDataType)} ${defield.codeName?lower_case};
</#list>

}


```

## 查看最终成果物

### Controller

![produce](img/service/result_controller.png)

### 服务接口

![produce](img/service/result_IService.png)

### 服务实现类

![produce](img/service/result_serviceImpl.png)

### 实体类

![produce](img/service/result_de.png)

### 开始使用


添加测试类，进行功能测试，测试类相关代码如下：

```java

@RunWith(SpringRunner.class)
@SpringBootTest(classes = demoMain.class)
public class ApplicationTest {
    private MockMvc mockMvc;
    @Autowired
    private WebApplicationContext webApplicationContext;
    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
    @Test
    public void contextLoads() {
        try {
            MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/demo/springboot/dbet/maineditform/get")).andReturn();
            System.out.println("返回结果为："+mvcResult.getResponse().getContentAsString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

```

控制台输出：

```
----正在调用实体controller----
您当前正在调用[DBETServiceImpl]的[get]方法
返回结果为：{"dbetname":null,"createdate":null,"createman":null,"dbetid":null,"updatedate":null,"updateman":null}
 
```


