发表于: 2021-01-04 19:04:05

1 1315


今天完成的事情:


使用Faker假数据失败

项目分层搭建



明天计划的事情:

请假7天



遇到的问题:

楼上装修,浓烈的油漆味,下午回去了




收获:

使用Faker假数据


maven 依赖
<!-- 生成假数据-->
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
============
我在这里直接使用了lombok插件,getter和setter注解也不用加了




使用lombok插件好处?


在项目开发阶段,一个class的属性是一直变化的,今天可能增加一个字段,明天可能删除一个字段。每次变化都需要修改对应的模板代码。另外,有的class的字段超级多,多到一眼看不完。如果加上模板代码,更难一眼看出来。更有甚者,由于字段太多,想要使用builder来创建。手动创建builder和字段和原来的类夹杂在一起,看起来真的难受。lombok的@Builder即可解决这个问题。



=====================
JAVA实现
MockItem参数类(包含调用的方法,参数以及输出时参数对应的key)
package com.kbk.javaFakerTest;
import lombok.Data;
import java.util.List;
@Data
public class MockItem{
/**
* @ 名称对应的faker一级方法.二级方法(number.randomDigit)
*/
private String methodNames;
/**
* @ 生成数据调用方法对应的参数,前段传入的参数
*/
public List<MockItemParamters> inParameters;
/**
* @ 返回数据时的key
*/
private String key;
}
==============
MockItemParamters(调用方法时传入的参数以及参数类型)
package com.kbk.javaFakerTest;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MockItemParamters {
/**
* @ 名称对应Params参数
*/
private Object Params;
/**
* @ 名称对应Params参数类型
*/
Class<?> clazz;
}
=======
最终实现的工具类GenerateData
package com.kbk.javaFakerTest;
import com.kbk.javaFakerTest.MockItem;
import com.github.javafaker.Faker;
import com.kbk.model.Tourist;
import java.util.*;
public class GenerateData{
/**
* TODO
* @param: faker
* @param: mockItem 生成数据是调用的方法,方法需要的参数及类型以及输出数据时的key
* @param: number 生成假数据的条数
* @param: clazz 需要输出的实体
*/
public static <T> List<T> generatList(Faker faker, List<MockItem> mockItem, int number, Class<T> clazz) throws Exception {
List<T> listResult = new ArrayList<>();
for(int i = 0; i < number; i++){
listResult.add(i,generateEntity(faker,mockItem,clazz));
}
return listResult;
}
public static List<Map<String, Object>> generatListMap(Faker faker, List<MockItem> mockItem, int number){
List<Map<String, Object>> listResult = new ArrayList<>();
for(int i=0;i<number;i++){
listResult.add(i,generateMap(faker,mockItem));
}
return listResult;
}
/**
* TODO
* @Description: 一次生成一条Map假数据
* @return: listResultdata
*/
public static Map<String, Object> generateMap(Faker faker,List<MockItem> mockItem){
Map<String,Object> listResultdata = new HashMap<>();
try {
for (MockItem m : mockItem) {
listResultdata.put(m.getKey(),generateSingleData(faker,m));
}
}
catch (Exception e){
throw new RuntimeException("Data generation failed", e);
}
return listResultdata;
}
/**
* TODO
* @Description: 一次生成一条数据,核心在于利用BeanUtils.setProperty反射机制
* @return: T
*/
public static <T> T generateEntity(Faker faker,List<MockItem> mockItem, Class<T> clazz){
try {
T result = clazz.newInstance();
for (MockItem mock : mockItem) {
Object value = generateSingleData(faker, mock);
BeanUtils.setProperty(result, mock.getKey(), value);
}
return result;
}
catch (Exception e){
throw new RuntimeException("Data generation failed", e);
}
}
/**
* TODO
* @Description: 调用Faker方法一次生成一个数据
* @return: (T)
*/
public static Object generateSingleData(Faker faker,MockItem mockItem) throws Exception{
String[] methods = mockItem.getMethodNames().split("\\.");
if(methods.length != 2) {
throw new RuntimeException("methodNames is not invaild");
}
Object firstMethod = faker.getClass().getMethod(methods[0]).invoke(faker);//获取到faker第一个方法的调用句柄
Class<?> firstMethodClass = firstMethod.getClass();
if(mockItem.getInParameters() != null) {
Class<?>[] clazz = typeConversion(mockItem.getInParameters());
Object[] paramets = parameterConversion(mockItem.getInParameters());
//getMethod的第二个参数parameterTypes是按声明顺序标识该方法形参类型。
return firstMethodClass.getMethod(methods[1], clazz).invoke(firstMethod, paramets);
}
return firstMethodClass.getMethod(methods[1]).invoke(firstMethod);
}
/**
* TODO
* @Description: 根据调用者提供的数据类型进行相对应的转换(类型转换)主要用在getMethod的第二个参数parameterTypes需要声明方法形参类型
* @param: mockItemParamters 参数类包含参数及参数类型
* @return: Class<?>[]
*/
public static Class<?>[] typeConversion(List<MockItemParamters> mockItemParamters){
Class<?>[] clazz = new Class<?>[mockItemParamters.size()];
//遍历获取形参类型以及转换参数
int i = 0;
for(MockItemParamters m : mockItemParamters){
if(int.class == m.getClazz() || Integer.class == m.getClazz()){
clazz[i] = int.class;
}else if(boolean.class == m.getClazz() || Double.class == m.getClazz()){
clazz[i] = boolean.class;
}else if(long.class == m.getClazz() || Long.class == m.getClazz()){
clazz[i] = long.class;
}else if(byte.class == m.getClazz() || Byte.class == m.getClazz()){
clazz[i] = byte.class;
}else if(float.class == m.getClazz() || Float.class == m.getClazz()){
clazz[i] = float.class;
}else if(double.class == m.getClazz() || Double.class == m.getClazz()){
clazz[i] = double.class;
}else if(short.class == m.getClazz() || Short.class == m.getClazz()){
clazz[i] = short.class;
}else{
clazz[i] = String.class;
}
i++;
}
return clazz;
}
/**
* TODO
* @Description: 根据调用者提供的数据类型进行相对应的转换(参数类型转换)
* @param: mockItemParamters参数类包含参数及参数类型
* @return: Class<?>[]
*/
public static Object[] parameterConversion(List<MockItemParamters> mockItemParamters){
Object[] paramets = new Object[mockItemParamters.size()];
//遍历获取形参类型以及转换参数
int i = 0;
for(MockItemParamters m : mockItemParamters){
if(int.class == m.getClazz() || Integer.class == m.getClazz()){
//int a = ConvertUtils.convert(m.getParams(),int.class,true);
paramets[i] = (Integer.parseInt(m.getParams().toString()));
}else if(boolean.class == m.getClazz() || Double.class == m.getClazz()){
paramets[i] = (Boolean.parseBoolean(m.getParams().toString()));
}else if(long.class == m.getClazz() || Long.class == m.getClazz()){
paramets[i] = (Long.parseLong(m.getParams().toString()));
}else if(byte.class == m.getClazz() || Byte.class == m.getClazz()){
paramets[i] = (Byte.parseByte(m.getParams().toString()));
}else if(float.class == m.getClazz() || Float.class == m.getClazz()){
paramets[i] = (Float.parseFloat(m.getParams().toString()));
}else if(double.class == m.getClazz() || Double.class == m.getClazz()){
paramets[i] = (Double.parseDouble(m.getParams().toString()));
}else if(short.class == m.getClazz() || Short.class == m.getClazz()){
paramets[i] = (Short.parseShort(m.getParams().toString()));
}else{
paramets[i] = (m.getParams().toString());
}
i++;
}
return paramets;
}
public static void main(String[] args) throws Exception {
Faker faker = Faker.instance(Locale.CHINA);
List<MockItem> mockItemList = new ArrayList<>();
//参数
List<MockItemParamters> mockItemParamters = new ArrayList<>();
MockItemParamters MockItemParamters = new MockItemParamters();
MockItemParamters.setParams(2);
MockItemParamters.setClazz(int.class);
MockItemParamters MockItemParamters1 = new MockItemParamters();
MockItemParamters1.setParams(2);
MockItemParamters1.setClazz(int.class);
MockItemParamters MockItemParamters2 = new MockItemParamters();
MockItemParamters2.setParams(99);
MockItemParamters2.setClazz(int.class);
mockItemParamters.add(MockItemParamters);
mockItemParamters.add(MockItemParamters1);
mockItemParamters.add(MockItemParamters2);
MockItem mockItem = new MockItem();
mockItem.setMethodNames("name.fullName");
mockItem.setKey("name");
MockItem mockItem1 = new MockItem();
mockItem1.setMethodNames("number.randomDouble");
mockItem1.setInParameters(mockItemParamters);
mockItem1.setKey("value");
mockItemList.add(mockItem);
mockItemList.add(mockItem1);
//输入的参数
System.out.println("输入的参数~~~~~~~~~~~~~~~~~"+mockItemList);
//根据实体类生成
//Tourist tourist = new Tourist();
// List<Map<String,Object>> Tourist= generatList(faker,mockItemList,10,Class<Tourist>);
// System.out.println("根据实体映射输出的list结果~~~~~~~~~~~~~~~~~"+Tourist);
//生成map类型
List<Map<String,Object>> listMap = generatListMap(faker, mockItemList, 10);
System.out.println("输出的listMap结果~~~~~~~~~~~~~~~~~"+listMap );
}
}
最终结果:




遇到报错问题:
还没解决,等有空在来解决吧




========

maven多模块构建项目(常见的springmvc项目结构)


该功能一般使用于较大的项目,对项目进行业务拆分或者代码分层,这里以代码分层+IDEA为例,构建常用的springmvc项目


最终项目结构:(这里仅分三层,基于项目的规模和复用程度,可以追加mn_bpo层,mn_api层,mn_domin层等)


个人建议:由于每个层级所负责的功能不同,对应的实体类定位也不一样,甚至大项目每个层级都是有专门的开发人员负责,因此推荐避免创建domin层,而是在每个层级之间建立依赖关系,具体的实体类也以不同的后缀区分,调用时,对实体类进行拷贝,如:


(页面)与(controller层)之间交互的参数命名为:XxxVO
(controller层、dao层)与(bs层)之间交互的参数命名为:XxxDTO
(service成,dao层)之间交互的参数命名为:XxxDO
(dao层)与(数据库)之间交互的参数命名为:XxxPO (即对应数据库表的实体类)
对于特殊情况的参数,如多表关联查询参数可使用DTO统称
===========
了解实体类(VO,DO,DTO,PO)的基础概念:




注意:项目中我们并没有严格遵循这种传递关系,但这种和业务层次的关联对我们理解各实体类的作用是有帮助的。(我们没有接触到PO的原因,我理解为ORM对PO进行了封装)


VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。


DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。


DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。


PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

主要结论是:在项目应用中,VO对应于页面上需要显示的数据(表单),DO对应于数据库中存储的数据(数据表),DTO对应于除二者之外需要进行传递的数据。


===========
第一步:创建一个空项目Project



第二步:创建一个空的maven父工程(module)
由于这里想使用springboot来启动项目,因此该父工程创建为springboot项目




勾选web起步依赖



最后删除无用文件,只保留pom.xml和idea的.iml文件,设置pom.xml文件打包方式为pom



=========
第三步:创建一个mn_controller子工程
这里要将controller层设置为项目启动层,因此也创建为springboot项目




修改项目路径在kbk_parent目录下




删除无用文件,最终目录




由于kbk_parent项目是父工程,所有子项目将继承父工程,因此这里将kbk_controller的pom.xml文件就不需要kbk_parent项目中重复出现过的依赖


最终,kbk_controller的pom.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.kbk</groupId>
<artifactId>kbk_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.kbk</groupId>
<artifactId>kbk_controller</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>kbk_controller</name>
<description>Demo project for Spring Boot</description>
<dependencies>
</dependencies>
</project>


父工程的pom.xml文件如下:(记得添加module)



<?xml version="1.0" encoding="UTF-8"?>
<modelVersion>4.0.0</modelVersion>
<modules>
<module>mn_controller</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.kbk</groupId>
<artifactId>kbk_parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>kbk_parent</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
=========

第四步:创建一个mn_bs子工程


其余的子项目只需要创建普通的maven工程即可


注意修改工程位置:
这里无法选择  kbk_parent为父模块




在这里手动添加也报错





现在还是一股油漆味,我觉得我在吸毒,头晕,溜了



返回列表 返回列表
评论

    分享到