提交 514c0194 编写于 作者: 如梦技术's avatar 如梦技术 🐛

📝 完善文档.

上级 4c9a91de
# 模块说明
## mica-auto
1. 编译期生成 `spring.factories`
2. 编译期生成 `spring-devtools.properties`
3. 编译期生成 `FeignClient` 信息到 `spring.factories` 中,供 `mica-cloud` 中完成 `Feign` 自动化配置。
`文档地址`[https://gitee.com/596392912/mica-auto](https://gitee.com/596392912/mica-auto)
## mica-core
- 常用工具包,基于 `Spring-core` 扩展增强,无其他依赖。
- 增强 cglib Bean copy,高性能(接近直接 get set),支持链式 bean,支持自动类型转换 。
- `$` 工具类快捷方法,不用再记忆到底有哪些工具类。
- 统一消息返回体,封装得更加好用。
- Spring 枚举转换器,规则同 Jackson。
`文档地址`[mica-core](https://www.dreamlu.net/docs/utils-common.html)
## mica-http
- `mica-http``okhttp` 的封装,Fluent 语法的 http 工具包,语法参考 HttpClient Fluent API。
`文档地址`[mica-http](mica-http/README.md)
## mica-spider
- `mica-spider` 是基于 `mica-http` 的爬虫工具。
`文档地址`[mica-spider](mica-spider/README.md)
## mica-laytpl
- laytpl 模板(将其引入到 java 中)
`文档地址`[mica-laytpl](mica-laytpl/README.md)
## mica-captcha
- 验证码,支持 `webflux``serlvet`
`文档地址`[mica-captcha](mica-captcha/README.md)
## mica-redis
- spring-data-redis 的扩展
- spring cache 支持 # 分割超时时间
- 分布式限流组件
`文档地址`[mica-redis](mica-redis/README.md)
## mica-mongo
- mongo 复杂 tree 和 jsonNode 转换处理。
`文档地址`[mica-mongo](mica-mongo/README.md)
## mica-swagger
- `swagger``knife4j` 依赖,自动化配置。
`文档地址`[mica-swagger](mica-swagger/README.md)
## mica-ip2region
- ip 获取地址位置扩展
`文档地址`[mica-ip2region](mica-ip2region/README.md)
## mica-jobs
- xxl job stater,方便使用
`文档地址`[mica-jobs](mica-jobs/README.md)
\ No newline at end of file
......@@ -13,7 +13,7 @@
![犬夜叉-云母](docs/img/mica-001.jpeg)
## 使用文档
**使用文档**详见:https://www.dreamlu.net/mica2x/index.html
**使用文档**详见:[mica2.x 使用文档](MODULE.md)
[**更新记录**](CHANGELOG.md)
......
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
# mica 验证码
## 功能
## 图示
![数学验证码01](../docs/images/0701.m.jpg)
![数学验证码02](../docs/images/0702.m.jpg)
![随机数验证码03](../docs/images/0703.r.jpg)
![随机数验证码04](../docs/images/0703.r.jpg)
## 功能和特点
1. 验证码生成
2. 验证码缓存
3. 内置字体
## 使用
### maven
......@@ -18,3 +26,74 @@
```groovy
compile("net.dreamlu:mica-captcha:${version}")
```
## 配置
| 对象 | 默认值 | 说明 |
| ------------------------- | ------------------- | ---------------------------------- |
| mica.captcha.captcha-type | RANDOM(随机) | RANDOM(随机)MATH(算术) |
| mica.captcha.cache-name | captcha:cache#5m, | cache 名称,配合 mica-redis、mica-redisson 5分钟缓存 |
注意:
1. 单服务可以采用 `guava``ehcache``caffeine` 等内存缓存。
2. 分布式下可以使用 `redis` 等。
3. 如果不是用 `spring cache`,可自行实现 `ICaptchaCache` 注册成 `Spring bean` 即可。
## 使用文档
### 导入 Bean
```java
@Autowired
ICaptchaService captchaService;
```
### 方法
```java
/**
* 生成验证码
*
* @param uuid 自定义缓存的 uuid
* @param outputStream OutputStream
*/
void generate(String uuid, OutputStream outputStream);
/**
* 生成验二进制证码
*
* @param uuid 自定义缓存的 uuid
* @return bytes
*/
byte[] generateBytes(String uuid);
/**
* 生成验 Resource 证码
*
* @param uuid 自定义缓存的 uuid
* @return ByteArrayResource
*/
ByteArrayResource generateByteResource(String uuid);
/**
* 生成验证码 base64 字符串
*
* @param uuid 自定义缓存的 uuid
* @return base64 图片
*/
String generateBase64(String uuid);
/**
* 生成验证码
*
* @param uuid uuid
* @return {ResponseEntity}
*/
ResponseEntity<Resource> generateResponseEntity(String uuid);
/**
* 校验验证码
*
* @param uuid 自定义缓存的 uuid
* @param userInputCaptcha 用户输入的图形验证码
* @return 是否校验成功
*/
boolean validate(String uuid, String userInputCaptcha);
```
\ No newline at end of file
......@@ -20,4 +20,68 @@
### gradle
```groovy
compile("net.dreamlu:mica-core:${version}")
```
\ No newline at end of file
```
## 工具类说明
### 常量池
| 类名 | 说明 |
| ----- | ------ |
| Charsets | 字符集常量池 |
| CharPool | Char常量池 |
| StringPool | 字符串常量池 |
### 常用工具类
| 类名 | 说明 |
| ----- | ------ |
| StringUtil | 字符串工具类 |
| ObjectUtil | Object工具类 |
| JsonUtil | json处理工具 |
| DateUtil | 时间处理工具 |
| BeanUtil | bean处理工具 |
| NumberUtil | Number工具类 |
| CollectionUtil | 集合工具类 |
| FileUtil | File工具类 |
| IoUtil | io工具类 |
### 签名加密工具类
| 类名 | 说明 |
| ----- | ------ |
| HexUtil | hex工具类 |
| DigestUtil | md5、sha、hmc等 |
| Base64Util | Base64 |
| AesUtil | Aes |
| DesUtil | Des |
| RsaUtil | Rsa |
### 类、反射工具
| 类名 | 说明 |
| ----- | ------ |
| ClassUtil | 类工具类 |
| ConvertUtil | 类型转换工具类 |
| ReflectUtil | 反射工具类 |
### 线程、异常等工具类
| 类名 | 说明 |
| ----- | ------ |
| ThreadUtil | 线程工具类 |
| ThreadLocalUtil | 本地线程工具类 |
| Exceptions | 异常处理工具类 |
| Unchecked | lambda 异常包装类 |
### 其他工具类
| 类名 | 说明 |
| ----- | ------ |
| CountMap | 计数器 |
| Lazy | 延迟加载 |
| Once | 一次加载 |
| Holder | 部分常量 |
| Version | Version工具 |
| XmlHelper | xml处理 |
| INetUtil | 网络工具类 |
| PathUtil | 路径工具类 |
| ResourceUtil | 资源工具类 |
| SystemUtil | 系统工具类 |
| RuntimeUtil | 系统运行时工具类 |
| UrlUtil | url工具类 |
| WebUtil | web工具类 |
......@@ -29,3 +29,148 @@ spring-retry 为可选依赖,用来对 http 结果断言重试。
```groovy
compile("org.springframework.retry:spring-retry:${springRetryVersion}")
```
## 基础用法
```java
// 设定全局日志级别 NONE,BASIC,HEADERS,BODY, 默认:NONE 和 self4
HttpRequest.setGlobalLog(LogLevel.BODY);
// 设置控制台日志,用于没有日志依赖的 sdk 开发时使用
HttpRequest.setGlobalLog(HttpLogger.Console, LogLevel.BODY);
```
```java
// 同步请求 url,方法支持 get、post、patch、put、delete
HttpRequest.get("https://www.baidu.com")
.useSlf4jLog() //使用 Slf4j 日志,同类的有 .useConsoleLog(),日志级别为 BODY
.addHeader("x-account-id", "mica001") // 添加 header
.addCookie(new Cookie.Builder() // 添加 cookie
.name("sid")
.value("mica_user_001")
.build()
)
.query("q", "mica") //设置 url 参数,默认进行 url encode
.queryEncoded("name", "encodedValue")
.formBuilder() // 表单构造器,同类 multipartFormBuilder 文件上传表单
.add("id", 123123) // 表单参数
.retryOn(responseSpec -> !responseSpec.isOk()) // 结合 spring retry 进行结果集断言
.proxy(InetSocketAddress.createUnresolved("127.0.0.1", 8080)) // 设置代理
.execute() // 发起请求
.asJsonNode(); // 结果集转换,注:如果网络异常等会直接抛出异常。
// 同类的方法有 asString、asBytes
// json 类响应:asJsonNode、asValue、asList、asMap、atJsonPath、,采用 jackson 处理
// file 文件:toFile
// 同步
String html = HttpRequest.post("https://www.baidu.com")
.execute()
.onFailed((request, e) -> {// 网络等异常情况的消费处理,可无
e.printStackTrace();
})
.onResponse(ResponseSpec::asString);// 处理响应,有网络异常等直接返回 null
// 同步
Document document = HttpRequest.patch("https://www.baidu.com")
.execute()
.onSuccess(DomMapper::asDocument);
// onSuccess http code in [200..300) 处理响应,有网络异常等直接返回 null
// 发送异步请求
HttpRequest.delete("https://www.baidu.com")
.async() // 开启异步
.onFailed((request, e) -> { // 异常时的处理
e.printStackTrace();
})
.onResponse(responseSpec -> { // 消费响应, 注意:响应的流只能读一次
int httpCode = responseSpec.code();
})
.onSuccessful(responseSpec -> { // 消费响应成功 http code in [200..300)
// 注意:响应结果流只能读一次
JsonNode jsonNode = responseSpec.asJsonNode();
})
.execute(); // 异步最后发起请求
```
## 示例
### 示例代码1
```java
// 设置全局日志级别
HttpRequest.setGlobalLog(LogLevel.BODY);
// 直接用 jackson json path 语法
private String getUserEmail(String accessToken) {
return HttpRequest.get("https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))")
.addHeader("Host", "api.linkedin.com")
.addHeader("Connection", "Keep-Alive")
.addHeader("Authorization", "Bearer " + accessToken)
.execute()
.asJsonNode()
.at("/elements/0/handle~0/emailAddress")
.asText();
}
// 异步
public static void test() {
HttpRequest.post("https://www.baidu.com/do-stuff")
.log(LogLevel.BASIC) // 日志级别
.formBuilder() // 表单构造器
.add("a", "b")
.async() // 使用异步
.onSuccessful(System.out::println) // 异步成功时的函数
.onFailed((request, e) -> { // 异步失败,可无
e.printStackTrace();
})
.execute();
}
```
### 示例代码2
```java
HttpRequest.setGlobalLog(LogLevel.BODY);
// 同步,异常时 返回 null
String html = HttpRequest.get("www.baidu.com")
.connectTimeout(Duration.ofSeconds(1000))
.query("test", "a")
.query("name", "張三")
.query("x", 1)
.query("abd", Base64Util.encode("123&$#%"))
.queryEncoded("abc", Base64Util.encode("123&$#%"))
.execute()
.onFailed(((request, e) -> {
e.printStackTrace();
}))
.onSuccess(ResponseSpec::asString);
System.out.println(html);
// 同步调用,返回 Optional,异常时返回 Optional.empty()
Optional<String> opt = HttpRequest.post(URI.create("https://www.baidu.com"))
.bodyString("Important stuff")
.formBuilder()
.add("a", "b")
.execute()
.onSuccessOpt(ResponseSpec::asString);
// 同步,成功时消费(处理) response
HttpRequest.post("https://www.baidu.com/some-form")
.addHeader("X-Custom-header", "stuff")
.execute()
.onSuccessful(responseSpec -> {
String text = responseSpec.asString();
System.out.println(text);
});
// 同步,异常时直接抛出
HttpRequest.get("https://www.baidu.com/some-form")
.execute()
.asString();
// async,异步执行结果,失败时打印堆栈
HttpRequest.get("https://www.baidu.com/some-form")
.async()
.onSuccessful(System.out::println)
.onFailed((request, e) -> {
e.printStackTrace();
})
.execute();
```
\ No newline at end of file
......@@ -20,3 +20,92 @@ jmh 实测性能不是很出色,约为 `Thymeleaf` 的 `1/2` 适合用于对
compile("net.dreamlu:mica-laytpl:${version}")
```
## 使用
```java
@Autowired
private MicaTemplate micaTemplate;
```
```java
Map<String, Object> data = new HashMap<>();
data.put("title", "mica");
String html = micaTemplate.render("<h3>{{ d.title }}</h3>", data);
```
```java
Map<String, Object> data = new HashMap<>();
data.put("title", "mica");
// renderTpl 将渲染 classpath:templates/tpl/ 下的模板文件
String html = micaTemplate.renderTpl("test.html", data);
```
## 模版语法
| 语法 | 说明 |
| ----------------- | ------------------------------------------------------------ |
| {{ d.field }} | 输出一个普通字段,不转义html |
| {{= d.field }} | 输出一个普通字段,并转义html |
| {{# JS表达式 }} | JS 语句。一般用于逻辑处理。用分隔符加 # 号开头。注意:如果你是想输出一个函数,正确的写法是:{{ fn() }},而不是:{{# fn() }} |
| {{! template !}} | 对一段指定的模板区域进行过滤,即不解析该区域的模板。 |
## 内置对象
| 对象 | 说明 |
| ------- | ------- |
| console | 同 js console 可使用 console.log 打印日志,采用 Slf4j 做的嫁接 |
| fmt | 格式化时间或者数字 fmt.format( d.date )),或者 fmt.format( d.date, "yyyy-MM-dd" )) 自定义格式。|
| mica | 使用 mica.use("sec") 在模板中使用 spring bean |
## 日志和格式
```html
{{#
console.log();
console.log("im {}", "L.cm");
console.error("hi im {}", "L.cm");
console.log("laytpl version:{}", laytpl.v);
console.log(fmt.format( d.date ));
}}
```
## 使用 Spring bean
```html
测试tpl中使用spring bean:
直接使用 mica.use("sec"); 方法传参beanName,即可。
示例:
<br>
{{# mica.use("sec").hasPermission('admin:add') }}
<br>
```
## 拓展阅读
巧用 java 调用 js,解决一些小问题。
### 使用场景
1. 执行爬虫登录中的加解密算法,部分 js 中的加解密算法和 java 的不能正常通用。
### 示例(巧妙解析 jsonp)
```java
public static void main(String[] args) throws ScriptException {
String jsonp = "/**/callback( {\"client_id\":\"123\",\"openid\":\"123\",\"unionid\":\"123\"} )";
// 构造 jsonp 的 function
String jsFun = "function callback(json) { return json };";
// 加载 js 引擎
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByMimeType("text/javascript");
// 执行
engine.eval(jsFun);
// 读取结果
Map json = (Map) engine.eval(jsonp);
System.out.println(json);
}
```
\ No newline at end of file
## 说明
用于 jackson 和 mongo 复杂 tree 处理
\ No newline at end of file
# 说明文档
用于 `jackson``mongo` 复杂 tree 处理。
## 功能
* 将模型属性定义为 JsonNode 对象,自动序列号和反序列化。
## 示例
```java
@Data
@Persistent
@Document(collection = "testConfig")
public class TestConfig {
@Id
private String id;
private JsonNode settings;
// ...
}
```
......@@ -16,3 +16,134 @@
```groovy
compile("net.dreamlu:mica-redis:${version}")
```
## 使用文档
#### 1. redis cache 增强
1. 支持 # 号分隔 cachename 和 超时,支持 ms(毫秒),s(秒默认),m(分),h(小时),d(天)等单位。
示例:
```java
@Cacheable(value = "user#5m", key = "#id")
public String selectById(Serializable id) {
log.info("selectById");
return "selectById:" + id;
}
```
### MicaRedisCache
MicaRedisCache 为简化 redis 使用的 bean。
```java
@Autowired
private MicaRedisCache redisCache;
@Override
public String findById(Serializable id) {
return redisCache.get("user:" + id, () -> userMapper.selectById(id));
}
```
### 2. 分布式限流
#### 2.1 开启限流组件
```yaml
mica:
redis:
rate-limiter:
enable: true
```
### 2.2 使用注解
```java
@RateLimiter
```
注解变量:
```java
/**
* 限流的 key 支持,必须:请保持唯一性
*
* @return key
*/
String value();
/**
* 限流的参数,可选,支持 spring el # 读取方法参数和 @ 读取 spring bean
*
* @return param
*/
String param() default "";
/**
* 支持的最大请求,默认: 2500
*
* @return 请求数
*/
long max() default 2500L;
/**
* 持续时间,默认: 3600
*
* @return 持续时间
*/
long ttl() default 3600L;
/**
* 时间单位,默认为秒
*
* @return TimeUnit
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
```
#### 2.3 使用 Client
```java
@Autowired
private RateLimiterClient rateLimiterClient;
```
方法:
```java
/**
* 服务是否被限流
*
* @param key 自定义的key,请保证唯一
* @param max 支持的最大请求
* @param ttl 时间,单位默认为秒(seconds)
* @return 是否允许
*/
boolean isAllowed(String key, long max, long ttl);
/**
* 服务是否被限流
*
* @param key 自定义的key,请保证唯一
* @param max 支持的最大请求
* @param ttl 时间
* @param timeUnit 时间单位
* @return 是否允许
*/
boolean isAllowed(String key, long max, long ttl, TimeUnit timeUnit);
/**
* 服务限流,被限制时抛出 RateLimiterException 异常,需要自行处理异常
*
* @param key 自定义的key,请保证唯一
* @param max 支持的最大请求
* @param ttl 时间
* @param supplier Supplier 函数式
* @return 函数执行结果
*/
<T> T allow(String key, long max, long ttl, CheckedSupplier<T> supplier);
/**
* 服务限流,被限制时抛出 RateLimiterException 异常,需要自行处理异常
*
* @param key 自定义的key,请保证唯一
* @param max 支持的最大请求
* @param ttl 时间
* @param supplier Supplier 函数式
* @return 函数执行结果
*/
<T> T allow(String key, long max, long ttl, TimeUnit timeUnit, CheckedSupplier<T> supplier);
```
\ No newline at end of file
......@@ -15,3 +15,164 @@
```groovy
compile("net.dreamlu:mica-spider:${version}")
```
## 使用文档
注意:清先阅读 `mica-http` 部分文档。
### DomMapper 工具
`DomMapper` 工具采用 `cglib` 动态代理和 `Jsoup` html 解析,不到 `200` 行代码实现了 `html``java Bean` 工具,爬虫必备。
主要方法有:
- DomMapper.asDocument
- DomMapper.readDocument
- DomMapper.readValue
- DomMapper.readList
### CssQuery 注解说明
```java
public @interface CssQuery {
/**
* CssQuery
*
* @return CssQuery
*/
String value();
/**
* 读取的 dom attr
*
* <p>
* attr:元素对于的 attr 的值
* html:整个元素的html
* text:元素内文本
* allText:多个元素的文本值
* </p>
*
* @return attr
*/
String attr() default "";
/**
* 正则,用于对 attr value 处理
*
* @return regex
*/
String regex() default "";
/**
* 默认的正则 group
*/
int DEFAULT_REGEX_GROUP = 0;
/**
* 正则 group,默认为 0
*
* @return regexGroup
*/
int regexGroup() default DEFAULT_REGEX_GROUP;
/**
* 嵌套的内部模型:默认 false
*
* @return 是否为内部模型
*/
boolean inner() default false;
}
```
## 示例代码
### 爬取开源中国首页
```java
// 同步,异常返回 null
Oschina oschina = HttpRequest.get("https://www.oschina.net")
.execute()
.onSuccess(responseSpec -> responseSpec.asDomValue(Oschina.class));
if (oschina == null) {
return;
}
System.out.println(oschina.getTitle());
System.out.println("热门新闻");
List<VNews> vNews = oschina.getVNews();
for (VNews vNew : vNews) {
System.out.println("title:\t" + vNew.getTitle());
System.out.println("href:\t" + vNew.getHref());
System.out.println("时间:\t" + vNew.getDate());
}
System.out.println("热门博客");
List<VBlog> vBlogList = oschina.getVBlogList();
for (VBlog vBlog : vBlogList) {
System.out.println("title:\t" + vBlog.getTitle());
System.out.println("href:\t" + vBlog.getHref());
System.out.println("阅读数:\t" + vBlog.getRead());
System.out.println("评价数:\t" + vBlog.getPing());
System.out.println("点赞数:\t" + vBlog.getZhan());
}
```
### 模型1
```java
@Getter
@Setter
public class Oschina {
@CssQuery(value = "head > title", attr = "text")
private String title;
@CssQuery(value = "#v_news .page .news", inner = true) // 标记为嵌套模型
private List<VNews> vNews;
@CssQuery(value = ".blog-container .blog-list div", inner = true) // 标记为嵌套模型
private List<VBlog> vBlogList;
}
```
### 模型2
```java
@Setter
@Getter
public class VNews {
@CssQuery(value = "a", attr = "title")
private String title;
@CssQuery(value = "a", attr = "href")
private String href;
@CssQuery(value = ".news-date", attr = "text")
@DateTimeFormat(pattern = "MM/dd")
private Date date;
}
```
### 模型3
```java
@Getter
@Setter
public class VBlog {
@CssQuery(value = "a", attr = "title")
private String title;
@CssQuery(value = "a", attr = "href")
private String href;
//1341阅/9评/4赞
@CssQuery(value = "span", attr = "text", regex = "^\\d+")
private Integer read;
@CssQuery(value = "span", attr = "text", regex = "(\\d*).*/(\\d*).*/(\\d*).*", regexGroup = 2)
private Integer ping;
@CssQuery(value = "span", attr = "text", regex = "(\\d*).*/(\\d*).*/(\\d*).*", regexGroup = 3)
private Integer zhan;
}
```
\ No newline at end of file
......@@ -20,6 +20,44 @@
compile("net.dreamlu:mica-swagger:${version}")
```
## 配置
| 配置项 | 默认值 | 说明 |
| ----- | ------ | ------ |
| mica.swagger.enabled | true | 是否开启 swagger,默认:true |
| mica.swagger.title | XXX服务 | 标题,默认:XXX服务 |
| mica.swagger.description | XXX服务 | 详情,默认:XXX服务 |
| mica.swagger.version | V1.0 | 版本号,默认:V1.0 |
| mica.swagger.headers | 无 | 全局统一请求头 |
| mica.swagger.contact-email | 无 | 组织邮箱 |
| mica.swagger.contact-url | 无 | 组织url |
| mica.swagger.contact-user | 无 | 组织名 |
| mica.swagger.authorization.auth-regex | ^.*$ | 需要开启鉴权URL的正则,默认:^.*$ |
| mica.swagger.authorization.enabled | false | 开启Authorization,默认:false |
| mica.swagger.authorization.key-name | TOKEN | 鉴权传递的Header参数,默认:TOKEN |
| mica.swagger.authorization.name | Authorization | 鉴权策略ID,对应 SecurityReferences ID,默认:Authorization |
## 使用
**注意**: 添加有 `@Api` 注解的控制器才会自动暴露给 `swagger`
```java
/**
* demo 服务
*
* @author L.cm
*/
@Validated
@RestController
@Api("demo服务")
@RequiredArgsConstructor
public class DemoController {
private final AccountService accountService;
@ApiOperation("demo")
@GetMapping("/demo")
public R<AccountVO> demo() {
return accountService.getAccount();
}
}
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册