Merge branch 'dev' into dev

This commit is contained in:
Wendal Chen 2017-12-11 22:00:34 +08:00 committed by GitHub
commit d3f58ee37a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
86 changed files with 2209 additions and 113 deletions

View File

@ -1,5 +1,16 @@
# NB进化史
## 2.0-RC2 "?"
* 变更:
* add: new NbApp()可以不传类名,从堆栈自动推断
* add: starter-mongodb by @qingerg
* add: starter-tomcat by @ben
* add: starter-beetlsql 来自beetl的SQL解决方案
* add: starter-sharding-jdbc 分库分表
* add: starter-thymeleaf 模板引擎
* fix: jetty扫描websocket的endpoint有问题
## 2.0-RC "属于"
首先,必须高亮一下[@qinerg](https://github.com/qinerg)提交的[starter-undertow](https://gitee.com/nutz/nutzboot/tree/dev/nutzboot-starter-undertow),嗷嗷嗷. Jetty与Undertow任意切换^_^

View File

@ -18,7 +18,7 @@ import org.nutz.mvc.annotation.*;
@IocBean
public class MainLauncher {
@Ok("raw")
@At("/time/now")
public long now() {
@ -50,16 +50,17 @@ public class MainLauncher {
- [ ] mqtt
- [ ] pure tcp/udp
- [ ] Rpc类启动器
- [x] [Dubbo](http://dubbo.io/)
- [x] [zbus](http://zbus.io)
- [x] [Dubbo](http://dubbo.io/) 阿里出品的高性能RPC平台
- [x] [zbus](http://zbus.io) 国产知名RPC平台
- [ ] [motan](https://github.com/weibocom/motan)
- [ ] 其他
- [x] Ngrok内网穿透
- [x] Ngrok 内网穿透,轻松获取外网地址
- [ ] 数据库类相关
- [ ] 关系型数据库
- [x] Jdbc连接池
- [x] Jdbc连接池,默认使用druid,带监控功能
- [x] [sharding-jdbc](https://github.com/shardingjdbc/sharding-jdbc) 分库分表
- [x] Nutz.Dao
- [ ] BeetlSql
- [x] [BeetlSql](http://ibeetl.com/guide/#beetlsql) 基于Beetl的SQL框架
- [ ] Hibernate
- [ ] mybatis
- [ ] 非关系型数据库
@ -75,33 +76,40 @@ public class MainLauncher {
- [x] Nutz.Mvc
- [ ] 安全鉴权
- [x] [Shiro](http://shiro.apache.org)
- [ ] 分布式Session
- [x] [Shiro+LCache](https://github.com/nutzam/nutzmore/tree/master/nutz-plugins-cache)基于shiro/jedis/插件的分布式可持久化的session缓存
- [ ] 计划任务
- [x] [Quartz](http://www.quartz-scheduler.org)
- [ ] 模板引擎
- [x] [Beetl](http://ibeetl.com/)
- [x] [Beetl](http://ibeetl.com/)
- [x] [jetbrick-template](https://github.com/subchen/jetbrick-template-2x)
- [ ] Vecloity
- [ ] FreeMarker
- [ ] Thymeleaf
- [x] Thymeleaf by [温泉](https://github.com/ywjno)
- [ ] 消息队列
- [x] disque
- [x] disque redis作者的另一作品
- [ ] zeromq
- [ ] rabbitmq
- [ ] rocketmq
- [ ] activemq
- [ ] zbus
- [ ] 工作流
- [ ] [uflo2](https://github.com/youseries/uflo)
- [x] [uflo2](https://github.com/youseries/uflo) 中式工作流引擎
- [ ] Activity
- [ ] 规则引擎
- [ ] urule
- [x] [urule](https://github.com/youseries/urule) 中式规则引擎
- [ ] drools
- [ ] 报表系统
- [x] ureport 中式报表
- [ ] drools
- [ ] 开放平台
- [x] 微信公众号开放平台
- [ ] 微信公众号开放平台
- [x] [NutzWX](https://github.com/nutzam/nutzwx) Weixin Api By Nutz
- [ ] 云平台
- [ ] [阿里云](https://aliyun.com)
- [ ] [腾讯云](https://qcloud.com)
- [ ] 缓存相关
- [x] wkcache 方法缓存
- [x] wkcache 方法缓存 by 大鲨鱼
- [ ] docker相关
- [ ] docker compose配置
- [ ] WebService
@ -110,6 +118,19 @@ public class MainLauncher {
期待您的到来,报个issue告知一下吧 ^_^
## Contributors
* 蛋蛋(提交了第一个Banner及打印逻辑)
* 胖五(nutz.io主笔)
* [qinerg](https://github.com/qinerg)(率先提交undertow)
* [温泉](https://github.com/ywjno)(提交thymeleaf)
* 科技(Rekoe,探路者,正在踩坑)
* 潇潇(howe,探路者,正在踩坑)
* 道坤(探路者,正在踩坑)
* HeTaro(探路者,正在踩坑)
* zozoh(路过...)
* wendal(到处挖坑)
## 文档
* [NutzBoot简介](doc/overview.md)
@ -118,4 +139,4 @@ public class MainLauncher {
## 授权协议
与Nutz一样, NutzBoot遵循[Apache协议](LICENSE),完全开源,文档齐全,永远免费(商用也是)
与Nutz一样, NutzBoot遵循[Apache协议](LICENSE),完全开源,文档齐全,永远免费(商用也是)

View File

@ -17,7 +17,6 @@
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.6</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -23,15 +23,9 @@
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
@ -41,7 +35,7 @@
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-dubbo</artifactId>
<version>2.0-SNAPSHOT</version>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -13,15 +13,9 @@
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>

View File

@ -26,7 +26,6 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,74 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-simple</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-simple-beetlsql</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-mvc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-beetl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-beetlsql</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jdbc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.193</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/nutz/org.nutz.boot.starter.NbStarter</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.nutz.demo.simple.MainLauncher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,56 @@
package io.nutz.demo.simple;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.beetl.sql.core.OnConnection;
import org.beetl.sql.core.SQLManager;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.boot.NbApp;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.trans.Trans;
import io.nutz.demo.simple.bean.User;
@IocBean(create = "init")
public class MainLauncher {
@Inject
protected SQLManager beetlsqlManager;
@At({ "/", "/index" })
@Ok("beetl:/index.html")
@Aop(TransAop.READ_COMMITTED)
public User index() {
User user = new User();
user.setName("admin");
return beetlsqlManager.template(user).get(0);
}
public void init() {
// 貌似BeetlSQL没有POJO --> Table的操作?
beetlsqlManager.executeOnConnection(new OnConnection<Object>() {
public Object call(Connection conn) throws SQLException {
Statement st = conn.createStatement();
st.execute("CREATE TABLE `user` (\r\n" + " `id` int(11) NOT NULL AUTO_INCREMENT,\r\n"
+ " `name` varchar(64) DEFAULT NULL,\r\n" + " `age` int(4) DEFAULT NULL,"
+ "PRIMARY KEY (`id`)" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8");
st.close();
return null;
}
});
beetlsqlManager.insert(new User("admin", 18));
beetlsqlManager.insert(new User("root", 21));
}
public static void main(String[] args) throws Exception {
Trans.DEBUG = true;
new NbApp().setArgs(args).setPrintProcDoc(true).run();
}
}

View File

@ -0,0 +1,43 @@
package io.nutz.demo.simple.bean;
/**
* 用户
*/
public class User {
private Integer id;
private Integer age;
private String name;
public User() {
}
public User(String name, Integer age) {
this.age = age;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,8 @@
jetty.port=8080
jetty.host=0.0.0.0
jdbc.url=jdbc:h2:mem:~
beetlsql.dbStyle=h2
beetlsql.debug=true
beetlsql.path=/sqls/

View File

@ -0,0 +1,7 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,9 @@
select
===
select * from user where 1=1
@if(!isEmpty(age)){
and age = #age#
@}
@if(!isEmpty(name)){
and name = #name#
@}

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>NB demo for Beetl</title>
</head>
<body>
<div>
<h2>Context Path = '${base}'</h2>
</div>
<div>
<h2>From Action name=${obj.name}, age=${obj.age}</h2>
</div>
</body>
</html>

View File

@ -16,22 +16,18 @@
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-dao</artifactId>
<version>2.0-SNAPSHOT</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jdbc</artifactId>
<version>2.0-SNAPSHOT</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>

View File

@ -26,7 +26,6 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>

View File

@ -23,10 +23,6 @@
<artifactId>nutzboot-starter-undertow</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>

View File

@ -28,15 +28,9 @@
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>

View File

@ -11,27 +11,21 @@
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-mvc</artifactId>
<version>2.0-SNAPSHOT</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>2.0-SNAPSHOT</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>

View File

@ -23,15 +23,9 @@
<artifactId>nutzboot-starter-redis</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,73 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-simple</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-simple-sharding-jdbc</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-mvc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-dao</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-sharding-jdbc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/nutz/org.nutz.boot.starter.NbStarter</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.nutz.demo.simple.MainLauncher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,71 @@
package io.nutz.demo.simple;
import java.util.List;
import org.nutz.boot.NbApp;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.impl.SimpleDataSource;
import org.nutz.dao.util.Daos;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import io.nutz.demo.simple.bean.UserOrder;
@IocBean(create = "init")
public class MainLauncher {
private static final Log log = Logs.get();
@Inject
protected Dao dao;
@At("/user/query/?")
public List<UserOrder> queryByUserId(int userId) {
return dao.query(UserOrder.class, Cnd.where("userId", "=", 1));
}
public void init() {
// 建表及插入测试数据
// shardingjdbc的表需要自己建,为了demo,这里只能迁就一下...
creare_order_table();
// 测试一下查询语句
List<UserOrder> orders = dao.query(UserOrder.class, Cnd.where("userId", "=", 1));
log.info("User A orders = " + Json.toJson(orders));
orders = dao.query(UserOrder.class, Cnd.where("userId", "=", 2));
log.info("User B orders = " + Json.toJson(orders));
}
protected void creare_order_table() {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
SimpleDataSource ds = new SimpleDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/ds_" + i);
ds.setUsername("root");
ds.setPassword("root");
NutDao dao = new NutDao(ds);
Daos.ext(dao, "_" + j).create(UserOrder.class, false);
}
}
// 分别为userId=1和userId=2插入2条记录
if (dao.count(UserOrder.class, Cnd.where("userId", "=", 1)) == 0) {
dao.insert(new UserOrder(1, 11));
dao.insert(new UserOrder(1, 18));
}
if (dao.count(UserOrder.class, Cnd.where("userId", "=", 2)) == 0) {
dao.insert(new UserOrder(2, 12));
dao.insert(new UserOrder(2, 9));
}
}
public static void main(String[] args) throws Exception {
new NbApp().setPrintProcDoc(true).run();
}
}

View File

@ -0,0 +1,57 @@
package io.nutz.demo.simple.bean;
import java.util.Date;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.EL;
import org.nutz.dao.entity.annotation.PK;
import org.nutz.dao.entity.annotation.Prev;
import org.nutz.dao.entity.annotation.Table;
@PK({ "userId", "orderId" })
@Table("t_order${t}")
public class UserOrder {
@Column("user_id")
private int userId;
@Column("order_id")
private int orderId;
@Prev(els = @EL("now()"))
private Date createTime;
public UserOrder() {
}
public UserOrder(int userId, int orderId) {
super();
this.userId = userId;
this.orderId = orderId;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}

View File

@ -0,0 +1,34 @@
package io.nutz.demo.simple.module;
import java.util.List;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.pager.Pager;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import io.nutz.demo.simple.bean.UserOrder;
@At("/user")
@IocBean
public class UserModule {
@Inject
Dao dao;
@Ok("raw")
@At("/count")
public long count() {
return dao.count(UserOrder.class);
}
@Ok("json:full")
@At("/query")
public List<UserOrder> query(@Param("..")Pager pager) {
return dao.query(UserOrder.class, Cnd.orderBy().asc("age"), pager);
}
}

View File

@ -0,0 +1,2 @@
jetty.port=8080
jetty.host=127.0.0.1

View File

@ -0,0 +1,8 @@
log4j.rootLogger=info,Console
log4j.logger.org.nutz.mvc=debug
log4j.logger.org.eclipse.jetty=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss.SSS}] %5p [%t] --- %c{1}: %m%n

View File

@ -0,0 +1,22 @@
dataSources:
ds_0: !!com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/ds_0
username: root
password: root
ds_1: !!com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/ds_1
username: root
password: root
shardingRule:
tables:
t_order:
actualDataNodes: ds_${0..1}.t_order_${0..1}
databaseStrategy:
inline:
shardingColumn: user_id
algorithmExpression: ds_${user_id % 2}
tableStrategy:
inline:
shardingColumn: order_id
algorithmExpression: t_order_${order_id % 2}

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello, So NB!</title>
</head>
<body>
Hello, So NB!
</body>
</html>

View File

@ -26,7 +26,6 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,59 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-simple</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-simple-thymeleaf</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-nutz-mvc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-thymeleaf</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/nutz/org.nutz.boot.starter.NbStarter</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.nutz.demo.simple.MainLauncher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,21 +1,22 @@
package io.nutz.demo.dubbo.rpc;
package io.nutz.demo.simple;
import org.nutz.boot.NbApp;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
public class MainLauncher {
@Ok("raw")
@At("/time/now")
public long now() {
return System.currentTimeMillis();
@At({"/", "/index"})
@Ok("th:/index.html")
public NutMap index() {
return NutMap.NEW().setv("name", "NB").setv("age", 18);
}
public static void main(String[] args) throws Exception {
new NbApp(MainLauncher.class).run();
new NbApp().run();
}
}

View File

@ -0,0 +1,2 @@
jetty.port=8080
jetty.host=127.0.0.1

View File

@ -0,0 +1,8 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.logger.org.thymeleaf=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>NB demo for Thymeleaf</title>
</head>
<body>
<div>
<h2>Context Path = '<span th:text="${#request.getAttribute('base')}">No Value</span>'</h2>
</div>
<div>
<h2>From Action name=<span th:text="${obj.name}">name</span>, age=<span th:text="${obj.age}">age</span></h2>
</div>
</body>
</html>

View File

@ -0,0 +1,59 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-simple</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-simple-uflo</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-uflo</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/nutz/org.nutz.boot.starter.NbStarter</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.nutz.demo.simple.MainLauncher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package io.nutz.demo.simple;
import org.nutz.boot.NbApp;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean
public class MainLauncher {
public static void main(String[] args) throws Exception {
new NbApp().setPrintProcDoc(true).run();
}
}

View File

@ -0,0 +1,7 @@
jetty.port=8080
jetty.host=127.0.0.1
jdbc.url=jdbc:h2:mem:~
uflo.debug=true

View File

@ -0,0 +1,10 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.logger.org.springframework=info
log4j.logger.org.hibernate=info
log4j.logger.org.quartz=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello, So NB!</title>
</head>
<body>
Hello, So NB!
<div>
<h2><a href="uflo/designer">uflo流程设计器</a></h2>
</div>
</body>
</html>

View File

@ -28,10 +28,6 @@
<artifactId>nutzboot-starter-shiro</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>

View File

@ -0,0 +1,59 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-simple</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-simple-ureport</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-ureport</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/nutz/org.nutz.boot.starter.NbStarter</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.nutz.demo.simple.MainLauncher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package io.nutz.demo.simple;
import org.nutz.boot.NbApp;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean
public class MainLauncher {
public static void main(String[] args) throws Exception {
new NbApp().setPrintProcDoc(true).run();
}
}

View File

@ -0,0 +1,5 @@
jetty.port=8080
jetty.host=127.0.0.1
ureport.repository.dir=./ureport.repo

View File

@ -0,0 +1,10 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.logger.org.springframework=info
log4j.logger.org.hibernate=info
log4j.logger.org.quartz=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello, So NB!</title>
</head>
<body>
Hello, So NB!
<div>
<h2><a href="ureport/designer">ureport报表</a></h2>
</div>
</body>
</html>

View File

@ -0,0 +1,59 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-demo-simple</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-demo-simple-urule</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter-urule</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/nutz/org.nutz.boot.starter.NbStarter</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.nutz.demo.simple.MainLauncher</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package io.nutz.demo.simple;
import org.nutz.boot.NbApp;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean
public class MainLauncher {
public static void main(String[] args) throws Exception {
new NbApp().setPrintProcDoc(true).run();
}
}

View File

@ -0,0 +1,5 @@
jetty.port=8080
jetty.host=127.0.0.1
urule.repository.dir=./urule.repo

View File

@ -0,0 +1,10 @@
log4j.rootLogger=debug,Console
log4j.logger.org.eclipse.jetty=info
log4j.logger.org.springframework=info
log4j.logger.org.hibernate=info
log4j.logger.org.quartz=info
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%-5p] %d{HH:mm:ss.SSS} %l - %m%n

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello, So NB!</title>
</head>
<body>
Hello, So NB!
<div>
<h2><a href="urule/frame">urule规则引擎</a></h2>
</div>
</body>
</html>

View File

@ -13,12 +13,18 @@
<module>nutzboot-demo-simple-redis</module>
<module>nutzboot-demo-simple-mongodb</module>
<module>nutzboot-demo-simple-beetl</module>
<module>nutzboot-demo-simple-beetlsql</module>
<module>nutzboot-demo-simple-jetx</module>
<module>nutzboot-demo-simple-mvc-ngrok</module>
<module>nutzboot-demo-simple-mvc-shiro</module>
<module>nutzboot-demo-simple-swagger</module>
<module>nutzboot-demo-simple-undertow</module>
<module>nutzboot-demo-simple-tomcat</module>
<module>nutzboot-demo-simple-tomcat</module>
<module>nutzboot-demo-simple-thymeleaf</module>
<module>nutzboot-demo-simple-sharding-jdbc</module>
<module>nutzboot-demo-simple-uflo</module>
<module>nutzboot-demo-simple-urule</module>
<module>nutzboot-demo-simple-ureport</module>
</modules>
<properties>
</properties>

View File

@ -17,7 +17,6 @@
<dependency>
<groupId>io.zbus</groupId>
<artifactId>zbus</artifactId>
<version>0.11.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -0,0 +1,23 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-parent</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-starter-beetlsql</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetlsql</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,96 @@
package org.nutz.boot.starter.beetlsql;
import javax.sql.DataSource;
import org.beetl.sql.core.ClasspathLoader;
import org.beetl.sql.core.ConnectionSource;
import org.beetl.sql.core.DefaultConnectionSource;
import org.beetl.sql.core.DefaultNameConversion;
import org.beetl.sql.core.Interceptor;
import org.beetl.sql.core.NameConversion;
import org.beetl.sql.core.SQLLoader;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.UnderlinedNameConversion;
import org.beetl.sql.core.db.AbstractDBStyle;
import org.beetl.sql.core.db.DBStyle;
import org.beetl.sql.ext.DebugInterceptor;
import org.nutz.boot.annotation.PropDoc;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.resource.Scans;
/**
* 封装BeetlSql的初始化逻辑
*
* @author wendal(wendal1985@gmail.com)
*
*/
@IocBean
public class BeetlSqlStarter {
protected static final String PRE = "beetlsql.";
@PropDoc(group = "beetlsql", value = "数据库类型", defaultValue = "mysql", possible = { "mysql", "oracle", "h2", "db2",
"postgres", "sqlite", "sqlserver", "sqlserver2012" })
public static final String PROP_DBSTYLE = PRE + "dbStyle";
@PropDoc(group = "beetlsql", value = "SQL目录", defaultValue = "/sqls/")
public static final String PROP_PATH = PRE + "path";
@PropDoc(group = "beetlsql", value = "命名转换方式", defaultValue = "default", possible = { "default", "under_lined" })
public static final String PROP_NAME_CONVERSION = PRE + "nameconv";
@PropDoc(group = "beetlsql", value = "是否使用DebugInterceptor", defaultValue = "true")
public static final String PROP_DEBUG = PRE + "debug";
@PropDoc(group = "beetlsql", value = "是否启用Trans支持", defaultValue = "true")
public static final String PROP_TRANS = PRE + "trans";
@Inject("refer:$ioc")
protected Ioc ioc;
@Inject
protected PropertiesProxy conf;
@IocBean(name = "beetlsqlDBStyle")
public DBStyle createDBStyle() throws Exception {
String type = conf.check(PROP_DBSTYLE);
// DBStyle的实现类总是 XXXStyle风格的命名,但大小写不一,所以需要循环判断一下
for (Class<?> klass : Scans.me().scanPackage(AbstractDBStyle.class.getPackage().getName())) {
if (klass.getName().endsWith("Style")) {
String name = klass.getSimpleName();
name = name.substring(0, name.length() - 5);
if (name.toLowerCase().equals(type))
return (DBStyle) klass.newInstance();
}
}
throw new RuntimeException("unsupport DBStyle=" + type);
}
@IocBean(name = "beetlsqlConnectionSource")
public ConnectionSource createConnectionSource(@Inject DataSource dataSource) {
if (conf.getBoolean(PROP_TRANS, true)) {
// 默认事务管理,就是没有管理
return new DefaultConnectionSource(dataSource, null);
}
// 支持 Trans.exec 或者 @Aop(TransAop.READ_COMMITTED)
return new NutzConnectionSource(dataSource);
}
@IocBean(name = "beetlsqlManager")
public SQLManager creatSQLManager(@Inject("refer:beetlsqlDBStyle") DBStyle dbStyle,
@Inject("beetlsqlConnectionSource") ConnectionSource ds) {
// BeetlSql默认/sql/,但NutzBoot的约定是/sqls/,入乡随俗吧
SQLLoader loader = new ClasspathLoader(conf.get(PROP_PATH, "/sqls/"));
// TODO 支持更多种类的NameConversion
NameConversion nameconv = "default".equals(conf.get(PROP_NAME_CONVERSION, "default"))
? new DefaultNameConversion()
: new UnderlinedNameConversion();
// 是否插入debug拦截器呢? 默认启用好了
if (conf.getBoolean(PROP_DEBUG, true))
return new SQLManager(dbStyle, loader, ds, nameconv, new Interceptor[] { new DebugInterceptor() });
return new SQLManager(dbStyle, loader, ds, nameconv);
}
}

View File

@ -0,0 +1,96 @@
package org.nutz.boot.starter.beetlsql;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Random;
import javax.sql.DataSource;
import org.beetl.sql.core.ConnectionSource;
import org.nutz.trans.Trans;
/**
* 基于Trans的事务实现
*
* @author wendal
*
*/
public class NutzConnectionSource implements ConnectionSource {
protected Random r = new Random();
protected DataSource master;
protected DataSource[] slaves;
protected ThreadLocal<Integer> forceStatus = new ThreadLocal<Integer>() {
protected Integer initialValue() {
return 0;
}
};
public Connection getMaster() {
return getConnectionQuite(master);
}
public Connection getSlave() {
// 如果没有slaves,回落到master
if (slaves == null || slaves.length == 0)
return getMaster();
// TODO 用随机数还是轮询呢? 这是个问题
return getConnectionQuite(slaves[r.nextInt(slaves.length)]);
}
public Connection getConn(String sqlId, boolean isUpdate, String sql, List<?> paras) {
if (isUpdate) // 也就是 非select操作咯
return getMaster();
int status = forceStatus.get();
if (status == 0 || status == 1) {
return getSlave();
} else {
return getMaster();
}
}
public void forceBegin(boolean isMaster) {
// 初始值0, slave=1, master=2
forceStatus.set(isMaster ? 2 : 1);
}
public void forceEnd() {
forceStatus.set(0);
}
public boolean isTransaction() {
return Trans.get() != null || Trans.isTransactionNone();
}
/*
* getMaster和getSlave都不允许抛SQLException,所以封装一下
*/
protected Connection getConnectionQuite(DataSource ds) {
try {
return Trans.getConnectionAuto(ds);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public NutzConnectionSource() {
}
public NutzConnectionSource(DataSource master) {
this.master = master;
}
public NutzConnectionSource(DataSource master, DataSource[] slaves) {
this.master = master;
this.slaves = slaves;
}
public void setMaster(DataSource master) {
this.master = master;
}
public void setSlaves(DataSource[] slaves) {
this.slaves = slaves;
}
}

View File

@ -0,0 +1 @@
org.nutz.boot.starter.beetlsql.BeetlSqlStarter

View File

@ -11,6 +11,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
@ -21,6 +24,7 @@ import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.nutz.boot.AppContext;
import org.nutz.boot.annotation.PropDoc;
import org.nutz.boot.aware.AppContextAware;
@ -37,6 +41,7 @@ import org.nutz.lang.Strings;
import org.nutz.lang.util.LifeCycle;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.resource.Scans;
public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, LifeCycle, AppContextAware {
@ -46,10 +51,13 @@ public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, Lif
@PropDoc(group="jetty", value="监听的ip地址", defaultValue="0.0.0.0")
public static final String PROP_HOST = PRE + "host";
@PropDoc(group="jetty", value="监听的端口", defaultValue="8080", type="int")
public static final String PROP_PORT = PRE + "port";
@PropDoc(group="jetty", value="空闲时间,单位毫秒", defaultValue="300000", type="int")
public static final String PROP_IDLE_TIMEOUT = PRE + "http.idleTimeout";
@PropDoc(group="jetty", value="上下文路径", defaultValue="/")
public static final String PROP_CONTEXT_PATH = PRE + "contextPath";
@ -102,6 +110,7 @@ public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, Lif
PropertiesProxy conf = appContext.getConfigureLoader().get();
connector.setHost(conf.get(PROP_HOST, "0.0.0.0"));
connector.setPort(conf.getInt(PROP_PORT, 8080));
connector.setIdleTimeout(conf.getInt(PROP_IDLE_TIMEOUT, 300*1000));
server.setConnectors(new Connector[]{connector});
@ -152,6 +161,13 @@ public class JettyStarter implements ClassLoaderAware, IocAware, ServerFace, Lif
server.setDumpBeforeStop(false);
server.setStopAtShutdown(true);
ServerContainer sc = WebSocketServerContainerInitializer.configureContext(wac);
for (Class<?> klass : Scans.me().scanPackage(appContext.getPackage())) {
if (klass.getAnnotation(ServerEndpoint.class) != null) {
sc.addEndpoint(klass);
}
}
// 添加其他starter提供的WebXXXX服务
Map<String, WebFilterFace> filters = new HashMap<>();
for (Object object : appContext.getStarters()) {

View File

@ -2,13 +2,20 @@ package org.nutz.boot.starter.nutz.mvc;
import org.nutz.boot.AppContext;
import org.nutz.ioc.Ioc;
import org.nutz.lang.Stopwatch;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.LoadingException;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.NutConfig;
import org.nutz.mvc.Setup;
import org.nutz.mvc.UrlMapping;
import org.nutz.mvc.annotation.Localization;
import org.nutz.mvc.impl.NutLoading;
public class NbMvcLoading extends NutLoading {
private static final Log log = Logs.get();
public UrlMapping load(NutConfig config) {
config.setMainModule(AppContext.getDefault().getMainClass());
@ -27,4 +34,25 @@ public class NbMvcLoading extends NutLoading {
else
super.evalLocalization(config, NbMainModule.class);
}
public void depose(NutConfig config) {
if (log.isInfoEnabled())
log.infof("Nutz.Mvc[%s] is deposing ...", config.getAppName());
Stopwatch sw = Stopwatch.begin();
// Firstly, upload the user customized desctroy
try {
Setup setup = config.getAttributeAs(Setup.class, Setup.class.getName());
if (null != setup)
setup.destroy(config);
}
catch (Exception e) {
throw new LoadingException(e);
}
// Done, print info
sw.stop();
if (log.isInfoEnabled())
log.infof("Nutz.Mvc[%s] is down in %sms", config.getAppName(), sw.getDuration());
}
}

View File

@ -51,7 +51,7 @@ public class NutFilterStarter implements WebFilterFace {
if (conf.has("nutz.mvc.ignore")) {
params.put("ignore", conf.get("nutz.mvc.ignore"));
}
params.put("exclusions", conf.get("nutz.mvc.exclusions", "/druid/*,/uflo/*"));
params.put("exclusions", conf.get("nutz.mvc.exclusions", "/druid/*,/uflo/*,/swagger/*"));
return params;
}

View File

@ -0,0 +1,22 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-parent</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-starter-sharding-jdbc</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.shardingjdbc</groupId>
<artifactId>sharding-jdbc-core</artifactId>
<version>2.0.0</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,45 @@
package org.nutz.boot.starter.shardingjdbc;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.sql.DataSource;
import org.nutz.boot.AppContext;
import org.nutz.boot.annotation.PropDoc;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Streams;
import io.shardingjdbc.core.api.ShardingDataSourceFactory;
@IocBean
public class ShardingJdbcDataSourceStarter {
protected static String PRE = "shardingjdbc.";
@PropDoc(group = "shardingjdbc", value = "配置文件路径", defaultValue = "shardingjdbc.yaml")
public static final String PROP_PATH = PRE + "path";
@Inject
protected PropertiesProxy conf;
@Inject
protected AppContext appContext;
@IocBean
public DataSource getDataSource() throws Exception {
String path = conf.get(PROP_PATH, "shardingjdbc.yaml");
InputStream ins = appContext.getResourceLoader().get(path);
if (ins == null) {
File f = new File(path);
if (f.exists() && f.canRead()) {
ins = new FileInputStream(f);
} else {
throw new RuntimeException("no such shardingjdbc configure file=" + path);
}
}
return ShardingDataSourceFactory.createDataSource(Streams.readBytesAndClose(ins));
}
}

View File

@ -0,0 +1 @@
org.nutz.boot.starter.shardingjdbc.ShardingJdbcDataSourceStarter

View File

@ -1,6 +1,8 @@
package org.nutz.boot.starter.shiro;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.List;
import org.apache.shiro.ShiroException;
import org.apache.shiro.cache.CacheManager;
@ -62,9 +64,12 @@ public class ShiroEnvStarter implements WebEventListenerFace {
if (conf.getBoolean("shiro.session.enable", true)) {
webSecurityManager.setSessionManager(ioc.get(WebSessionManager.class, "shiroWebSessionManager"));
}
if (ioc.has(conf.get("shiro.realm.names", "shiroRealm"))) {
webSecurityManager.setRealm(ioc.get(Realm.class, conf.get("shiro.realm.names", "shiroRealm")));
List<Realm> realms = new ArrayList<>();
for (String realmName : ioc.getNamesByType(Realm.class)) {
realms.add(ioc.get(Realm.class, realmName));
}
if (realms.size() > 0)
webSecurityManager.setRealms(realms);
return webSecurityManager;
}
@ -148,4 +153,5 @@ public class ShiroEnvStarter implements WebEventListenerFace {
public EventListener getEventListener() {
return ioc.get(EnvironmentLoaderListener.class, "shiroEnvironmentLoaderListener");
}
}

View File

@ -0,0 +1,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-parent</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-starter-thymeleaf</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,64 @@
package org.nutz.boot.starter.thymeleaf;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.nutz.lang.util.Context;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.view.AbstractPathView;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
public class ThymeleafView extends AbstractPathView {
private static final Log log = Logs.get();
private NutMap prop;
private TemplateEngine templateEngine = new TemplateEngine();
public ThymeleafView(ClassLoader classLoader, NutMap prop, String path) {
super(path);
this.prop = prop;
templateEngine.setTemplateResolver(initializeTemplateResolver(classLoader, prop));
}
@Override
public void render(HttpServletRequest request, HttpServletResponse response, Object value) throws Exception {
String path = evalPath(request, value);
String encoding = prop.getString("encoding", "UTF-8");
response.setContentType(prop.getString("contentType", "text/html") + "; charset=" + encoding);
response.setCharacterEncoding(encoding);
try {
Context ctx = super.createContext(request, value);
WebContext context = new WebContext(request,
response,
Mvcs.getServletContext(),
Locale.getDefault(),
ctx.getInnerMap());
templateEngine.process(path, context, response.getWriter());
} catch (Exception e) {
log.error("模板引擎错误", e);
throw e;
}
}
private ITemplateResolver initializeTemplateResolver(ClassLoader classLoader, NutMap prop) {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(classLoader);
templateResolver.setTemplateMode(prop.getString("mode", "HTML"));
templateResolver.setPrefix(prop.getString("prefix", "template/"));
templateResolver.setSuffix(prop.getString("suffix", ".html"));
templateResolver.setCharacterEncoding(prop.getString("encoding", "UTF-8"));
templateResolver.setCacheable(prop.getBoolean("cache", true));
templateResolver.setCacheTTLMs(prop.getLong("cacheTTLMs", 3600000L));
return templateResolver;
}
}

View File

@ -0,0 +1,48 @@
package org.nutz.boot.starter.thymeleaf;
import org.nutz.boot.AppContext;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.View;
import org.nutz.mvc.ViewMaker;
@IocBean(name="$views_thymeleaf", create="init")
public class ThymeleafViewMakerStarter implements ViewMaker {
private static final Log log = Logs.get();
@Inject
protected PropertiesProxy conf;
@Inject
protected AppContext appContext;
protected NutMap prop = NutMap.NEW();
public void init() {
if (conf == null) {
return;
}
log.debug("thymeleaf init ....");
for (String key : conf.keySet()) {
if (key.startsWith("thymeleaf.")) {
prop.put(key.substring("thymeleaf.".length()), conf.get(key));
}
}
log.debug("thymeleaf init complete");
}
@Override
public View make(Ioc ioc, String type, String value) {
if ("th".equalsIgnoreCase(type)) {
return new ThymeleafView(appContext.getClassLoader(), prop, value);
} else {
return null;
}
}
}

View File

@ -0,0 +1 @@
org.nutz.boot.starter.thymeleaf.ThymeleafViewMakerStarter

View File

@ -0,0 +1,26 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-parent</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-starter-uflo</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.bstek.uflo</groupId>
<artifactId>uflo-console</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutz</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,56 @@
package org.nutz.boot.starter.uflo;
import org.hibernate.SessionFactory;
import org.nutz.boot.AppContext;
import org.nutz.ioc.Ioc;
import org.springframework.transaction.PlatformTransactionManager;
import com.bstek.uflo.env.EnvironmentProvider;
public class UfloEnvironmentProvider implements EnvironmentProvider {
protected SessionFactory sessionFactory;
protected PlatformTransactionManager platformTransactionManager;
protected Ioc ioc;
protected EnvironmentProvider origin;
public String getCategoryId() {
checkOrigin();
if (origin != null)
return origin.getCategoryId();
return null;
}
public String getLoginUser() {
checkOrigin();
if (origin != null)
return origin.getLoginUser();
return "anonymous";
}
protected void checkOrigin() {
if (ioc == null) {
ioc = AppContext.getDefault().getIoc();
if (ioc.has("uflo.environmentProvider")) {
origin = ioc.get(EnvironmentProvider.class, "uflo.environmentProvider");
}
}
}
public PlatformTransactionManager getPlatformTransactionManager() {
return platformTransactionManager;
}
public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
this.platformTransactionManager = platformTransactionManager;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}

View File

@ -0,0 +1,155 @@
package org.nutz.boot.starter.uflo;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.nutz.boot.AppContext;
import org.nutz.boot.starter.WebServletFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.Ioc2;
import org.nutz.ioc.IocContext;
import org.nutz.ioc.ObjectProxy;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.XmlWebApplicationContext;
import com.bstek.uflo.console.handler.ServletHandler;
@SuppressWarnings("serial")
@IocBean
public class UfloServletStarter extends HttpServlet implements WebServletFace {
public static final String URL="/uflo";
protected Map<String,ServletHandler> handlerMap = new HashMap<String,ServletHandler>();
@Inject
protected PropertiesProxy conf;
@Inject
protected AppContext appContext;
@Inject("refer:$ioc")
protected Ioc ioc;
protected XmlWebApplicationContext applicationContext;
protected ContextLoaderListener ctx;
public String getName() {
return "uflo";
}
public String getPathSpec() {
return "/uflo/*";
}
public Servlet getServlet() {
return this;
}
public Map<String, String> getInitParameters() {
return new HashMap<>();
}
public void init(ServletConfig config) throws ServletException {
applicationContext = new XmlWebApplicationContext();
applicationContext.setServletContext(config.getServletContext());
applicationContext.setConfigLocation("classpath:uflo-spring-context.xml");
applicationContext.refresh();
IocContext ictx = ((Ioc2) ioc).getIocContext();
for (String name : applicationContext.getBeanDefinitionNames()) {
if (name.startsWith("uflo.")) {
switch (name) {
case "uflo.props":
case "uflo.environmentProvider":
break;
default:
Object bean = applicationContext.getBean(name);
ictx.save("app", name, new ObjectProxy(bean));
break;
}
}
}
Collection<ServletHandler> handlers = applicationContext.getBeansOfType(ServletHandler.class).values();
for(ServletHandler handler:handlers){
String url=handler.url();
if(handlerMap.containsKey(url)){
throw new RuntimeException("Handler ["+url+"] already exist.");
}
handlerMap.put(url, handler);
}
}
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try{
String path=req.getContextPath()+URL;
String uri=req.getRequestURI();
String targetUrl=uri.substring(path.length());
if(targetUrl.length()<1){
resp.sendRedirect(req.getContextPath()+"/uflo/todo");
return;
}
int slashPos=targetUrl.indexOf("/",1);
if(slashPos>-1){
targetUrl=targetUrl.substring(0,slashPos);
}
ServletHandler targetHandler=handlerMap.get(targetUrl);
if(targetHandler==null){
outContent(resp,"Handler ["+targetUrl+"] not exist.");
return;
}
targetHandler.execute(req, resp);
}catch(Exception ex){
Throwable e=getCause(ex);
resp.setCharacterEncoding("UTF-8");
PrintWriter pw=resp.getWriter();
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
String errorMsg = e.getMessage();
if(StringUtils.isBlank(errorMsg)){
errorMsg=e.getClass().getName();
}
pw.write(errorMsg);
pw.close();
throw new ServletException(ex);
}
}
protected Throwable getCause(Throwable e){
if(e.getCause()!=null){
return getCause(e.getCause());
}
return e;
}
protected void outContent(HttpServletResponse resp,String msg) throws IOException {
resp.setContentType("text/html");
PrintWriter pw=resp.getWriter();
pw.write("<html>");
pw.write("<header><title>Uflo Console</title></header>");
pw.write("<body>");
pw.write(msg);
pw.write("</body>");
pw.write("</html>");
pw.flush();
pw.close();
}
@Override
public void destroy() {
applicationContext.destroy();
}
}

View File

@ -0,0 +1 @@
org.nutz.boot.starter.uflo.UfloServletStarter

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- 导入nutzboot的spring定义 -->
<import resource="classpath:META-INF/spring/nutzboot-spring-context.xml" />
<!-- 导入uflo的spring定义 -->
<import resource="classpath:uflo-console-context.xml" />
<!-- uflo需要一个EnvironmentProvider -->
<bean id="uflo.environmentProvider" class="org.nutz.boot.starter.uflo.UfloEnvironmentProvider">
<property name="platformTransactionManager" ref="uflo.transactionManager" />
<property name="sessionFactory" ref="uflo.sessionFactory" />
</bean>
<!-- uflo总是依赖hibernate,那就给它咯 -->
<bean id="uflo.sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="nutz.dataSource" />
<property name="packagesToScan">
<list>
<value>com.bstek.uflo.model*</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- 还需要事务管理器 -->
<bean id="uflo.transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="uflo.sessionFactory"/>
</bean>
</beans>

View File

@ -7,6 +7,8 @@ import java.util.Iterator;
import java.util.Map;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import org.nutz.boot.AppContext;
import org.nutz.boot.annotation.PropDoc;
@ -36,10 +38,9 @@ import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.api.InstanceFactory;
import io.undertow.servlet.api.InstanceHandle;
import io.undertow.servlet.api.ListenerInfo;
import io.undertow.servlet.api.ServletInfo;
import io.undertow.servlet.util.ImmediateInstanceFactory;
/**
* Undertow 启动器
@ -173,14 +174,15 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
if (webServlet == null || webServlet.getServlet() == null)
return;
ServletInfo servlet = new ServletInfo(webServlet.getName(), webServlet.getServlet().getClass());
log.debugf("add servlet name=%s pathSpec=%s", webServlet.getName(), webServlet.getPathSpec());
ImmediateInstanceFactory<Servlet> factory = new ImmediateInstanceFactory<Servlet>(webServlet.getServlet());
ServletInfo servlet = new ServletInfo(webServlet.getName(), webServlet.getServlet().getClass(), factory);
Iterator<Map.Entry<String, String>> entries = webServlet.getInitParameters().entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
servlet.addInitParam(entry.getKey(), entry.getValue());
}
servlet.addMapping(webServlet.getPathSpec());
log.debugf("add servlet name=%s pathSpec=%s", webServlet.getName(), webServlet.getPathSpec());
deployment.addServlet(servlet);
}
@ -189,7 +191,8 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
return;
log.debugf("add filter name=%s pathSpec=%s", webFilter.getName(), webFilter.getPathSpec());
FilterInfo filter = new FilterInfo(webFilter.getName(), webFilter.getFilter().getClass());
ImmediateInstanceFactory<Filter> factory = new ImmediateInstanceFactory<Filter>(webFilter.getFilter());
FilterInfo filter = new FilterInfo(webFilter.getName(), webFilter.getFilter().getClass(), factory);
Iterator<Map.Entry<String, String>> entries = webFilter.getInitParameters().entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, String> entry = entries.next();
@ -205,18 +208,9 @@ public class UndertowStarter implements ClassLoaderAware, IocAware, ServerFace,
return;
EventListener et = webEventListener.getEventListener();
ListenerInfo listener = new ListenerInfo(et.getClass());
listener.setInstanceFactory(new InstanceFactory<EventListener>() {
public InstanceHandle<EventListener> createInstance() throws InstantiationException {
return new InstanceHandle<EventListener>() {
public EventListener getInstance() {
return et;
}
public void release() {
}
};
}
});
log.debugf("add listener %s", et.getClass());
ImmediateInstanceFactory<EventListener> factory = new ImmediateInstanceFactory<EventListener>(et);
ListenerInfo listener = new ListenerInfo(et.getClass(), factory);
deployment.addListener(listener);
}

View File

@ -0,0 +1,27 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-parent</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-starter-ureport</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.bstek.ureport</groupId>
<artifactId>ureport2-console</artifactId>
<version>2.2.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,159 @@
package org.nutz.boot.starter.ureport;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.nutz.boot.AppContext;
import org.nutz.boot.starter.WebServletFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.Ioc2;
import org.nutz.ioc.IocContext;
import org.nutz.ioc.ObjectProxy;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Files;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.XmlWebApplicationContext;
import com.bstek.ureport.console.RequestHolder;
import com.bstek.ureport.console.ServletAction;
@SuppressWarnings("serial")
@IocBean
public class UreportServletStarter extends HttpServlet implements WebServletFace {
protected Map<String, ServletAction> handlerMap = new HashMap<String,ServletAction>();
@Inject
protected PropertiesProxy conf;
@Inject
protected AppContext appContext;
@Inject("refer:$ioc")
protected Ioc ioc;
protected XmlWebApplicationContext applicationContext;
protected ContextLoaderListener ctx;
public String getName() {
return "ureport";
}
public String getPathSpec() {
return "/ureport/*";
}
public Servlet getServlet() {
return this;
}
public Map<String, String> getInitParameters() {
return new HashMap<>();
}
public void init(ServletConfig config) throws ServletException {
Files.createDirIfNoExists(conf.check("ureport.repository.dir"));
applicationContext = new XmlWebApplicationContext();
applicationContext.setServletContext(config.getServletContext());
applicationContext.setConfigLocation("classpath:ureport-spring-context.xml");
applicationContext.refresh();
IocContext ictx = ((Ioc2) ioc).getIocContext();
for (String name : applicationContext.getBeanDefinitionNames()) {
if (name.startsWith("ureport.")) {
switch (name) {
case "ureport.props":
break;
default:
Object bean = applicationContext.getBean(name);
ictx.save("app", name, new ObjectProxy(bean));
break;
}
}
}
Collection<ServletAction> handlers = applicationContext.getBeansOfType(ServletAction.class).values();
for(ServletAction handler:handlers){
String url=handler.url();
if(handlerMap.containsKey(url)){
throw new RuntimeException("Handler ["+url+"] already exist.");
}
handlerMap.put(url, handler);
}
}
public static final String URL="/ureport";
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String path = req.getContextPath() + URL;
String uri = req.getRequestURI();
String targetUrl = uri.substring(path.length());
if (targetUrl.length() < 1) {
outContent(resp, "Welcome to use ureport,please specify target url.");
return;
}
int slashPos = targetUrl.indexOf("/", 1);
if (slashPos > -1) {
targetUrl = targetUrl.substring(0, slashPos);
}
ServletAction targetHandler = handlerMap.get(targetUrl);
if (targetHandler == null) {
outContent(resp, "Handler [" + targetUrl + "] not exist.");
return;
}
RequestHolder.setRequest(req);
try{
targetHandler.execute(req, resp);
}catch(Exception ex){
resp.setCharacterEncoding("UTF-8");
PrintWriter pw=resp.getWriter();
Throwable e=buildRootException(ex);
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
String errorMsg = e.getMessage();
if(StringUtils.isBlank(errorMsg)){
errorMsg=e.getClass().getName();
}
pw.write(errorMsg);
pw.close();
throw new ServletException(ex);
}finally{
RequestHolder.clean();
}
}
private Throwable buildRootException(Throwable throwable){
if(throwable.getCause()==null){
return throwable;
}
return buildRootException(throwable.getCause());
}
private void outContent(HttpServletResponse resp, String msg) throws IOException {
resp.setContentType("text/html");
PrintWriter pw = resp.getWriter();
pw.write("<html>");
pw.write("<header><title>UReport Console</title></header>");
pw.write("<body>");
pw.write(msg);
pw.write("</body>");
pw.write("</html>");
pw.flush();
pw.close();
}
@Override
public void destroy() {
applicationContext.destroy();
}
}

View File

@ -0,0 +1 @@
org.nutz.boot.starter.ureport.UreportServletStarter

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- 导入nutzboot的spring定义 -->
<import resource="classpath:META-INF/spring/nutzboot-spring-context.xml" />
<!-- 导入urule的spring定义 -->
<import resource="classpath:ureport-console-context.xml" />
</beans>

View File

@ -0,0 +1,27 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-parent</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>nutzboot-starter-urule</artifactId>
<dependencies>
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzboot-starter</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.bstek.urule</groupId>
<artifactId>urule-console</artifactId>
<version>2.1.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,170 @@
package org.nutz.boot.starter.urule;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.nutz.boot.AppContext;
import org.nutz.boot.starter.WebServletFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.Ioc2;
import org.nutz.ioc.IocContext;
import org.nutz.ioc.ObjectProxy;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Files;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.XmlWebApplicationContext;
import com.bstek.urule.console.exception.NoPermissionException;
import com.bstek.urule.console.repository.NodeLockException;
import com.bstek.urule.console.servlet.RequestHolder;
import com.bstek.urule.console.servlet.ServletHandler;
@SuppressWarnings("serial")
@IocBean
public class UruleServletStarter extends HttpServlet implements WebServletFace {
protected Map<String,ServletHandler> handlerMap = new HashMap<String,ServletHandler>();
@Inject
protected PropertiesProxy conf;
@Inject
protected AppContext appContext;
@Inject("refer:$ioc")
protected Ioc ioc;
protected XmlWebApplicationContext applicationContext;
protected ContextLoaderListener ctx;
public String getName() {
return "urule";
}
public String getPathSpec() {
return "/urule/*";
}
public Servlet getServlet() {
return this;
}
public Map<String, String> getInitParameters() {
return new HashMap<>();
}
public void init(ServletConfig config) throws ServletException {
Files.createDirIfNoExists(conf.check("urule.repository.dir"));
applicationContext = new XmlWebApplicationContext();
applicationContext.setServletContext(config.getServletContext());
applicationContext.setConfigLocation("classpath:urule-spring-context.xml");
applicationContext.refresh();
IocContext ictx = ((Ioc2) ioc).getIocContext();
for (String name : applicationContext.getBeanDefinitionNames()) {
if (name.startsWith("urule.")) {
switch (name) {
case "urule.props":
break;
default:
Object bean = applicationContext.getBean(name);
ictx.save("app", name, new ObjectProxy(bean));
break;
}
}
}
Collection<ServletHandler> handlers = applicationContext.getBeansOfType(ServletHandler.class).values();
for(ServletHandler handler:handlers){
String url=handler.url();
if(handlerMap.containsKey(url)){
throw new RuntimeException("Handler ["+url+"] already exist.");
}
handlerMap.put(url, handler);
}
}
public static final String URL="/urule";
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
RequestHolder.set(req, resp);
try{
String path=req.getContextPath()+URL;
String uri=req.getRequestURI();
String targetUrl=uri.substring(path.length());
if(targetUrl.length()<1){
resp.sendRedirect(req.getContextPath()+"/urule/frame");
return;
}
int slashPos=targetUrl.indexOf("/",1);
if(slashPos>-1){
targetUrl=targetUrl.substring(0,slashPos);
}
ServletHandler targetHandler=handlerMap.get(targetUrl);
if(targetHandler==null){
outContent(resp,"Handler ["+targetUrl+"] not exist.");
return;
}
targetHandler.execute(req, resp);
}catch(Exception ex){
Throwable e=getCause(ex);
resp.setCharacterEncoding("UTF-8");
PrintWriter pw=resp.getWriter();
if(e instanceof NoPermissionException){
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
pw.write("<h1>Permission denied!</h1>");
pw.close();
}else{
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
String errorMsg = e.getMessage();
if(StringUtils.isBlank(errorMsg)){
errorMsg=e.getClass().getName();
}
pw.write(errorMsg);
pw.close();
if(!(e instanceof NodeLockException)){
throw new ServletException(ex);
}
}
}finally{
RequestHolder.reset();
}
}
private void outContent(HttpServletResponse resp,String msg) throws IOException {
resp.setContentType("text/html");
PrintWriter pw=resp.getWriter();
pw.write("<html>");
pw.write("<header><title>URule Console</title></header>");
pw.write("<body>");
pw.write(msg);
pw.write("</body>");
pw.write("</html>");
pw.flush();
pw.close();
}
private Throwable getCause(Throwable e){
if(e.getCause()!=null){
return getCause(e.getCause());
}
return e;
}
@Override
public void destroy() {
applicationContext.destroy();
}
}

View File

@ -0,0 +1 @@
org.nutz.boot.starter.urule.UruleServletStarter

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- 导入nutzboot的spring定义 -->
<import resource="classpath:META-INF/spring/nutzboot-spring-context.xml" />
<!-- 导入urule的spring定义 -->
<import resource="classpath:urule-console-context.xml" />
</beans>

View File

@ -61,6 +61,12 @@
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.11.RELEASE</version>
<scope>provided</scope>
</dependency>
</dependencies>
<distributionManagement>
<snapshotRepository>

View File

@ -8,6 +8,7 @@ import org.nutz.boot.env.EnvHolder;
import org.nutz.boot.resource.ResourceLoader;
import org.nutz.boot.starter.ServerFace;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.combo.ComboIocLoader;
import org.nutz.lang.util.LifeCycle;
@ -49,6 +50,10 @@ public class AppContext implements LifeCycle {
return configureLoader;
}
public PropertiesProxy getConf() {
return configureLoader.get();
}
public ResourceLoader getResourceLoader() {
return resourceLoader;
}
@ -120,6 +125,8 @@ public class AppContext implements LifeCycle {
if (object instanceof LifeCycle)
((LifeCycle) object).depose();
}
if (ioc != null)
ioc.depose();
}
public void startServers() throws Exception {

View File

@ -44,7 +44,7 @@ import org.nutz.mvc.annotation.IocBy;
* @author wendal
*
*/
public class NbApp {
public class NbApp extends Thread {
/**
* 日志属性要等日志适配器准备好了才能加载,这里不可以使用Logs.get();
@ -88,6 +88,8 @@ public class NbApp {
protected boolean prepared;
protected Object lock = new Object();
/**
* 创建一个NbApp,把调用本构造方法的类作为mainClass
*/
@ -147,10 +149,18 @@ public class NbApp {
return ctx;
}
public void run() {
try {
_run();
} catch (Throwable e) {
Logs.get().error("something happen", e);
}
}
/**
* 启动整个NbApp
*/
public void run() throws Exception {
public void _run() throws Exception {
Stopwatch sw = Stopwatch.begin();
// 各种预备操作
@ -163,24 +173,35 @@ public class NbApp {
}
// 依次启动
ctx.init();
ctx.startServers();
if (mainClass.getAnnotation(IocBean.class) != null)
ctx.getIoc().get(mainClass);
sw.stop();
log.infof("NB started : %sms", sw.du());
// 等待关闭
Lang.quiteSleep(Integer.MAX_VALUE);
try {
ctx.init();
ctx.startServers();
if (mainClass.getAnnotation(IocBean.class) != null)
ctx.getIoc().get(mainClass);
sw.stop();
log.infof("NB started : %sms", sw.du());
synchronized (lock) {
lock.wait();
}
}
catch (Throwable e) {
log.error("something happen!!", e);
}
// 收尾
ctx.stopServers();
ctx.depose();
}
public void shutdown() {
log.info("ok, shutting down ...");
synchronized (lock) {
lock.notify();
}
}
/**
* 执行预备操作
*/

View File

@ -0,0 +1,26 @@
package org.nutz.boot.tools;
import java.util.Properties;
import org.nutz.ioc.impl.PropertiesProxy;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
public class Nb2SpringPropertyPlaceholder extends PropertyPlaceholderConfigurer {
protected PropertiesProxy conf;
public Nb2SpringPropertyPlaceholder() {
setIgnoreUnresolvablePlaceholders(true);
setOrder(100);
}
protected String resolvePlaceholder(String placeholder, Properties props) {
if (conf.has(placeholder))
return conf.get(placeholder);
return super.resolvePlaceholder(placeholder, props);
}
public void setConf(PropertiesProxy conf) {
this.conf = conf;
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- 定义各种nutz提供的bean -->
<bean id="nutz.appContext" class="org.nutz.boot.AppContext" factory-method="getDefault" lazy-init="true"/>
<bean id="nutz.ioc" class="org.nutz.ioc.impl.NutIoc" factory-bean="nutz.appContext" factory-method="getIoc" lazy-init="true"/>
<bean id="nutz.dataSource" class="javax.sql.DataSource" factory-bean="nutz.ioc" factory-method="get" lazy-init="true">
<constructor-arg type="java.lang.Class" value="javax.sql.DataSource"></constructor-arg>
<constructor-arg value="dataSource"></constructor-arg>
</bean>
<bean id="nutz.conf" class="org.nutz.ioc.impl.PropertiesProxy" factory-bean="nutz.appContext" factory-method="getConf" lazy-init="true"/>
<bean id="nutz.spring.propertyPlaceHolder" class="org.nutz.boot.tools.Nb2SpringPropertyPlaceholder" lazy-init="true">
<property name="conf" ref="nutz.conf"></property>
</bean>
</beans>

10
pom.xml
View File

@ -44,6 +44,7 @@
</scm>
<modules>
<module>nutzboot-starter</module>
<module>nutzboot-starter-beetlsql</module>
<module>nutzboot-starter-jetty</module>
<module>nutzboot-starter-undertow</module>
<module>nutzboot-starter-tomcat</module>
@ -69,6 +70,11 @@
<module>nutzboot-starter-disque</module>
<module>nutzboot-starter-beetl</module>
<module>nutzboot-starter-jetx</module>
<module>nutzboot-starter-sharding-jdbc</module>
<module>nutzboot-starter-thymeleaf</module>
<module>nutzboot-starter-uflo</module>
<module>nutzboot-starter-urule</module>
<module>nutzboot-starter-ureport</module>
</modules>
<profiles>
<profile>
@ -220,7 +226,7 @@
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.8.RELEASE</version>
<version>3.0.9.RELEASE</version>
</dependency>
<dependency>
@ -416,4 +422,4 @@
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
</repository>
</distributionManagement>
</project>
</project>