第1步:从大佬的gitee:https://gitee.com/canonical-entropy/nop-entropy下载源码,进行本地编译,具体编译看项目下的readme,想偷懒的可以下载我编译后的jar,放到自己的maven仓库

https://pan.baidu.com/s/1p9MOh40MJ2mVMWI-sAr_uA?pwd=g2zy

我把代码上传到gitee,地址:https://gitee.com/a-crud-boy/nop-simple-demonn

第2步:创建一个maven项目,然后添加依赖

io.github.entropy-cloud

nop-entropy

2.0.0-SNAPSHOT

11

11

UTF-8

io.github.entropy-cloud

nop-spring-web-starter

com.h2database

h2

runtime

org.projectlombok

lombok

true

第3步 ,添加springboot入口

@SpringBootApplication

public class NopSpringSimpleApplication {

public static void main(String[] args) {

SpringApplication.run(NopSpringSimpleApplication.class, args);

}

}

第4步 ,添加application.yaml文件,注意是yaml,不是yml

nop:

debug: true

orm:

init-database-schema: true

datasource:

driver-class-name: org.h2.Driver

jdbc-url: jdbc:h2:./db/demo

username: sa

password:

第5步 ,创建类

import com.nop.biz.DemoRequest;

import com.nop.biz.DemoResponse;

import io.nop.api.core.annotations.biz.BizModel;

import io.nop.api.core.annotations.biz.BizMutation;

import io.nop.api.core.annotations.biz.BizQuery;

import io.nop.api.core.annotations.biz.RequestBean;

import io.nop.api.core.annotations.core.Name;

import io.nop.api.core.exceptions.NopException;

import static com.nop.biz.DemoErrors.ARG_NAME;

import static com.nop.biz.DemoErrors.ERR_DEMO_NOT_FOUND;

@BizModel("Demo")

public class DemoBizModel {

@BizQuery

public String hello(@Name("message") String message) {

return "Hi," + message;

}

@BizMutation

public DemoResponse testOk(@RequestBean DemoRequest request) {

DemoResponse ret = new DemoResponse();

ret.setName(request.getName());

ret.setResult("ok");

return ret;

}

@BizMutation

public DemoResponse testError(@RequestBean DemoRequest request) {

throw new NopException(ERR_DEMO_NOT_FOUND).param(ARG_NAME, request.getName());

}

}

package com.nop.biz.demo;

import io.nop.api.core.annotations.biz.BizModel;

import io.nop.api.core.annotations.biz.BizMutation;

import io.nop.api.core.annotations.biz.BizQuery;

import io.nop.api.core.annotations.core.Name;

import io.nop.api.core.annotations.graphql.GraphQLReturn;

import io.nop.api.core.beans.FilterBeans;

import io.nop.api.core.beans.query.QueryBean;

import io.nop.core.reflect.bean.BeanTool;

import io.nop.dao.api.IDaoProvider;

import io.nop.dao.api.IEntityDao;

import io.nop.orm.IOrmEntity;

import jakarta.inject.Inject;

import java.util.List;

import java.util.Map;

/**

*

*

*

*

*

*

* @author :

* @date 2024年01月31日

* 修改人 修改日期 修改描述

* -------------------------------------------

*

*

*/

@BizModel("DemoEntity")

public class DemoEntityBizModel {

@Inject

IDaoProvider daoProvider;

@BizQuery

@GraphQLReturn(bizObjName = "DemoEntity")

public IOrmEntity getEntity(@Name("id") String id) {

IEntityDao dao = daoProvider.dao("app.demo.DemoEntity");

return dao.getEntityById(id);

}

@BizMutation

@GraphQLReturn(bizObjName = "DemoEntity")

public IOrmEntity saveEntity(@Name("data") Map data) {

IEntityDao dao = daoProvider.dao("app.demo.DemoEntity");

IOrmEntity entity = dao.newEntity();

BeanTool.instance().setProperties(entity, data);

dao.saveEntity(entity);

return entity;

}

@BizQuery

@GraphQLReturn(bizObjName = "DemoEntity")

public List findByName(@Name("name") String name) {

IEntityDao dao = daoProvider.dao("app.demo.DemoEntity");

QueryBean query = new QueryBean();

query.addFilter(FilterBeans.contains("name", name));

// name like '%a%'

return dao.findAllByQuery(query);

}

// 注意,字段不能声明为private。NopIoC无法注入私有成员变量

@Inject

DemoMapper demoMapper;

@BizQuery

@GraphQLReturn(bizObjName = "DemoEntity")

public IOrmEntity findBySql(@Name("name") String name) {

return demoMapper.findFirstByName(name);

}

}

package com.nop.biz.demo;

import io.nop.api.core.annotations.core.Name;

import io.nop.api.core.annotations.orm.SqlLibMapper;

import io.nop.orm.IOrmEntity;

/**

*

*

*

*

*

*

* @author :

* @date 2024年01月31日

* 修改人 修改日期 修改描述

* -------------------------------------------

*

*

*/

@SqlLibMapper("/test/demo/sql/demo.sql-lib.xml")

public interface DemoMapper {

IOrmEntity findFirstByName(@Name("name") String name);

}

package com.nop.biz;

import io.nop.api.core.annotations.core.Locale;

import io.nop.api.core.exceptions.ErrorCode;

import static io.nop.api.core.exceptions.ErrorCode.define;

/**

*

*

*

*

*

*

* @author :

* @date 2024年01月31日

* 修改人 修改日期 修改描述

* -------------------------------------------

*

*

*/

@Locale("zh-CN")

public interface DemoErrors {

String ARG_NAME = "name";

ErrorCode ERR_DEMO_NOT_FOUND =

define("nop.err.demo.not-found", "指定数据不存在: {name}", ARG_NAME);

}

package com.nop.biz;

import lombok.Data;

/**

*

*

*

*

*

*

* @author :

* @date 2024年01月30日

* 修改人 修改日期 修改描述

* -------------------------------------------

*

*

*/

@Data

public class DemoRequest {

private String name;

private String email;

}

package com.nop.biz;

import lombok.Data;

/**

*

*

*

*

*

*

* @author :

* @date 2024年01月30日

* 修改人 修改日期 修改描述

* -------------------------------------------

*

*

*/

@Data

public class DemoResponse {

private String name;

private String result;

}

其中@BizModel @BizMutation @BizQuery @RequestBean @Name,@SqlLibMapper 是nop中规定的一些注解,BizModel 类似spring中的Controlller,RequestBean 类似于spring中的RequestBody,SqlLibMapper类似于Mapper,代表存放sql的地址文件,后面会有请求案例,

第6步 ,创建资源文件

关于目录结构后面有介绍,需要按照nop规定好的结构,千万别忘了_module,这是规定一个目录为一个模块的文件,就是一个空文件

app-demo.beans.xml

ioc:type="@bean:id" ioc:bean-method="build">

DemoEntity.xmeta

if(entity.status == 1)

return "ACTIVE";

return "INACTIVE";

]]>

app.orm.xml

className="io.nop.orm.support.DynamicOrmEntity" registerShortName="true">

mandatory="true" primary="true"/>

demo.sql-lib.xml

select o from DemoEntity o where o.name like ${'%' + name + '%'}

第7步 ,运行项目,项目启动以后,会在项目目录下生成一个_dump 的目录,里面可以供开发者调试

Nop平台调试模式启动Nop平台的调试模式,只需设置nop.debug=true。在调试模式下,可以通过以下链接获取所有服务定义:

/p/DevDoc__graphql/p/DevDoc__beans

例:

127.0.0.1:8080/p/DevDoc__graphql 可以看到对外暴露的所有服务定义。 例如: type DemoEntity{ "SID" sid : String "名称" name : String "状态" status : Int "状态文本" status_label : String } 127.0.0.1:8080/p/DevDoc__beans 可以查看所有对象定义。 例如:

注意事项

前端的REST链接根据对象名和方法名自动推定,无需手工指定,固定格式为: /r/{bizObjName}__{bizMethod}。 注意是两个下划线。@BizQuery允许通过GET和POST两种HTTP方法调用,而@BizMutation只允许通过POST方法调用。通过GET方式调用时,可以通过URL链接来传递参数,例如/r/Demo__hello?message=abc。通过POST方式调用时可以通过URL来传参,也可以通过Http的body使用JSON格式传递。可以通过@Name来一个个的指定前台参数,也可以通过@RequestBean将前台传递过来的所有参数包装为指定的JavaBean类型。服务函数总是返回POJO对象,并指定按照JSON格式进行编码。

示例API访问

REST

例1,带响应状态:

访问127.0.0.1:8080/r/Demo__hello?message=abc响应:

{ “data”: “Hi,abc”, “status”: 0 }

例2,不带响应状态:

访问127.0.0.1:8080/p/Demo__hello?message=abc响应: Hi,abc

其他类似:

127.0.0.1:8080/r/DemoEntity__findByName?name=abc 127.0.0.1:8080/r/Demo2Entity__findByName?name=abc

GraphQL

例1(查询),关键字query:

访问POST 127.0.0.1:8080/graphql 请求体: query{ Demo__hello(message:“2343”) } 响应 { “data”: { “Demo__hello”: “Hi,abc” } }

例2(更新),关键字mutation:

访问POST 127.0.0.1:8080/graphql 请求体: mutation { Demo__testOk( name: “zhagnsan”, email: “123@qq.com” ) { name result } } 响应 { “data”: { “Demo__hello”: “Hi,abc” } }

例3(保存),关键字mutation:

访问POST 127.0.0.1:8080/graphql请求体: mutation { DemoEntity__saveEntity(data: {name: “zhagnsan”, status: 1}) { sid name status } }响应 { “data”: { “DemoEntity__saveEntity”: { “sid”: “23410bb4cdd74fc7bd2c1795059ff8a1”, “name”: “zhagnsan”, “status”: 1 } } }

例2跟例3有点类似于spring中的加RequestBody跟不加RequestBody的区别, 用 @RequestBean注解就直接写属性字段,@Name需要把方法中的对象参数名写在前面

文件命名规范

平台内所有会被自动识别并处理的文件模式已在此文档中列举:

Nop平台内部约定了一定的资源路径模式,会自动查找满足模式的文件进行加载。

META-INF/services

io.nop.core.initialize.ICoreInitializer 使用Java内置的ServiceLoader机制注册分级初始化函数

CoreInitialization会读取所有CoreInitializer,按照优先级顺序执行

bootstrap.yaml 静态全局配置文件,其中的内容优先级最高,不会被外部配置所覆盖

application.yaml 全局的配置文件

application-{profile}.yaml 全局的配置文件,profile是通过nop.profile指定的部署环境名称

_vfs/

/_delta

/{deltaDir} 这里是delta层的名称,缺省会加载default层

这里的文件会覆盖标准路径的同名文件

/dict

{dictName}.dict.yaml 字典文件不会被自动加载,但是通过dictName加载指定字典文件

/i18n

/{locale}

{moduleName}.i18n.yaml I18nManager初始化的时候会自动加载所有i18n文件

/nop

/aop

{xxx}.annotations Nop的AOP代码生成器生成包装类时会读取所有的annotations文件,并为每个标注了指定注解的类生成AOP包装类

/autoconfig

{xxx}.beans NopIoC会自动扫描解析所有后缀名为beans的文件,加载其中的beans.xml文件

/core

/reigstry

{xxx}.register-model.xml 初始化时会自动扫描所有registry-model.xml文件,并注册对应的DSL模型解析器,

将它们和特定的文件类型关联起来

/dao

/dialect

/selector

{xxx}.selector.xml 初始化时会自动扫描所有selector.xml文件,加载数据库方言的匹配规则

{dialectName}.dialect.xml 数据库方言定义文件,按照dialectName来加载

/main

/auth

/main.action-auth.xml 全局的操作权限和菜单定义文件,在其中通过x:extends来引用其他权限文件

/main.data-auth.xml 全局的数据权限定义文件,在其中通过x:extends来引用其他数据权限文件

/{moduleId} Nop模块的moduleId必须是nop/auth这种两级目录结构

_module 每个Nop模块下都有一个_module文件来标记它是模块。

/beans

app-{xxx}.beans.xml NopIoC启动时会自动扫描每个模块的beans目录下以`app-`为前缀的beans.xml文件

/model

{bizObjName}.xbiz 所有的服务对象原则上都是要在beans.xml中注册,然后再通过对象名查找到对应的xbiz和xmeta文件

{bizObjName}.xmeta NopDynEntity对象采用了简化注册流程,直接向BizObjectManager注册,没有在beans.xml中定义服务对象

/orm

app.orm.xml NopOrm引擎初始化的时候会加载所有模块的orm目录下的app.orm.xml模型文件

/pages

/{bizObjName}

{pageId}.page.yaml 可以配置页面文件在系统初始化的情况下加载,它引用的view模型因此被连带加载

{bizObjName}.view.xml View模型不会被自动加载,但是一般会放置在这个位置

第1篇就先写这么多,后面再慢慢完善

参考链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。