javaEE6java8的关注_GitHub - howsun/howsun-javaee-framework: 这是一款特别适用于中小企业应用的JavaEE快速开发框架。它是居于Spring容器之上...

howsun-javaee-framework

Java应用层框架

版本:1.0.8

1、项目介绍

这是一款居于Spring容器之上特别适用于中小企业应用的JavaEE快速开发框架,具有如下特性:

1、跨服务调用(跨Spring容器,也可以使用类似Netty的通信中间件来实现)

2、封装DAO操作,大大简化了数据库操纵业务,统一的查询参数接口,统一的分页对象,可创建单机可集群环境的数据唯一ID。支持Hibernate,JPA和MongoDB操纵

3、统一配置管理,配置文件不随工程一起发布,可以有效地避免线上线下配置文件混乱问

4、统一日志管理,不需要做太多的日志配置,自动生成日志配置模板,并将日志记录到指定的文件夹中

5、封装了Redis客户端,取代Memcache

6、简化了Json操作

7、提供了分页、工具类封装的JSP标签库

8、大量工具包:如安全、Web、断言、编码等40多种

2、引入框架构件

Maven引入

org.howsun

howsun-jee-framework

1.0.8

需要注意,必须保证内部仓库中已经存在构件。

非Maven工程,请在build目录下载howsun-jee-framework-1.0.8.jar,并手工将其和依赖构件全部加入工程的ClassPath

3、定制统一配置的名称空间

步骤:

在工程Source下创建META-INF目录

目录中创建howsun-config.properties配置文件

文件中只需一行:namespace=空间名

统一这种配置后,框架会在工程所在的磁盘根目录下创建opt/hjf/{namespace}子目录,用于存放配置文件、日志文件。

4、统一日志管理

框架运行时,第一次会在项目同分区中创建/opt/hjf/${空间名}目录,并自动写一份log4j.properties的配置文件

日志级别默认为info

日志分别往控制台和文件中传送

日志内容文件在/opt/hjf/logs/${空间名}.log

按天切分存储

5、统一服务管理

以实际例子说明应用,假如某项目含有如下服务:

WWW:主站服务,既是个Web工程

CMS:资源管理服务,重点是数据存储和操纵。普通Java工程

SNS:用户管理服务,并含有复杂社交关系应用。普通Java工程

如果WWW要调用CMS服务中接口,就涉及到跨服务,目前1.8版是跨Spring容器来实现的,具体使用如下。

(1)、配置

步骤:

新建一普通Java工程,例如howsun-sns;

设定howsun-config.properties中的namespace=howsun_sns

在/opt/hjf/${空间名}目录下手工创建一份Spring配置文件,文件名为${空间名}-sc.xml;即/opt/hjf/howsun_sns/sns-sc.xml

要将cms服务中接口纳入到框架统一服务中管理,需要在接口和实现类上标注:@ContractService,其中实现类上的注解需要指定bean的id

示例:

@ContractService

public interface PersonService{

}

@ContractService("personService")

public class PersonServiceImpl implements PersonService{

}

(2)、跨服务调用

现在www服务需要调用sns服务的PersonService,步骤如下:

新建一Java Web工程,例如howsun-www;

设定howsun-config.properties中的namespace=howsun_www

在/opt/hjf/${空间名}目录下手工创建一份Spring配置文件,文件名为${空间名}-sc.xml;即/opt/hjf/howsun_www/www-sc.xml

在配置文件中装配ContractServices Bean并注入modules属性,如:

在Controller类中注入ContractServices,ContractServices来调用PersonService接口

示例:

//配置文件

//Java文件

@Controller

public class HomeController{

@Resource

private ContractServices contractServices;

@RequestMapping("/{nickname}/index")

public String index(@PathVariable String nickname, Model model){

PersonService personService = contractServices.getContractService(PersonService.class);

model.addAttribute("person",personService.getPerson(nickname));

}

}

6、统一数据库操纵

框架中封装了三种持久层框架,分别是Hibernate、JPA、Mongo4J。其中前两者是针对RDBMS,后者是针对NoSQL MongoDB

使用时只需在配置中增加id为genericDao的bean,实现类可以为上述三种的任意一种

实现类为Hibernate、JPA时,需要注入相应的Session工厂和数据源;为Mongo4j时,需要MongoDB连接池。这些都可以在各自的软件厂商找到使用说明

6.1、重点数据操纵方法

6.1.1、事务方法

■ 保存实体

void save(Object object)

■ 更新对象

void update(Object object)

■ 根据条件更新记录

public int update(Class entityName, String[] fields, Object[] values, Serializable id)

返回更新的结果数

■ 批量更新记录

public int updateByBatch(Class entityName, String fields, String condition, Object[] values)

返回批量更新的记录个数

■ 根据主键值删除记录

public int delete(Class entityClass, Serializable... entityids)

返回删除的记录个数

■ 删除一个已知的记录

public int delete(Object object)

返回删除的记录个数

■ 根据条件和参数删除记录

public int delete(Class entityClass, String condition, Object[] params)

返回删除的记录个数

注意:

这些方法都需要事务,Service层标上@Transactional

MongoDB目前还不支持事务

6.1.2、非事务方法

■ 根据主键值查询一条记录

public T find(Class entityClass, Serializable entityid)

返回与实体名一致的单个实体对象

■ 根据条件查询多条记录,可以设分页、排序

public List finds(Class entityClass, String fields, Page page,String condition, Object[] params, OrderBean order)

返回与实体名一致的多个实体集合对象

■ 统计某表中的总记录数

long getCount(Class entityClass);

返回总记录数

■ 根据条件统计某表中的总记录数

long getCount(Class entityClass, String condition, Object[] params);

返回记录数

■ 模拟自增长主键,不支持同步锁,适合数据频繁低的应用中

Long nextId(Class> entityClass);

返回下一个主键值

注意:

这些方法都不需要事务,Service层标上@Transactional,还需要调用方法上加上@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)以提高性能

6.2、数据分页

构建一个Page对象:new Page(当前页码,每页大小,页码上的URL地址)

将对象送到分页查询方法中去

方法执行完后,将对象放在HttpServletRequest作用域中,Key为Page. SCOPE_NAME

JSP页面上引入框架的标签库:

JSP页面上利用分页标签显示分页结果:

效果示例:

6.3、创建主键

支持大规模数据库集群环境中无重复主键

主键类型:java.lang.Long,因此表中预先要设计为bigint型主键类型

org.howsun.dao.IDGenerator .getUniqueID ()

6.4、增强的Seeker参数查询

只需编写一个自定义的查询参数类实现Seeker接口,或者继承GeneralSeeker类

下面以实现在MongoDB中存储的Person记录查询为例具体说明,首页新建一个PersonSeeker类:

public class PersonSeeker extends GeneralSeeker implements Seeker {

private static final long serialVersionUID = 9183107407293358219L;

/**最大时间间隔查询为90天**/

public static final long TIME_SLICES = 90L * 24 * 3600 * 1000;

static{

ORDER_FIELDS.put("created", "创建时间");

ORDER_FIELDS.put("updated", "修改时间");

ORDER_FIELDS.put("followers", "粉丝数量");

ORDER_FIELDS.put("friends", "好友数量");

ORDER_FIELDS.put("ffs", "互相关注数量");

ORDER_FIELDS.put("birthday", "生日");

ORDER_FIELDS.put("auth.logonWithMonth", "月访问量");

ORDER_FIELDS.put("auth.logonWithWeek", "周访问量");

ORDER_FIELDS.put("auth.logonWithDay", "日访问量");

ORDER_FIELDS.put("auth.logonTotal", "总访问量");

ORDER_FIELDS.put("auth.lastLogonTime", "最后访问时间");

}

/**按用户ID查寻**/

protected Set personIds = new HashSet(0);

/**按昵称查**/

protected String nickname;

/**按真实姓名查**/

protected String realname;

/**按用户名查**/

protected String username;

/**是否锁定账号**/

protected Boolean locked;

/**按授了权的App查**/

protected Set appIds = new HashSet(0);

/**是否存在的字段**/

protected Map existsFields = new HashMap(1,1);

/**按起始创建时间查**/

protected Date startCreated;

/**按结束创建时间查**/

protected Date endCreated;

/**关注我的人**/

protected int followers;

/**好友数量:我关注的人数**/

protected int friends;

/**互相关注数量**/

protected int ffs;

/* (non-Javadoc)

* @see com.chinaot.core.service.Seeker#buildCriteria()

*/

@Override

public Criteria buildCriteria(){

Criteria criteria = new Criteria();

List criteras = new ArrayList(1);

if(Collections.notEmpty(personIds)){

if(personIds.size() == 1){

for(Long id : personIds){

criteras.add(Criteria.where("_id").is(id));

break;

}

}else{

criteras.add(Criteria.where("_id").in(personIds));

}

}

if(Strings.hasLength(username)){

criteras.add(Criteria.where("auth.accounts.username").is(username));

}

//昵称是唯一值,应精确查找

if(Strings.hasLength(nickname)){

criteras.add(Criteria.where("nickname").is(nickname));

}

if(Strings.hasLength(realname)){

criteras.add(Criteria.where("realname").regex(String.format(MongoGenericDaoUtil.REGEX_LIKE, realname)));

}

if(followers > 0){

criteras.add(Criteria.where("followers").gte(followers));

}

if(friends > 0){

criteras.add(Criteria.where("friends").gte(friends));

}

if(ffs > 0){

criteras.add(Criteria.where("ffs").gte(ffs));

}

if(Collections.notEmpty(appIds)){

criteras.add(Criteria.where("apps.appId").in(appIds));

}

if(locked != null){

List temps = new ArrayList();

temps.add(Criteria.where("auth.locked").exists(false));

temps.add(Criteria.where("auth.locked").is(locked));

criteras.add(new Criteria().orOperator(temps.toArray(new Criteria[]{})));

}

if(existsFields != null && existsFields.size() > 0){

for(Map.Entry exist : existsFields.entrySet()){

criteras.add(Criteria.where(exist.getKey()).exists(exist.getValue()));

}

}

if(criteras.size() > 0){

criteria.andOperator(criteras.toArray(new Criteria[]{}));

}

return criteria;

}

@Override

public RQLConditionbind buildRQL() {

return throw new RuntimeException("不支持RDBMS数据库查询");

}

//Setter&Getter...

}

public class PersonServiceImpl implements PersonService{

//在Service类实现查询的方法,仅如下几行代码就够了

public List<Person> getPersons(Seeker seeker, Set<String> fields, Page page){

//创建MongoDB查询对象

Query query = Query.query(seeker.buildCriteria());

//需要查询哪些字段

MongoGenericDaoUtil.bindFields(query, PersonUtil.checkFields(fields));

//排序

MongoGenericDaoUtil.bindOrders(query, seeker.getOrderBean());

//分页

MongoGenericDaoUtil.bindPaging(Person.class, dao.getMongoTemplate(), query, page);

//查询结果

List<Person> persons = dao.getMongoTemplate().find(query, Person.class);

return personj;

}

}

可见使用Seeker接口的参数查询,业务层代码更加简洁。

7、Redis缓存客户端封装

注意:Redis客户端使用的是jedis。

配置文件:

注意:由于jedis内部使用了线程池,客户没必须使用多例对象,这里做了个CacheHelper静态工具类,当客户端对象在实例化时,同步为CacheHelper赋值,所以在所有要访问缓存的地方直接调用CacheHelper.get(xxx)、CacheHelper.set(xxx,xx)方法即可

8、工具包

■安全工具

org.howsun.util.security.Codings

org.howsun.util.security.AES

■字符串工具

org.howsun.util.Strings

■日期工具

org.howsun.util.Dates

■断言工具

org.howsun.util. Asserts

■JavaBean工具

org.howsun.util. Beans

■中文拼音工具

org.howsun.util.ChinesePinyin

■文件工具

org.howsun.util. Files

■文件流工具

org.howsun.util.Streams

■IO工具

org.howsun.util.IOs

■数值工具

org.howsun.util.Numbers

■随机数工具

org.howsun.util.Randoms

■IP工具

org.howsun.util.Ips

■Web工具

org.howsun.util.Webs

其它未列的请查看JavaDoc说明

敬告:howsun2.0将不再兼容1.x版本,新版是居于Spring4.0重新架构设计的,敬请期待。

作者:张纪豪(zhangjihao@sohu.com)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值