Commit 6ef938ca authored by yang's avatar yang
parents 9a48d073 486f2c1d
# hlsCombobox标签
ComboBox下拉列表组件,通常数据源以code - meaning形式出现,用户操作的是meaning,实际保存的是code。
```xml
<h:hlsCombobox name="hlsCombobox" id="hlsCombobox"
bind="enabled: isEnabled,source: sdDataSource, value:data.code"
colspan="3"
dataTextField="meaning"
dataValueField="code"
placeholder="hlsCombobox"
prompt="hlsCombobox"
promptColspan="1"
valuePrimitive="true"
style="width:100%"
/>
```
### **主要属性**
属性名 | 类型
-------- | ---
id | String
promptColspan | String
promptClassName | String
promptImage | String
prompt | String
colspan | String
hlsClassName | String
animation | Boolean
autoBind | Boolean
autoWidth | Boolean
cascadeFrom| String
cascadeFromField | String
clearButton| Boolean
dataSource | DataSource
dataTextField | String
dataValueField| String
delay | Number
enable | Boolean
enforceMinLength| Boolean
filter | String
fixedGroupTemplate| String \| Function
footerTemplate| String \| Function
groupTemplate| String \| Function
height| Number
highlightFirst| Boolean
ignoreCase| Boolean
index| Number
minLength| Number
noDataTemplate| String \| Function
placeholder | String
suggest| Boolean
headerTemplate| String \| Function
template| String \| Function
text| String
value| String
valuePrimitive| Boolean
virtual| Boolean
change| Function
close| Function
dataBound | Function
filtering| Function
open| Function
select| Function
cascade| Function
> 属性用法请参考KendoUI文档 [http://docs.telerik.com/kendo-ui/api/javascript/ui/combobox](http://docs.telerik.com/kendo-ui/api/javascript/ui/combobox)
### **用法示例*
```javascript
//对于系统定义好的数据源
<script src="${base.contextPath}/common/code?sdDataSource=FND.CODING_RULE_TYPE" type="text/javascript"></script>
//自定义静态数据源sdDataSource
var sdDataSource= new kendo.data.DataSource({
data:["one","two"]
});
//自定义动态查询到的数据源sdDataSource
$.ajax({
type : 'GET',
url : url,
async: false,
contentType : "application/json; charset=utf-8",
success : function(datas) {
viewModel.set("sdDataSource,",datas.rows);
}
});
//需要注意,bind中写dataSource,需要在viewModel中定义
var viewModel = kendo.observable({
enabled: true,
isEnabled: false,
data: {},
sdDataSource:sdDataSource,
});
//下拉列表渲染函数
var itemTemplate = function (){
//...
}
//选中某一个列表选项后触发
function onComboboxChange(e){
var value = this.value();
// Use the value of the widget.
}
//以上两种函数定义方法皆可
```
```xml
<h:hlsCombobox name="hlsCombobox" id="hlsCombobox"
bind="enabled: isEnabled,source: sdDataSource, value:data.code"
colspan="3"
dataTextField="meaning"
dataValueField="code"
placeholder="hlsCombobox"
prompt="hlsCombobox"
promptColspan="1"
valuePrimitive="true"
style="width:100
change="onComboboxChange"
template="fn:itemTemplate"
/>
```
#### 特别注意 valuePrimitive="true" 如果该值为false,选中的值将不会匹配给dataTextField和dataValueField
dataValueField
> **提示:** 某些属性类型为**String \| Function** 时,表明它可以定义为字符串或者函数。因此当需要定义为Function时需要增加前缀**fn:**来区分(例如函数template="fn:itemTemplate" )
# hlsDatePicker标签
日期选择器(不包含时分秒)
xml配置
```
<!--基本用法-->
<h:hlsDatePicker id="hlsDatePickerId" bind="enabled:isEnabled,value:data.value" placeholder="hlsDatePicker"/>
```
### **主要属性**
属性名 | 类型
-------- | -----
promptColspan | Integer
promptClassName | String
promptImage | String
prompt | String
colspan | Integer
hlsClassName | String
animation | Boolean
ARIATemplate| String
culture | String
depth| String
footer| String & Function
format| String
max| String
min| String
start| String
value | String
name | String
bind | Function
required | Boolean
change | Function
close| Function
open | Function
placeholder | String
interval |Integer
timeFormat |String
> **提示:** 属性用法请参考kendoui API文档 http://docs.telerik.com/kendo-ui/api/javascript/ui/datetimepicker
### **用法示例**
```javascript
//注意是写在script标签内的
var viewModel = kendo.observable({
data:{},
isEnabled:true
});
function open(){
//...
}
function change(e){
//...
}
```
```xml
<h:hlsDatePicker id="hlsDatePickerId"bind="enabled: isEnabled,value:data.value"
style="width:200px;"
max="2016-6-6"
placeholder="hlsDatePicker"
open="open"
required="true"
change="change"
prompt="日期选择器:"
/>
id:可写可不写;
bind:属性里面包含配置两个选项:
(1)enabled配置日期选择器是否可以编辑,值为Boolean类型的变量,在viewModel里面配置。
(2)value配置日期选择器与变量关联,默认是在ViewModel下面的变量;
max:可选择日期的上限值;
style可改变该控件的样式;
open:点击控件调用的方法;
change:选择日期之后的事件;
prompt:为控件添加一个label,该属性一般和<h:hlsForm><h:hlsHBox>一起使用;
```
> **提示:**
> - 上述所有属性直接添加在标签内即可,(**[属性名] = "..."**),对于既是**String**类型又是**Function**类型的属性,只需要加**fn:**前缀区分即可,(**fn:函数名**)
> - 对于**max min**等本该是**时间类型**的属性,改为日期字符串,且连接符号为"**-**"
# hlsCombobox标签
# hlsCombobox标签(下拉框)
ComboBox下拉列表组件,通常数据源以code - meaning形式出现,用户操作的是meaning,实际保存的是code。
......@@ -20,52 +20,24 @@ ComboBox下拉列表组件,通常数据源以code - meaning形式出现,用
```
### **主要属性**
属性名 | 类型
-------- | ---
id | String
promptColspan | String
promptClassName | String
promptImage | String
prompt | String
colspan | String
hlsClassName | String
animation | Boolean
autoBind | Boolean
autoWidth | Boolean
cascadeFrom| String
cascadeFromField | String
clearButton| Boolean
dataSource | DataSource
dataTextField | String
dataValueField| String
delay | Number
enable | Boolean
enforceMinLength| Boolean
filter | String
fixedGroupTemplate| String \| Function
footerTemplate| String \| Function
groupTemplate| String \| Function
height| Number
highlightFirst| Boolean
ignoreCase| Boolean
index| Number
minLength| Number
noDataTemplate| String \| Function
placeholder | String
suggest| Boolean
headerTemplate| String \| Function
template| String \| Function
text| String
value| String
valuePrimitive| Boolean
virtual| Boolean
change| Function
close| Function
dataBound | Function
filtering| Function
open| Function
select| Function
cascade| Function
属性名 | 类型 | 说明 |
--- | --- | --- |
id | String | id |
promptColspan | String | 提示语句需要占几列 |
promptClassName | String | 提示语句类名,默认不填 |
promptImage | String | 提示前面的文字图形,默认不填 |
prompt | String | 提示信息 |
colspan | String | 所占列数 |
hlsClassName | String | 类名,默认不填 |
dataSource | DataSource | 数据源 |
dataTextField | String | 返回的显示描述字段 |
dataValueField| String | 绑定的英文字段 |
enable | Boolean | 是否可编辑,true为可编辑,false不可编辑 |
placeholder | String | 占位符 |
template| Function| 渲染函数 |
change| Function | 数据变化时触发的函数 |
> 属性用法请参考KendoUI文档 [http://docs.telerik.com/kendo-ui/api/javascript/ui/combobox](http://docs.telerik.com/kendo-ui/api/javascript/ui/combobox)
......
......@@ -9,33 +9,24 @@ xml配置
```
### **主要属性**
属性名 | 类型
-------- | -----
promptColspan | Integer
promptClassName | String
promptImage | String
prompt | String
colspan | Integer
hlsClassName | String
animation | Boolean
ARIATemplate| String
culture | String
depth| String
footer| String & Function
format| String
max| String
min| String
start| String
value | String
name | String
bind | Function
required | Boolean
change | Function
close| Function
open | Function
placeholder | String
interval |Integer
timeFormat |String
属性名 | 类型 | 说明 |
-------- | -----| --- |
promptColspan | Integer | 描述字段所占列数 |
promptClassName | String| 描述的样式名称 |
prompt | String| 描述 |
colspan | Integer | datePicker所占列数 |
hlsClassName | String | 样式名称 |
animation | Boolean | 动画 |
format| String | 格式化 |
max| String | 最大时间 |
min| String | 最小时间 |
value | String | 值 |
name | String | name属性 |
bind | Function | 绑定数据 |
required | Boolean | 必输 |
change | Function | chang事件 |
placeholder | String | 占位符 |
timeFormat |String| 时间格式化 |
> **提示:** 属性用法请参考kendoui API文档 http://docs.telerik.com/kendo-ui/api/javascript/ui/datetimepicker
......
## TlEdit
## hlsTlEdit
多语言编辑
......@@ -11,20 +11,23 @@
#### **一般属性**
| 属性名 | 类型 |
| --- | --- |
| idField | String |
| field | String |
| dto | String |
| model | Function |
| open | Function |
| close | Function |
| placeholder | String |
| bind | Function |
| 属性名 | 类型 | 说明 |
| --- | --- | --- |
| id | String | 唯一英文标识 |
| promptColspan | number | 该数字将会与col-sm-?进行拼接,替代问号,生成对应bootstrap的css样式,渲染描述的样式 |
| promptClassName | String | 描述的样式名称,会将对应的样式添加到描述中 |
| promptImage | String | 描述前面的一个文本图像,在设置为必填的时候会出现一个红色的* |
| prompt | String | 中文描述 |
| colspan| number | 该数字会与col-sm-?进行拼接,替代问号,生成对应bootStrap的css样式,渲染文本框的样式 |
| hlsClassName | String | 标签的样式名称 |
| placeholder | String | 占位符 |
| bind | expressions | 绑定数据 |
用法示例:
```javascript
```xml
<h:hlsTlEdit id="tl" placeholder="多语言" bind="value:data.name" idField="id" field="name" dto="com.hand.hap.function.dto.Resource" model="viewModel.data">
</h:hlsTlEdit>
```
......
# 跨域访问(CORS)
## 简介:
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
## 使用说明:
#### 1.修改web.xml文件:
添加Filter:
![](/assets/cors-web.png)
各参数含义:
allowedMappings: 允许跨域资源(必填)
allowedHeader:\(允许的头部参数)
allowedOrigin\(允许的请求源)
allowedMethod\(允许的请求方法\)
allowedCredentials\(是否允许携带证书)
MaxAge\(最大时长)
#### 2.发送跨域请求:
2.1 跨域登录,观察http请求response
![](/assets/cors-login.png)
2.2 登录成功所返回的信息:sessionId\(用于用户登录验证) csrf\_token(用于csrf验证)
![](/assets/cors-login1.png)
2.3 将sessionId\(Authorization\) csrf\_\_token\(X-CSRF-\_TOKEN\)添加进requestHeader中进行后续访问
![](/assets/cors-query.png)
2.4 得到返回信息
![](/assets/cors-quer1.png)
审计
---
融租易支持在代码级别记录用户对指定表的操作记录.
操作包括 : 插入, 更新, 删除.
## 1. 代码准备
再代码层面, 有两个注解 `AuditEnabled`,`AuditEntry`
#### 1.1 AuditEnabled
这个注解加在 DTO 类上, 表示这个 DTO 代表的 表需要开启审计功能.
```java
@Table("SYS_USER")
@AuditEnabled
public class User {
}
```
#### 1.2 AuditEntry
这个注解加在 `Service 接口的方法`上, 表示, 再这个方法的执行周期内开启审计功能.
> 这个方法内部可能会对多个表进行操作, 也可能调用其他的方法 f1, f1 在去操作其他的某个表.
这些调用涉及到的审计操作, 全部共享一个审计的 session (auditSessionId相同).
```java
public interface UserService {
@AuditEntry
User updateUser(User user);
}
```
## 2. 表结构
所有需要开启审计功能的表, 需要有一个与之相对应的 `审计表`.
命名规则 : `基表名`_a
可以在 `AuditEnabled` 注解中通过参数 `auditTable` 来指定.
>这个规则可以 实现接口 `IAuditTableNameProvider` 来自定义.
实现类需要定义为 spring bean
审计表字段`包含所有字段`, 但不包含`基表的唯一索引, 主键约束`
另外必须包括审计专用字段:
* `audit_id` (bigint) 自增长主键
* `audit_transaction_type` (varchar (10)) 审计操作(insert,update,delete)
* `audit_timestamp` (datetime) 审计时间
* `audit_session_id` (varchar(64)) 审计 session id
## 3 基本原理
`AuditInterceptor` 会拦截所有的 Mybatis 通过 dto 执行的操作,
根据当前有没有 `audit session` , 以及 dto 上的 AuditEnabled 注解 来决定是不是要执行 审计操作.
如果需要执行, 则动态生成 SQL 语句, 完成对新记录的`备份` 操作.
`插入`,`更新` 执行的操作是 先操作, 后记录.
`删除` 执行的操作是 先记录, 后操作.
也就是说, 审计表中插入的都是`最新的快照`.
> 基于这个原理的审计, 只能做到行级的记录, 无法具体到字段级.
但是结合一定的比较手段, 可以知道, 某次修改, 到底修改了哪些字段.
另外, 由于 audit session 的存在, 我们大概也可以知道,某次提交,同时修改了哪些数据.
当然操作的记录如何展示出来, 是需要另外开发页面的.
\ No newline at end of file
# 代码生成器
# 简介:
本功能可根据数据表生成相关的dto,mapper impl,service,controller与html,包含相关的增删改查功能。
**网页入口**:http:\/\/localhost:8080\/hel\/generator\/generator.html
## 使用说明:
**主页面:**
![](/assets/gnerator1.png)
**项目路径**:指向本机hap。
**包父路径:**指向hap的包路径。
**包路径:**为所要生成的包名。
**选择表:**选中所要维护的表。
**文件名:** 将自动根据表名生成对应名称(修改dto可选择是否根据dto修改其余文件,也可单独修改其余文件)( 文件创建之前会判断项目中是否有同名文件 ) 。
**是否创建:**勾选创建文件。
**是否覆盖:**勾选则可以覆盖同路径下同名文件。
**选择ftl模板:**可根据选择的ftl模板生成对应的html页面。
## 生成示例:
**1:相关文件**
![](/assets/generator2.png)
2:相关的dto
![](/assets/generator4.png)
**3:相关controller**(包含增删改查)
![](/assets/generator5.png)
**4:相关mapper**(包含基础resultMap)
![](/assets/generator6.png)
**5:生成基础的增删改查功能的html页面**
![](/assets/generator3.png)
**6:service文件** (mapper类似)
![](/assets/gernerator7.png)
# 日志管理 ELK(ElasticSearch+Logstash+Kibana)
## 简介:
**ElasticSearch:**一个开源分布式搜索引擎,具有分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等特点。<p>**Logstash:**一个完全开源的工具,可以对你的日志进行搜集,过滤,并将其储存供以后使用。<p>**Kibana:**为Logstash和ElasticSearch提供日志分析的友好Web界面,可以汇总,分析和搜索重要的数据日志。
##下载说明:
由于Logstash的运行依赖于Java环境, 而Logstash 1.5以上版本不低于java 1.7,因此推荐使用最新版本的Java。因为我们只需要Java的运行环境,所以可以只安装JRE,不过这里我依然使用JDK,请自行搜索安装<p>
ELK下载https://www.elastic.co/downloads/
## 使用说明:
### ElasticSearch:
#### 启动服务:
运行bin/elasticsearch.bat文件开启服务。查看127.0.0.1:9200出现如下页面运行成功<p>
#![](/assets/elasticsearch.png) <p>
#### 基础操作:es支持restful操作。<p>
获取对应文档:<p>
GET /[_index]/[_type]/_search <p>
上传文档: <p>
```javascript
PUT /[_index]/[_type]/[_id}
{ "first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ] }
```
<p>
操作文档:http://es.xiaoleilu.com/030_Data/15_Get.html
#### 面向文档:
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。<p>
ELasticsearch使用JSON,作为文档序列化格式。
以下使用JSON文档来表示一个用户对象:<p>
```javascript
{
"email": "john@smith.com",
"first_name": "John",
"last_name": "Smith",
"info": {
"bio": "Eco-warrior and defender of the weak",
"age": 25,
"interests": [ "dolphins", "whales" ]
},
"join_date": "2014/05/01"
}
```
在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中,我们可以画一些简单的对比图来类比传统关系型数据库:<p>
Relational DB -> Databases -> Tables -> Rows -> Columns<p>
Elasticsearch -> Indices -> Types -> Documents -> Fields<p>
Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。
#### elasticsearch 分布式:
Elasticsearch为分布式而生
Elasticsearch致力于隐藏分布式系统的复杂性。以下这些操作都是在底层自动完成的:<p>
*将你的文档分区到不同的容器或者分片(shards)中,它们可以存在于一个或多个节点中。<p>
*将分片均匀的分配到各个节点,对索引和搜索做负载均衡。<p>
*冗余每一个分片,防止硬件故障造成的数据丢失。<p>
*将集群中任意一个节点上的请求路由到相应数据所在的节点。<p>
*无论是增加节点,还是移除节点,分片都可以做到无缝的扩展和迁移<p>
#### 集群部署:
伪分布式环境搭建:创建3个es环境,修改其config/elasticsearch.yml配置文件<p>
1:<p>
cluster.name: elasticsearch<p>
node.name: node1<p>
2:<p>
cluster.name: elasticsearch<p>
node.name: node2<p>
http.port: 9202<p>
3:<p>
cluster.name: elasticsearch<p>
node.name: node3<p>
http.port: 9203<p>
es会自动搜索同一网段下的cluster.name(集群名)相同的es做成集群
将indeces(索引)下的分片(默认一个索引5个主分片每个分片一个复制分片)平分到不同es节点(node)下。
#### elasticsearch-head插件安装:
是es集群管理插件。执行如下命令安装插件:<p>
elasticsearch/bin/plugin install mobz/elasticsearch-head<p>
打开:http://localhost:9200/_plugin/head/ <p>
下图为以上操作建立的集群。
![](/assets/es.png) <p>
相关文档:http://es.xiaoleilu.com/020_Distributed_Cluster/05_Empty_cluster.html <p>
### Logstash:
#### 运行:
logstash -e input { stdin { } } output { stdout { codec => rubydebug } } <p>
输入报文 helloworld 可以在控制台看到对应报文。<p>
2016-10-20T09:05:53.446Z LAPTOP-RKIO0CO4 hellowrold <p>
#### 通过配置文件运行:
在bin目录下创建配置文件test.conf: <p>
input为logstash配置输入流,logstash支持多种input方式包括file redis TCP UDP syslog lumberjack等。<p>
filter过滤logstash输入流,并可以解析输入流。<p>
ouput为logstash输出流,支持多种输出方式如elsaticearch file email tcp hdfs等,并可以配置相关参数如在es中配置索引名和type名<p>
<p> 示例使用file方式获取logstash输入流需将path更改为项目log地址<p>
```
input {
file{
path => "C:\Users\zjl\.IntelliJIdea2016.2\system\tomcat\Unnamed_hap-parent\logs\hap.log"
start_position =>"beginning"
}
}
filter{
if ([message] =~ "^\s") {
drop {}
}
grok{
match => ["message", " .* %{GREEDYDATA:level} \[%{GREEDYDATA:accountId}\] \[%{GREEDYDATA:requestId}\] %{GREEDYDATA:dao} - %{GREEDYDATA:info}\s"]
}
}
output {
stdout {
}
elasticsearch {
hosts => "localhost:9200"
}
}
```
<p>若使用tcp为logstash配置输入修改logback.xml文件添加输出方式<p>
```
<appender name="stash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%X{accountId}] [%X{requestId}] %logger - %msg%n</pattern>
</encoder>
<destination>elk-hap:4560</destination></appender>
```
<p>
相关文档:http://kibana.logstash.es/content/logstash/plugins/input/file.html
<p>
在Logstash文件/bin目录下打开终端输入logstsh -f test.conf运行logstash解析日志文件 <p>
作为一个要长期运行的程序。发行包内都带有sysV或者systemd风格的启动程序配置,你只需要直接使用即可,以RPM为例 /etc/init.d/logstash 脚本中,会加载 /etc/init.d/functions 库文件,利用其中的 daemon 函数,将 logstash 进程作为后台程序运行。所以,你只需把自己写好的配置文件,统一放在 /etc/logstash/conf.d 目录下(注意目录下所有配置文件都应该是 .conf 结尾,且不能有其他文本文件存在。因为 logstash agent 启动的时候是读取全文件夹的),然后运行 service logstash start 命令即可。<p>
![](/assets/logstash.png)
<p>
### Kibana:
##### 打开文件bin目录下kibana.bat开启服务 <p> <p>
##### 浏览器打开localhost:5601查看通过logstash解析的日志文件
##### config/kibana.yml文件可进行对kibana相关配置 <p> <p>
![](/assets/kibana.png)
![](/assets/kibanaview.png)
# 锁机制
融租易提供两种锁机制, 满足项目上对数据并发修改的需求.
## 1.数据库锁
***
根据适当的参数进行物理锁定(数据库级锁),支持3种数据库:oracle,mysql,sqlserver。提供 API, 自动执行 sql
>
mysql,orcale 执行 select * from xxx where ... for update
> sqlserver 执行 select * from xxx with (ROWLOCK) where ...
> 都是数据库原生的锁机制
使用方式:
### 单数据源
在Java代码中,注入`DatabaseLockProvider`类,
```java
public class XXXServiceImpl {
@Autowired
private DatabaseLockProvider databaseLockProvider;
public int update (XXX dto, ...){
// 传入锁定对象,锁定数据库相关行
databaseLockProvider.lock(dto);
//...
}
}
```
### 多数据源
在Java代码中,`自己创建DatabaseLockProvider类`,指定`dataSource`
```java
public class XXXServiceImpl {
@Autowired
@Qualifier("xxxDataSource")
private DataSource dataSource;
private DatabaseLockProvider databaseLockProvider;
@Transactional(propagation = Propagation.REQUIRED)
public int update (XXX dto, ...){
databaseLockProvider = new DatabaseLockProvider(dataSource)
// 传入锁定对象,锁定数据库相关行
databaseLockProvider.lock(dto);
//...
}
}
```
> 事务提交以后,锁会自动释放
DatabaseLockProvider提供的接口
```java
//根据传入对象,自动加锁。
//确保bean上有@Table 注解,能自动解析出对应的表。 默认根据有@ID注解的字段进行加锁,确保id有值
public void lock(Object dto)
//根据传入对象和自定义的where条件,自动加锁。
//传入类似 "name = ? and age = ?" 的条件语句,根据whereCondition,依次对应传入属性对应的值。
public void lock(Object dto, String whereCondition, Object... whereParameter)
// 可以自定义表名,不必传入dto
public void lock(String tableName, String whereCondition, Object... whereParameter)
```
## 2.分布式锁
基于`redis`的锁,实现跨平台, 分布式锁
使用方式:
1.根据实际配置的redis,修改配置文件`config.properties`
```properties
redisson.server.url=127.0.0.1:6379
#redissson.server.password=
```
> 支持`多节点`配置,按照如下规范配置
>redisson.server.url=\
> 127.0.0.1:6379,\
> 10.211.103.142:6379
>内部使用redisson提供的`RedLock`进行加锁
2.在java代码中注入DistributedLockProvider
```java
public class XXXServiceImpl {
@Autowired
@Qualifier("distributeLockTemplate")
private DistributedLockProvider distributedLockProvider;
public int update (XXX dto, ...){
//使用回调方式,执行自己的业务逻辑
distributedLockProvider.lock(dto,new DistributedLockCallback<Object>() {
@Override
public Object process() {
//doSomething();
return null;
})
}
}
```
> 回调函数执行以后,锁都会自动释放
DistributedLockProvider提供的接口:
```java
/**
* 使用分布式锁,使用锁默认超时时间。
*
* @param lockKey
* 加锁对象,确保有@ID属性,建议BaseDto
* @param callback
* @return 回调函数返回的内容
*/
<T> T lock(Object lockKey, DistributedLockCallback<T> callback);
/**
* 使用分布式锁,使用锁默认超时时间。
*
* @param lockKey
* 确保唯一
* @param callback
* @return 回调函数返回的内容
*/
<T> T lock(String lockKey, DistributedLockCallback<T> callback);
/**
* 使用分布式锁。自定义锁的超时时间
*
* @param lockKey
* 加锁对象,确保有@ID属性,建议BaseDto
* @param callback
* @param leaseTime
* 锁超时时间。超时后自动释放锁。
* @param timeUnit
* @return 回调函数返回的内容
*/
<T> T lock(Object lockKey, DistributedLockCallback<T> callback, long leaseTime, TimeUnit timeUnit);
/**
* 使用分布式锁。自定义锁的超时时间
*
* @param lockKey
* 确保唯一
* @param callback
* @param leaseTime
* 锁超时时间。超时后自动释放锁。
* @param timeUnit
* @return 回调函数返回的内容
*/
<T> T lock(String lockKey, DistributedLockCallback<T> callback, long leaseTime, TimeUnit timeUnit);
/**
* 使用分布式锁,使用锁默认超时时间。
*
* @param lockKey
* 确保唯一
* @param callback
* @return 回调函数返回的内容
*
* @exception Exception 加锁过程的异常,比如锁已被占用,加锁失败
*/
<T> T tryLock(String lockKey, DistributedLockCallback<T> callback) throws Exception;
/**
* 使用分布式锁,使用锁默认超时时间。默认等待时间1秒
*
* @param lockKey
* 加锁对象,确保有@ID属性,建议BaseDto
* @param callback
* @return 回调函数返回的内容
*
* @exception Exception 加锁过程的异常,比如锁已被占用,加锁失败
*/
<T> T tryLock(Object lockKey, DistributedLockCallback<T> callback) throws Exception;
/**
* 使用分布式锁。自定义锁的超时时间
*
* @param lockKey
* 加锁对象,确保有@ID属性,建议BaseDto
* @param callback
* @param waitTime
* 获取锁等待时间,超过设置时间未获得锁则抛出异常
* @param leaseTime
* 锁超时时间。超时后自动释放锁。
* @param timeUnit
* waitTime,leaseTime 时间单位
* @return 回调函数返回的内容
*
* @exception Exception 加锁过程的异常,比如锁已被占用,加锁失败
*/
<T> T tryLock(Object lockKey, DistributedLockCallback<T> callback, long waitTime, long leaseTime, TimeUnit timeUnit)
throws Exception;
/**
* 使用分布式锁。自定义锁的超时时间
*
* @param lockKey
* 确保唯一
* @param callback
* @param waitTime
* 获取锁等待时间,超过设置时间未获得锁则抛出异常
* @param leaseTime
* 锁超时时间。超时后自动释放锁。
* @param timeUnit
* waitTime,leaseTime 的时间单位
* @return 回调函数返回的内容
*
* @exception Exception 加锁过程的异常,比如锁已被占用,加锁失败
*/
<T> T tryLock(String lockKey, DistributedLockCallback<T> callback, long waitTime, long leaseTime, TimeUnit timeUnit)
throws Exception;
```
# 用户安全策略
框架提供标准的用户安全策略接口
com.hand.hap.security.IUserSecurityStrategy
> 默认实现DefaultUserSecurityStrategy,order值为9999
编写自定义实现类,需要在 Spring 中定义为 bean (也可以通过 @Component之类的注解自动扫描注册)
可以实现下列方法,自定义安全策略:
### 登录成功以后,跳转至index页面前的策略
```java
ModelAndView loginVerifyStrategy(User user, HttpServletRequest request);
```
参数及返回类型说明
> - user 通过登录验证的User对象
- ModelAndView 重定向到该 ModelAndView
>
如果想要正常跳转到index页面,请返回null
注意:会根据order大小依次执行实现类的该方法,注意顺序
### 用户修改密码时,自定义密码复杂度
```java
void passwordVerifyStrategy(IRequest request ,User user,String oldPwd, String newPwd, String newPwdAgain) throws UserException;
```
参数及异常说明
> - user 通过登录验证的User对象
- oldPwd 旧密码
- newPwd 新密码
- newPwdAgain 再次输入的新密码
- 如果验证不通过,请抛出自定义的UserException
一般来说修改了复杂度验证策略,需要修改sys_config页面。
### 新建用户时的策略
```java
User beforeCreateUser(IRequest request ,User user)
```
可以对用户做统一的信息处理,如统一设置一些属性值,注意如果实现了该方法,一定要返回处理后的User对象,默认返回传入的user
> 实现IAuthenticationSuccessListener
接口, 是在用户登录验证成功时执行.
>
一般用来往session里面放一些值,或其他逻辑,如果抛出异常,则会在login页面显示异常信息,注意区别。
......@@ -162,7 +162,7 @@ public class demoJob extends AbstractJob{
#### 5.1 通过post请求直接创建周期任务
访问`"/hls/job/create"`地址,必须要为post请求类型,请求体中的参数也必须为json格式,如下:
访问`"/hls/job/create"`地址,必须要为post请求类型,方法返回的值为jobId,请求体中的参数也必须为json格式,如下:
```
{
......@@ -187,6 +187,10 @@ json格式说明:
* jobCreateDto:该元素中,只有job是自己定义的,其他全部按照如上所示的规范填写。
* taskId:taskId表示在任务维护中,定义的任务的ID,创建的job执行的类实际上是根据任务中定义的类,所以请确保此处填写无误。
* scheduleName:scheduleName表示任务周期中定义的周期名,任务会按照scheduleName对应的周期执行。
* defineStartTime:自定义的任务开始时间,如果有需要则填写,否则直接根据周期定义中的开始时间执行。
* defineEndTime:自定义的任务结束时间,如果有需要则填写,否则直接根据周期定义中的时间结束。
* defineStartTime:自定义的任务开始时间,如果有需要则填写,否则直接根据周期定义中的开始时间执行,传到后台的值必须为Long类型
* defineEndTime:自定义的任务结束时间,如果有需要则填写,否则直接根据周期定义中的时间结束,传到后台的值必须为Long类型
* businessParam:业务所需的参数,填写后可以在任务执行时获取到。
#### 5.2 通过service中的方法创建周期任务
注入`HlsJobCreateService`,调用的方法为`createHlsJob(HlsJobDto hlsJobDto, IRequest requestCtx)`,其中HlsJobDto参数可以与上述的json相互转换,实现的效果也是一致的。
\ No newline at end of file
......@@ -18,6 +18,12 @@
* 2.3 Checkstyle
* III. 后端开发
* [3.1 用户安全策略](/后端开发/user-security-strategy.md)
* [3.2 审计](/后端开发/audit.md)
* [3.3 锁机制](/后端开发/lock.md)
* [3.4 日志管理](/后端开发/elk.md)
* [3.5 代码生成器](/后端开发/code-generator.md)
* [3.6 跨域访问](/后端开发/3.24-cors.md)
* IV. 前端JavaScript开发
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment