Junx-EP开发手册-开始使用

  |   0 评论   |   0 浏览

一、项目说明

Junx-EP项目是模块化项目,目前一共包含了以下11个模块:

junx-ep
  |-junx-ep-auth:基于shiro实现的认证与鉴权模块,支持简单RAM认证鉴权配置与ShiroRealm的复杂认证鉴权。
  |-junx-ep-codegen:代码生成模块后台Java实现,引入了本jar过后,相当于给系统添加代码生成功能。
  |-junx-ep-codegen-ui:EP框架基于Layui默认实现的生成模块前端html和js代码
  |-junx-ep-core:EP框架的微内核jar包,提供了核心的mybatis封装、Result、GlobalExceptionHandler等核心类定义。
  |-junx-ep-fs:文件上传模块,提供了文件上传与存储功能,引入本jar过后,相当于引入了文件上传功能。
  |-junx-ep-pvc:持久化版本控制模块,引入本模块jar包,相当于引入了基于数据库的模块版本控制,用于模块的数据库表结构初始化与后期版本升级。
  |-junx-ep-qlexp:封装的淘宝QLExpress包,提供了规则引擎功能。
  |-junx-ep-scheduler:基于Quartz封装的定时任务模块,引入本jar包,即可拥有分布式定时任务管理能力。
  |-junx-ep-scheduler-ui:EP框架基于Layui实现的定时任务前端html和js代码。
  |-junx-ep-sys:基于core包实现的默认系统框架,包含了系统登录及其系统管理等基础功能,含用户管理、组织管理、角色权限、菜单管理、系统日志等功能基础,是所有含有菜单的功能模块的基础模块。
  |-junx-ep-sys-ui:EP基于Layui实现的系统基础功能,含用户登录、含用户管理、组织管理、角色权限、菜单管理、系统日志等功能的前端html和js,以及用到的基础js、css等前端代码文件。

EP框架的jar包中,自带前端html和js代码,通过webinjar的方式,添加到jar包中,再与springboot做集成,因此框架的UI界面是通过jar包进行引入的,后期可以统一进行升级,比较方便和简单。

二、使用方式

1、仅使用ep-core微内核

微内核仅提供后端开发相关能力,提供了轻度的mybatis封装,不过度封装,支持mybatis-plus注解,但是不提供mybatis-plus一样的封装,个人觉得mybatis-plus封装有些过度,不应经常使用。

Maven:

		<dependency>
			<groupId>io.github.junxworks</groupId>
			<artifactId>junx-ep-core</artifactId>
			<version>2.1.0</version>
		</dependency>

1.1 ORM

引入core包后,即拥有了轻度封装的orm能力,下面是core提供的BaseMapper:

public interface BaseMapper {

	/**
	 * 解析实体类并将其写入到数据库中,排除空值字段写入,Object必须含有io.github.junxworks.ep.core.orm.annotations.Table注解。
	 * 写入数据后,系统默认生成ID字段回写,ID字段默认名称为id,如果id不是这个字段的,请不要调用此方法,将本方法复制到自己的mapper中,修改ID字段名即可,如下:
	 * 
	 * 	@InsertProvider(type = MybatisObjectSqlProvider.class, method = "insertWithoutNull")
	 * 	@Options(useGeneratedKeys = true, keyProperty = "xxxId")
	 *  public int insertWithoutNull(Object entity);{
	 *  	......
	 *  
	 *  }
	 *
	 * @param entity 需要写入数据库的实体对象
	 * @return 成功写入记录条数
	 */
	@InsertProvider(type = MybatisObjectSqlProvider.class, method = "insertWithoutNull")
	@Options(useGeneratedKeys = true, keyProperty = SqlGenerator.ID_COLUMN)
	public int insertWithoutNull(Object entity);

	/**
	 * 将实体类批量写入数据库,会采用第一个实体类的表结构进行sql解析,不支持多种实体类混合写入。
	 *
	 * @param entities 需要写入数据库的实体对象集合
	 * @return 成功写入记录条数
	 */
	@InsertProvider(type = MybatisObjectSqlProvider.class, method = "insertBatch")
	public int insertBatch(List<?> entities);

	/**
	 * 解析实体类并将其写入到数据库中,保留空值字段写入,Object必须含有io.github.junxworks.ep.core.orm.annotations.Table注解。
	 * 写入数据后,系统默认生成ID字段回写,ID字段默认名称为id,如果id不是这个字段的,请不要调用此方法,将本方法复制到自己的mapper中,修改ID字段名即可,如下:
	 * 
	 * 	@InsertProvider(type = MybatisObjectSqlProvider.class, method = "insertWithNull")
	 * 	@Options(useGeneratedKeys = true, keyProperty = "xxxId")
	 *  public int insertWithNull(Object entity);{
	 *  	......
	 *  
	 *  }
	 *
	 * @param entity 需要写入数据库的实体对象
	 * @return 成功写入记录条数
	 */
	@InsertProvider(type = MybatisObjectSqlProvider.class, method = "insertWithNull")
	@Options(useGeneratedKeys = true, keyProperty = "id")
	public int insertWithNull(Object entity);

	/**
	 * 根据主键更新一条记录,排除空值字段写入,实体类必须要包含io.github.junxworks.ep.core.orm.annotations.Table注解,io.github.junxworks.ep.core.orm.annotations.PrimaryKey主键或id属性。
	 *
	 * @param entity 需要更新数据库的实体对象
	 * @return 成功更新的记录条数
	 */
	@UpdateProvider(type = MybatisObjectSqlProvider.class, method = "updateWithoutNull")
	public int updateWithoutNull(Object entity);

	/**
	 * 根据主键更新一条记录,保留排除空值字段写入,实体类必须要包含io.github.junxworks.ep.core.orm.annotations.Table注解,io.github.junxworks.ep.core.orm.annotations.PrimaryKey主键或id属性。
	 *
	 * @param entity 需要更新数据库的实体对象
	 * @return 成功更新的记录条数
	 */
	@UpdateProvider(type = MybatisObjectSqlProvider.class, method = "updateWithNull")
	public int updateWithNull(Object entity);

	/**
	 * 根据主键删除一条记录,实体类必须要包含io.github.junxworks.ep.core.orm.annotations.Table注解,io.github.junxworks.ep.core.orm.annotations.PrimaryKey主键或id属性。
	 *
	 * @param entity 需要删除数据库的实体对象
	 * @return 成功删除的记录条数
	 */
	@DeleteProvider(type = MybatisObjectSqlProvider.class, method = "deleteByPK")
	public int deleteByPK(Object entity);

	/**
	 * 根据实体类class与id,删除一条数据库记录,实体类必须要包含io.github.junxworks.ep.core.orm.annotations.Table注解,io.github.junxworks.ep.core.orm.annotations.PrimaryKey主键或id属性。
	 *
	 * @param entityClass 需要删除数据库的实体对象类
	 * @param id 关键字值
	 * @return 成功删除的记录条数
	 */
	@DeleteProvider(type = MybatisObjectSqlProvider.class, method = "deleteByID")
	public int deleteOneById(@SuppressWarnings("rawtypes") @Param("class") Class entityClass, @Param("id") Long id);

	/**
	 * 根据实体类class与id,查询一条数据库记录,实体类必须要包含io.github.junxworks.ep.core.orm.annotations.Table注解,io.github.junxworks.ep.core.orm.annotations.PrimaryKey主键或id属性。
	 *
	 * @param entity 需要查询数据库的实体对象类
	 * @param id 关键字值
	 * @return 查询结果 
	 */
	@SelectProvider(type = MybatisObjectSqlProvider.class, method = "getOneByPK")
	public Map<String, Object> selectMapByID(@SuppressWarnings("rawtypes") @Param("class") Class entityClass, @Param("id") Long id);

	/**
	 * 根据实体类class与id,查询一条数据库记录,实体类必须要包含io.github.junxworks.ep.core.orm.annotations.Table注解,io.github.junxworks.ep.core.orm.annotations.PrimaryKey主键或id属性。
	 *
	 * @param entity 需要查询数据库的实体对象类
	 * @param pkName 关键属性列名
	 * @param id 关键字值
	 * @return 查询结果
	 */
	@SelectProvider(type = MybatisObjectSqlProvider.class, method = "getOneByPKNameAndValue")
	public Map<String, Object> selectMapByPKNameAndValue(@SuppressWarnings("rawtypes") @Param("class") Class entityClass, @Param("pkName") String pkName, @Param("pkValue") Object pkValue);
}

业务自身mapper继承BaseMapper即可,再配合io.github.junxworks.ep.core.orm.annotations包中的注解,可以达到动态解析实体成对应sql的目的,当然也可以不用annotations包的注解,有默认解析机制,将Entity实体属性映射成DB字段,DB字段和表名默认是驼峰转蛇形(下划线)的方式,可以通过设置EntityResolver.turnOffCamelFieldToSnake()与EntityResolver.turnOffCamelTableNameToSnake()设置成保留驼峰命名。

core里面轻度封装mybatis,实现了一些基础的最常用的方法封装,极大提升开发效率,这里采用的Entity实体翻译sql模式,只要继承了BaseMapper,就可以翻译任何实体类,当然如果为了规范,可以采用TBaseMapper,指定实体泛型。而且基于SQL翻译,可以优雅的实现表字段部分更新逻辑,当你有一个功能,业务侧只编辑某一张实体表的某几个字段,然后传到后端,正常实现后端把所有传过来的字段判断一下,塞进一个实体中,下面是基于mybatis-plus的实现部分字段更新代码:

LambdaUpdateWrapper<OilUser> userUpdateWrapper = new LambdaUpdateWrapper<>();
            userUpdateWrapper.set(OilUser::getUsername, user.getUsername());
            userUpdateWrapper.set(OilUser::getNickName, user.getNickName());
            userUpdateWrapper.set(OilUser::getTel, user.getTel());
            userUpdateWrapper.set(OilUser::getEmail, user.getEmail());
            if (!StringUtils.isEmpty(user.getPassword())) {
                userUpdateWrapper.set(OilUser::getPassword, passwordEncoder.encode(user.getPassword()));
            }
            userUpdateWrapper.eq(OilUser::getId, user.getId());
            oilUserMapper.update(null, userUpdateWrapper);

下面这个是基于ep-core实现的代码:

@Override
	public int updateStudent(StudentDto studentDto) {
		DStudentUpdateModel studentUM = new DStudentUpdateModel();
		BeanUtils.copyProperties(studentDto, studentUM);
		return tableDemoMapper.updateWithNull(studentUM);
	}

大量简化了这种无脑代码,提升系统扩展能力,新增表字段过后,再也不用到处去找地方调整代码了。

下面是基于core开发的一些样例代码:

EP框架之非入侵分页查询

Junx-ep实现部分更新表字段的方法

2、仅使用ep-auth鉴权认证

ep-auth基于shiro开发的RBAC角色权限控制模块,用起来极为简单,首先引入jar包:

Maven:

		<dependency>
			<groupId>io.github.junxworks</groupId>
			<artifactId>junx-ep-auth</artifactId>
			<version>2.1.0</version>
		</dependency>

2.1 认证测试

我们先起一个简单的web项目,测试一下ep-auth的效果,下面这个是测试项目,一个最基础的springboot的web项目,包含一个controller,返回Result对象:

@RestController
@RequestMapping("/test")
public class TestController {

	@GetMapping()
	public Result test() {
		return Result.ok("1");
	}

}

服务器端口为9999,上下文为test,访问如下URL地址http://localhost:9999/test/test能得到应答:

1684854891265748992.png

然后我们在application启动类上加入注解@EnableEPShiroProxy


@EnableEPShiroProxy
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class EpTestApplication {

	public static void main(String[] args) {
		SpringApplication.run(EpTestApplication.class, args);
	}

}

application.yml配置文件中加入下面这段auth配置:

junx:
  ep:
    auth:
      shiro:
        global-session-timeout: 86400000 #缓存过期时间,redis缓存有效,mem缓存无效
        filters: #过滤配置,anon表示匿名访问,ep为基于ep实现的认证逻辑
          "[/**/*.js]": anon
          "[/**/*.html]": anon
          "[/**/*.jpg]": anon
          "[/**/*.png]": anon
          "[/**/*.ico]": anon
          "[/**/css/**]": anon
          "[/**/plugins/**]": anon
          "[/**/fonts/**]": anon
          "[/**/verification-codes]": anon
          "[/**/login]": anon
          "[/**/system-name]": anon
          "[/**]": ep
        simple-accounts: #简单账号配置,请求方在header中带入key和secret即可访问有权限的url路径
          - epRamKey: test
            epRamSecret: "123"
            authorizes: /**

同时新增自己项目的AuthorizingRealm对象,注入到bean配置中,如果不注入自己的AuthorizingRealm对象,则默认会采用EP实现的逻辑,如果没有引用ep-sys模块,则可能会出现异常。我们这里只测试,不做认证。下面是AuthorizingRealm的实现。

public class TestAuthorizingRealm extends AuthorizingRealm {
	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof DefaultToken;
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//根据自己业务逻辑实现
		return null;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//根据自己业务逻辑实现
		return null;
	}
}

在bean配置中加入

	@Bean
	TestAuthorizingRealm testAuthorizingRealm() {
		return new TestAuthorizingRealm();
	}

加入ep-auth过后,再访问刚才那个url地址,就会出现如下结果

1684860381114757120.png

2.2 RAM认证

下面测试一下简单认证好使不好使,上面配置中配置了账户test密码123,可以访问的路径是所有,那用postman试一试,在header中计入两个认证属性。

1684861780716253184.png

请求结果

1684861918432030720.png

2.3 CacheManager缓存管理

ep-auth提供了2种缓存管理实现,1是基于本地内存的EPShiroMemCacheManager,这也是默认的认证缓存管理实现,第2种就是基于redis实现的EPShiroRedisCacheManager,要使用基于redis的分布式缓存,需要在bean注入的时候注入EPShiroRedisCacheManager,如下:

	@Bean
	public CacheManager epCacheManager() {
		return new EPShiroRedisCacheManager();
	}

同时需要配置项目的redis配置,具体参考springboot的redis配置。

对于测试环境或者一些很小的个人项目,可以直接使用本地内存的缓存即可。

3、使用ep-sys模块

ep-sys是包含系统管理的基础开发框架,主要面向的是后端开发人员,原生是基于springboot+ep+layui实现的,当然可以把layui换成其他MVVM框架,需要自己实现。在项目中引入ep-sys的jar包。

Maven:

                <dependency>
			<groupId>io.github.junxworks</groupId>
			<artifactId>junx-ep-sys</artifactId>
			<version>2.1.0</version>
		</dependency>

首先,springboot项目一定是web项目,这里会用到controller与数据库,在springboot的application启动类上加入@EnableEPSys复合注解,即可开启ep框架,并且初始化数据库表结构。

/**
 * 开启EP基础系统模块,含系统支撑以及EP认证
 *
 * @ClassName:  EnableEPSys
 * @author: Michael
 * @date:   2020-7-19 12:17:47
 * @since:  v1.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EnableBaseEPModules //EP基础系统模块
@EnableEPShiroProxy //开启EP认证
public @interface EnableEPSys {
}

3.1库表结构初始化

ep-sys在启动时候,会检查主库(如果是多数据源,则以@Primary定义的为主)的ep_s_profile表,检查每个模块的版本号,是否需要执行db升级,执行pvc持久化版本控制相关升级操作,第一次初始化库的时候,会在主库执行对应的sql,生成表结构和数据,sql脚本在各个模块的pvc包下:

1684866710420156416.png

profile中定义了当前最新的version版本号,如果ep_s_profile中模块版本号比jar包中的小,则会挨个执行每个sql脚本,直到最新的version。注意,这里数据库版本只支持升级,不能降级。

3.2系统默认登录页面

拿demo项目举例,demo项目上下文demo,默认登录页面为/eui/login.html,最终访问的URL地址为{系统域名}/demo/eui/login.html,系统默认超管账号admin,密码123456。

1684868997251166208.png

为了简化用户登录,只有当客户输错密码后,才会弹出验证码验证,不用每次登录都输入验证码。默认用户在连续输入5次错误密码时,账号会被锁定。如果用户账号被锁定,则需要在用户管理中进行修改用户状态。

EP框架基础使用先介绍到这里,下章继续介绍其他功能模块。


标题:Junx-EP开发手册-开始使用
作者:michael
地址:https://blog.junxworks.cn/articles/2023/07/28/1690537937626.html