Initial commit

This commit is contained in:
Eric
2026-01-16 18:51:16 +08:00
commit 98c057de11
280 changed files with 16665 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>lingniu-framework-demo</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-apollo</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-redisson</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-jetcache</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-xxljob</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-mybatis</artifactId>
</dependency>
<!-- todo mybatis-demo使用h2数据库-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-rocketmq</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-easyexcel</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-prometheus</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-web</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-microservice-common</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-microservice-nacos</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,16 @@
package cn.lingniu.demo;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = {"cn.lingniu.*"})
//jetcache 注解
@EnableMethodCache(basePackages = "cn.lingniu")
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

View File

@@ -0,0 +1,31 @@
package cn.lingniu.demo.apollo;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
@Component
@Slf4j
public class ApolloConfigChangeDemoListener {
@ApolloConfigChangeListener()
public void onChange(ConfigChangeEvent changeEvent) {
for (String changedKey : changeEvent.changedKeys()) {
ConfigChange changeInfo = changeEvent.getChange(changedKey);
if(StringUtils.isEmpty(changeInfo)){continue;}
log.info("apollo 配置变更 \r\n\t命名空间:{} \r\n\t属性:{} \r\n\t原值:{}\r\n\t新值:{}\r\n\t变更类型:{}"
,changeInfo.getNamespace()
,changeInfo.getPropertyName()
,changeInfo.getOldValue()
,changeInfo.getNewValue()
,changeInfo.getChangeType()
);
}
}
}

View File

@@ -0,0 +1,26 @@
package cn.lingniu.demo.apollo;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping(value = "/demo/apollo")
public class ApolloController {
@Autowired
private ObjectDemoConfig objectDemoConfig;
@GetMapping("/apolloDemoConfig")
public ObjectDemoConfig apolloDemoConfig() {
System.out.println("apolloDemoConfig:" + JSONObject.toJSONString(objectDemoConfig));
return objectDemoConfig;
}
}

View File

@@ -0,0 +1,15 @@
package cn.lingniu.demo.apollo;
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableApolloConfig
public class ObjcetDemoConfiguration {
@Bean
public ObjectDemoConfig apolloDemoConfig() {
return new ObjectDemoConfig();
}
}

View File

@@ -0,0 +1,39 @@
package cn.lingniu.demo.apollo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@ConfigurationProperties(prefix = "apollo.demo")
public class ObjectDemoConfig implements Serializable {
private String stringDemo = "";
private Boolean booleanDemo = true;
private List<String> listDemo = Lists.newArrayList();
private Set<String> setDemo = Sets.newHashSet();
private Map<String, String> hashDemo = Maps.newHashMap();
private Map<String, ObjectDemo> hashObjectDemo = Maps.newHashMap();
private ObjectDemo objectDemo = new ObjectDemo();
@Data
public static class ObjectDemo {
private String testObjcet;
}
}

View File

@@ -0,0 +1,49 @@
package cn.lingniu.demo.db;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
@RequestMapping("/demo/db")
@Slf4j
public class JobZookeeperController {
@Autowired
JobZookeeperServerMapper jobZookeeperServerMapper;
@GetMapping("/page")
public Page<JobZookeeperServer> getJobZookeeperServerPage() {
Page<JobZookeeperServer> jobZookeeperServerPage = jobZookeeperServerMapper.selectPage(Page.of(1, 1),
new LambdaQueryWrapper<JobZookeeperServer>().select(JobZookeeperServer::getName, JobZookeeperServer::getAddress, JobZookeeperServer::getDigest,
JobZookeeperServer::getJmxEnable, JobZookeeperServer::getJmxPort, JobZookeeperServer::getMessage, JobZookeeperServer::getCreateTime,
JobZookeeperServer::getUpdateTime, JobZookeeperServer::getStatus, JobZookeeperServer::getContactPhone, JobZookeeperServer::getUserName));
log.info("jobZookeeperServerPage:{}", jobZookeeperServerPage);
return jobZookeeperServerPage;
}
@GetMapping("/add")
public JobZookeeperServer addJobZookeeperServer() {
JobZookeeperServer server = new JobZookeeperServer();
server.setName("test");
server.setAddress("127.0.0.1:2181");
server.setDigest("");
server.setJmxEnable(1);
server.setJmxPort("");
server.setMessage("");
server.setCreateTime(new Date());
server.setUpdateTime(new Date());
server.setStatus(1);
server.setContactPhone("");
server.setUserName("");
jobZookeeperServerMapper.insert(server);
log.info("Added new JobZookeeperServer: {}", server);
return server;
}
}

View File

@@ -0,0 +1,60 @@
package cn.lingniu.demo.db;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* h2 建表语句:
CREATE TABLE job_zk_namespace (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
address VARCHAR(255),
digest VARCHAR(255),
jmx_enable INTEGER DEFAULT 1,
jmx_port VARCHAR(255),
message VARCHAR(255),
create_time TIMESTAMP,
update_time TIMESTAMP,
status INTEGER DEFAULT 1,
contact_phone VARCHAR(255),
user_name VARCHAR(255)
);
*/
@Data
@TableName("job_zk_namespace")
public class JobZookeeperServer implements Serializable {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private String address;
private String digest;
private Integer jmxEnable = 1;
private String jmxPort;
private String message;
private Date createTime;
private Date updateTime;
private Integer status = 1;
private String contactPhone;
private String userName;
}

View File

@@ -0,0 +1,8 @@
package cn.lingniu.demo.db;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface JobZookeeperServerMapper extends BaseMapper<JobZookeeperServer> {
}

View File

@@ -0,0 +1,26 @@
package cn.lingniu.demo.file;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
@Getter
@Setter
@EqualsAndHashCode
public class DemoData {
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
@ExcelProperty("数字标题")
private Double doubleData;
/**
* 忽略这个字段
*/
@ExcelIgnore
private String ignore;
}

View File

@@ -0,0 +1,79 @@
package cn.lingniu.demo.file;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List;
/**
* todo https://easyexcel.opensource.alibaba.com/docs/current/quickstart/write
* easyexcel 性能好api简单上手更简单
*/
@Slf4j
@RestController
@RequestMapping("/demo/file")
public class FileController {
@GetMapping("/test1")
public String test1() {
simpleWrite();
return "success";
}
/**
* 最简单的写
* <p>
* 1. 创建excel对应的实体对象 参照{@link DemoData}
* <p>
* 2. 直接写即可
*/
public void simpleWrite() {
// 注意 simpleWrite在数据量不大的情况下可以使用5000以内具体也要看实际情况数据量大参照 重复多次写入
// 写法1 JDK8+
// since: 3.0.0-beta1
String fileName = FileTestUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, DemoData.class)
.sheet("模板")
.doWrite(() -> {
// 分页查询数据
return data();
});
// 写法2
fileName = FileTestUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去写然后写到第一个sheet名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
// 写法3
fileName = FileTestUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去写
try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
excelWriter.write(data(), writeSheet);
}
}
private List<DemoData> data() {
List<DemoData> list = ListUtils.newArrayList();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setString("字符串" + i);
data.setDate(new Date());
data.setDoubleData(0.56);
list.add(data);
}
return list;
}
}

View File

@@ -0,0 +1,76 @@
package cn.lingniu.demo.file;
import org.springframework.util.CollectionUtils;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class FileTestUtil {
public static InputStream getResourcesFileInputStream(String fileName) {
return Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName);
}
public static String getPath() {
return FileTestUtil.class.getResource("/").getPath();
}
public static TestPathBuild pathBuild() {
return new TestPathBuild();
}
public static File createNewFile(String pathName) {
File file = new File(getPath() + pathName);
if (file.exists()) {
file.delete();
} else {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
}
return file;
}
public static File readFile(String pathName) {
return new File(getPath() + pathName);
}
public static File readUserHomeFile(String pathName) {
return new File(System.getProperty("user.home") + File.separator + pathName);
}
/**
* build to test file path
**/
public static class TestPathBuild {
private TestPathBuild() {
subPath = new ArrayList<>();
}
private final List<String> subPath;
public TestPathBuild sub(String dirOrFile) {
subPath.add(dirOrFile);
return this;
}
public String getPath() {
if (CollectionUtils.isEmpty(subPath)) {
return FileTestUtil.class.getResource("/").getPath();
}
if (subPath.size() == 1) {
return FileTestUtil.class.getResource("/").getPath() + subPath.get(0);
}
StringBuilder path = new StringBuilder(FileTestUtil.class.getResource("/").getPath());
path.append(subPath.get(0));
for (int i = 1; i < subPath.size(); i++) {
path.append(File.separator).append(subPath.get(i));
}
return path.toString();
}
}
}

View File

@@ -0,0 +1,24 @@
package cn.lingniu.demo.jetcache.annotationDemo;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String email;
public User() {
}
public User(Long id, String name, String email) {
this.name = name;
this.email = email;
this.id = id;
}
}

View File

@@ -0,0 +1,53 @@
package cn.lingniu.demo.jetcache.annotationDemo;
import org.springframework.stereotype.Repository;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
@Repository
public class UserDao {
// 模拟数据库存储
private final ConcurrentHashMap<Long, User> userDatabase = new ConcurrentHashMap<>();
private final AtomicLong idGenerator = new AtomicLong(1);
/**
* 根据ID获取用户信息使用缓存
* @param id 用户ID
* @return 用户信息
*/
public User getUserById(Long id) {
return userDatabase.get(id);
}
/**
* 创建新用户
* @param user 用户信息
* @return 创建后的用户信息
*/
public User createUser(User user) {
Long id = idGenerator.getAndIncrement();
user.setId(id);
userDatabase.put(id, user);
return user;
}
/**
* 更新用户信息并更新缓存
* @param user 更新后的用户信息
* @return 更新后的用户信息
*/
public User updateUser(User user) {
userDatabase.put(user.getId(), user);
return user;
}
/**
* 删除用户并清除缓存
* @param id 用户ID
*/
public void deleteUser(Long id) {
userDatabase.remove(id);
}
}

View File

@@ -0,0 +1,59 @@
package cn.lingniu.demo.jetcache.annotationDemo;
import com.alicp.jetcache.anno.CacheInvalidate;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CacheUpdate;
import com.alicp.jetcache.anno.Cached;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserDao userDao;
/**
* 根据ID获取用户信息使用缓存
* @param id 用户ID
* @return 用户信息
*/
@Cached(area = "ca2", name = "user:", key = "#id", expire = 3600, localExpire = 600, cacheType = CacheType.BOTH)
public User getUserById(Long id) {
// 模拟数据库查询延迟
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return userDao.getUserById(id);
}
/**
* 更新用户信息并更新缓存
* @param user 更新后的用户信息
* @return 更新后的用户信息
*/
@CacheUpdate(area = "ca2", name = "user:", key = "#user.id", value = "#user")
public User updateUser(User user) {
userDao.updateUser(user);
return user;
}
/**
* 删除用户并清除缓存
* @param id 用户ID
*/
@CacheInvalidate(area = "ca2", name = "user:", key = "#id")
public void deleteUser(Long id) {
userDao.deleteUser(id);
}
public User createUser(User user) {
return userDao.createUser(user);
}
}

View File

@@ -0,0 +1,71 @@
package cn.lingniu.demo.jetcache.controller;
import cn.lingniu.demo.jetcache.annotationDemo.User;
import cn.lingniu.demo.jetcache.annotationDemo.UserService;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.SimpleCacheManager;
import com.alicp.jetcache.anno.CachePenetrationProtect;
import com.alicp.jetcache.anno.CacheRefresh;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.Cached;
import com.alicp.jetcache.template.QuickConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Slf4j
@RestController
@RequestMapping("/demo/cache")
public class JetCacheController {
@Resource
private SimpleCacheManager jcCacheManager;
@Resource
private UserService userService; //todo 可以直接使用
@GetMapping
public String cache(
@RequestParam String localArea,
@RequestParam String remoteArea) {
Cache<Object, Object> localCache = jcCacheManager.getOrCreateCache(QuickConfig.newBuilder(localArea, "user:").cacheType(CacheType.LOCAL).build());
localCache.PUT("key1", "value3");
Object value = localCache.GET("key1").getValue();
log.info("value: {}", value);
Cache<Object, Object> remoteCache = jcCacheManager.getOrCreateCache(QuickConfig.newBuilder(remoteArea, "user:").build());
remoteCache.PUT("key1", "value4");
Object value1 = remoteCache.GET("key1").getValue();
log.info("value1: {}", value1);
return "success";
}
@GetMapping("/anno")
@CachePenetrationProtect
@Cached(name = "orderCache:", key = "#orderId", expire = 10, cacheType = CacheType.BOTH)
@CacheRefresh(refresh = 10, timeUnit = TimeUnit.MINUTES)
public KeyValueEntity getOrderById(String orderId) {
KeyValueEntity keyValueEntity = new KeyValueEntity();
keyValueEntity.setId(orderId);
keyValueEntity.setKey("key");
keyValueEntity.setValue("value");
return keyValueEntity;
}
@GetMapping("/userTest")
public String userTest() {
userService.createUser(new User(1L, "create", "create" ));
User temp1 = userService.getUserById(1L);
userService.updateUser(new User(1L, "update", "update"));
User temp2 = userService.getUserById(1L);
userService.deleteUser(1L);
return "success";
}
}

View File

@@ -0,0 +1,18 @@
package cn.lingniu.demo.jetcache.controller;
import lombok.Data;
import java.io.Serializable;
/**
*
*/
@Data
public class KeyValueEntity implements Serializable {
private static final long serialVersionUID = 1L;
String id;
String key;
String value;
}

View File

@@ -0,0 +1,63 @@
package cn.lingniu.demo.job;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* XxlJob开发示例Bean模式
* <p>
* 开发步骤:
* 1、任务开发在Spring Bean实例中开发Job方法
* 2、注解配置为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")"注解value值对应的是调度中心新建任务的JobHandler属性的值。
* 3、执行日志需要通过 "XxlJobHelper.log" 打印执行日志;
* 4、任务结果默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果;
*
*/
@Component
public class SampleXxlJob {
private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);
/**
* 1、简单任务示例Bean模式
*/
@XxlJob("demoJobHandler")
public void demoJobHandler() throws Exception {
XxlJobHelper.log("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) {
XxlJobHelper.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2);
}
// default success
}
/**
* 2、分片广播任务
*/
@XxlJob("shardingJobHandler")
public void shardingJobHandler() throws Exception {
// 分片参数
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
XxlJobHelper.log("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);
// 业务逻辑
for (int i = 0; i < shardTotal; i++) {
if (i == shardIndex) {
XxlJobHelper.log("第 {} 片, 命中分片开始处理", i);
} else {
XxlJobHelper.log("第 {} 片, 忽略", i);
}
}
}
}

View File

@@ -0,0 +1,30 @@
package cn.lingniu.demo.microservice;
import cn.lingniu.framework.plugin.core.base.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/demo/cloud")
public class CloudController {
@Autowired
private DemoFeignClient demoFeignClient;
@GetMapping("/contributors")
public CommonResult<List<Contributor>> contributors() {
return demoFeignClient.contributors("OpenFeign", "feign");
}
@GetMapping("/reposNotFound")
public CommonResult<List<Contributor>> reposNotFound() {
return demoFeignClient.reposNotFound("OpenFeign", "feign");
}
}

View File

@@ -0,0 +1,9 @@
package cn.lingniu.demo.microservice;
import lombok.Data;
@Data
public class Contributor {
String login;
int contributions;
}

View File

@@ -0,0 +1,25 @@
package cn.lingniu.demo.microservice;
import cn.lingniu.framework.plugin.core.base.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(name = "lingniu-framework-provider-demo"
//外部接口配置url: @FeignClient(name = "github-api", url = "https://api.github.com"
// 方式1 配置fallback
// , fallback = GithubApiClientFallBack.class
// 方式2 配置fallbackFactory
// , fallbackFactory = GithubApiClientFallbackFactory.class
)
public interface DemoFeignClient {
@GetMapping("/repos/{owner}/{repo}/contributors")
CommonResult<List<Contributor>> contributors(@PathVariable("owner") String owner, @PathVariable("repo") String repo);
@GetMapping("/reposNotFound")
CommonResult<List<Contributor>> reposNotFound(@RequestParam("owner") String owner, @RequestParam("repo") String repo);
}

View File

@@ -0,0 +1,24 @@
package cn.lingniu.demo.microservice;
import cn.lingniu.framework.plugin.core.base.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j
@Component
public class GithubApiClientFallBack implements DemoFeignClient {
@Override
public CommonResult<List<Contributor>> contributors(String owner, String repo) {
throw new RuntimeException("contributors no fallback");
}
@Override
public CommonResult<List<Contributor>> reposNotFound(String owner, String repo) {
log.info("reposNotFoundWithFallBack");
return CommonResult.success(null);
}
}

View File

@@ -0,0 +1,21 @@
package cn.lingniu.demo.microservice;
import cn.lingniu.framework.plugin.core.exception.ServerException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
*
*/
@Slf4j
@Component
public class GithubApiClientFallbackFactory implements FallbackFactory<GithubApiClientFallBack> {
@Override
public GithubApiClientFallBack create(Throwable cause) {
if (cause instanceof ServerException) {
return new GithubApiClientFallBack();
}
return null;
}
}

View File

@@ -0,0 +1,82 @@
package cn.lingniu.demo.monitor;
import cn.lingniu.framework.plugin.prometheus.PrometheusCounter;
import cn.lingniu.framework.plugin.prometheus.PrometheusMetrics;
import cn.lingniu.framework.plugin.prometheus.PrometheusSummary;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.Metrics;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* http://localhost:30290/actuator
* 访问 http://localhost:30290/actuator/metrics/metricName 查看指标
*/
@RestController
@RequestMapping("/demo/prometheus")
public class PrometheusController {
/**
*
Counter计数器
Counter 是最简单的指标类型,它是一个单调递增的计数器,只能增加或重置为 0。通常用于记录请求总数、任务完成数、错误数等累计数据 */
@GetMapping("/prometheusCounter")
@PrometheusCounter( labels = {"prometheusCounter","test"}, memo = "prometheusCounter")
public String prometheusCounter() {
return "prometheusCounter";
}
/**
DistributionSummary分布摘要
DistributionSummary 与 Histogram 类似,也用于测量数值的分布情况,但它专门用于跟踪事件的大小或持续时间等非时间性指标
*/
@GetMapping("/prometheusSummary")
@PrometheusSummary(labels = {"prometheusSummary","test"}, memo = "prometheusSummary")
public String prometheusSummary() {
return "prometheusSummary";
}
/**
Histogram直方图
Histogram 用于测量数据的分布情况,如请求延迟、响应大小等。它会统计样本数据的分布情况,并提供分位数计算功能。
*/
@GetMapping("/PrometheusMetrics")
@PrometheusMetrics(name = "prometheusMetrics")
public String prometheusMetrics() {
return "prometheusMetrics";
}
/**
* 自定义埋点
*/
@GetMapping("/selfMonitor")
public String selfMonitor() {
long startTime = System.currentTimeMillis();
Counter counter = Metrics.counter("selfMonitorCount", "selfMonitor", "selfMonitorCount");
counter.increment();
DistributionSummary distributionSummary = Metrics.summary("selfMonitorSummary", "selfMonitor", "selfMonitorSummary");
distributionSummary.record(System.currentTimeMillis() - startTime);
return "selfMonitor";
}
/**
* throw 异常 测试
*/
@GetMapping("/throw")
public String throwEx() {
throw new RuntimeException("test");
}
}

View File

@@ -0,0 +1,88 @@
package cn.lingniu.demo.redisson;
import cn.lingniu.framework.plugin.redisson.RedissonLockAction;
import cn.lingniu.framework.plugin.redisson.RedissonLockType;
import org.springframework.core.annotation.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class LockActionDemo {
@RedissonLockAction(redissonName = "r1", lockType = RedissonLockType.REENTRANT_LOCK,
waitTime = 3000L, leaseTime = 30000L, unit = TimeUnit.MILLISECONDS,
throwException = true)
public void testLockAction(String test) {
}
/**
* 使用 #orderId 参数作为锁的key
*/
@PostMapping("/process/{orderId}")
@RedissonLockAction(
redissonName = "r1",
key = "#orderId",
lockType = RedissonLockType.REENTRANT_LOCK,
waitTime = 3000L, leaseTime = 30000L, unit = TimeUnit.MILLISECONDS,
throwException = true
)
public ResponseEntity<String> processOrder(@PathVariable String orderId) {
// 业务逻辑
return ResponseEntity.ok("Order processed: " + orderId);
}
/**
* 使用请求参数
*/
@GetMapping("/query")
@RedissonLockAction(
redissonName = "defaultRedisson",
key = "'query:' + #userId + ':' + #status",
throwException = true
)
public ResponseEntity<List<Order>> queryOrders(
@RequestParam String userId,
@RequestParam String status) {
// 业务逻辑
return ResponseEntity.ok(new ArrayList<>());
}
/**
* 使用多个参数组合生成key
*/
@PostMapping("/update")
@RedissonLockAction(
redissonName = "defaultRedisson",
key = "'order:' + #orderDTO.orderId + ':user:' + #orderDTO.userId",
waitTime = 5000L
)
public ResponseEntity<String> updateOrder(@RequestBody OrderDTO orderDTO) {
// 业务逻辑
return ResponseEntity.ok("Order updated");
}
public class OrderDTO {
private String orderId;
private String userId;
private String status;
// getters and setters
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }
public String getUserId() { return userId; }
public void setUserId(String userId) { this.userId = userId; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}
}

View File

@@ -0,0 +1,100 @@
package cn.lingniu.demo.redisson;
import cn.lingniu.framework.plugin.redisson.RedissonClientFactory;
import cn.lingniu.framework.plugin.redisson.RedissonClusterLockerService;
import cn.lingniu.framework.plugin.redisson.RedissonLockAction;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* 包含分布式锁和集群操作
*/
@RestController
@RequestMapping("/demo/redisson")
public class RedissonLockControllerDemo {
@Autowired
RedissonClusterLockerService redissonClusterLockerService;
//指定数据源r1
private final RedissonClient redissonClient;
public RedissonLockControllerDemo() {
this.redissonClient = RedissonClientFactory.getRedissonClient("r1");
}
@GetMapping("/lock")
public String acquireLock(
@RequestParam String lockName,
@RequestParam long leaseTime
) {
RLock lock = redissonClient.getLock(lockName);
try {
boolean isLocked = lock.tryLock(5, leaseTime, TimeUnit.SECONDS);
if (isLocked) {
return "锁获取成功";
} else {
return "锁获取失败";
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "锁获取异常";
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
@GetMapping("/bucket/set")
public String setBucketValue(
@RequestParam String key,
@RequestParam String value
) {
RBucket<String> bucket = redissonClient.getBucket(key);
bucket.set(value);
return "键值设置成功";
}
@GetMapping("/bucket/get/{key}")
public String getBucketValue(@PathVariable String key) {
RBucket<String> bucket = redissonClient.getBucket(key);
return "结果:key:" + key + ",value:=" + bucket.get();
}
@GetMapping("/topic/publish")
public String publishMessage( @RequestParam String topicName,
@RequestParam String message
) {
RTopic topic = redissonClient.getTopic(topicName);
topic.publish(message);
return "消息发布成功";
}
@GetMapping("/lockAction")
@RedissonLockAction(redissonName = "r1")
public String redisson() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "lockAction";
}
@GetMapping("/redissonClusterLockerService")
public String redissonClusterLockerService() {
return redissonClusterLockerService.wrapLock(this,
x -> "r1", x -> "key1",
x -> "success");
}
}

View File

@@ -0,0 +1,58 @@
package cn.lingniu.demo.rocketmq;
import cn.lingniu.demo.jetcache.controller.KeyValueEntity;
import cn.lingniu.framework.plugin.rocketmq.core.producer.RocketMqSendMsgBody;
import cn.lingniu.framework.plugin.rocketmq.core.producer.call.SendMessageOnFail;
import cn.lingniu.framework.plugin.rocketmq.core.producer.call.SendMessageOnSuccess;
import org.apache.rocketmq.client.producer.SendResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
@RequestMapping("/demo/rocketmq")
public class RocketMqController {
@Autowired
TestMqProducer testProducer;
@Autowired
TestTransMqProducer testTransProducer;
@GetMapping("/test")
public String test() {
for (int i = 0; i < 10; i++) {
KeyValueEntity body = new KeyValueEntity();
String id = UUID.randomUUID().toString();
body.setId(id);
body.setKey("key" + id);
body.setValue("value" + id);
RocketMqSendMsgBody<KeyValueEntity> message = new RocketMqSendMsgBody<>();
message.setBody(body);
if (i > 5) {
message.setDelayLevel(1);
}
SendResult sendResult = testProducer.syncSend(message);
System.out.println(sendResult);
testProducer.asyncSend(message, new SendMessageOnSuccess<KeyValueEntity>() {
@Override
public void call(KeyValueEntity message, SendResult result) {
System.out.println(result);
}
}, new SendMessageOnFail<KeyValueEntity>() {
@Override
public void call(KeyValueEntity message, Throwable ex) {
System.out.println(ex);
}
});
testTransProducer.syncSendInTransaction(message, null);
}
return "over";
}
}

View File

@@ -0,0 +1,21 @@
package cn.lingniu.demo.rocketmq;
import cn.lingniu.demo.jetcache.controller.KeyValueEntity;
import cn.lingniu.framework.plugin.rocketmq.RocketMqConsumer;
import cn.lingniu.framework.plugin.rocketmq.core.consumer.listener.RocketMqListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
/**
* 消费测试
*/
@Slf4j
@RocketMqConsumer("consumer1")
public class TestC1Consumer implements RocketMqListener<KeyValueEntity> {
@Override
public void onMessage(KeyValueEntity message, MessageExt messageExt) {
log.info("message{}", message);
log.info("messageExt{}", messageExt);
}
}

View File

@@ -0,0 +1,12 @@
package cn.lingniu.demo.rocketmq;
import cn.lingniu.demo.jetcache.controller.KeyValueEntity;
import cn.lingniu.framework.plugin.rocketmq.RocketMqProducer;
import org.springframework.stereotype.Component;
/**
* 普通生产者
*/
@Component
public class TestMqProducer extends RocketMqProducer<KeyValueEntity> {
}

View File

@@ -0,0 +1,49 @@
package cn.lingniu.demo.rocketmq;
import cn.lingniu.demo.jetcache.controller.KeyValueEntity;
import cn.lingniu.framework.plugin.rocketmq.RocketMqProducer;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 事物消息
*/
@Component
public class TestTransMqProducer extends RocketMqProducer<KeyValueEntity> implements TransactionListener {
private AtomicInteger transactionIndex = new AtomicInteger(0);
private ConcurrentHashMap<String, Integer> localTrans = new ConcurrentHashMap<>();
@Override
public LocalTransactionState executeLocalTransaction(Message message, Object o) {
int value = transactionIndex.getAndIncrement();
int status = value % 3;
localTrans.put(message.getTransactionId(), status);
return LocalTransactionState.UNKNOW;
}
@Override
public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
Integer status = localTrans.get(messageExt.getTransactionId());
if (null != status) {
switch (status) {
case 0 :
return LocalTransactionState.UNKNOW;
case 1 :
return LocalTransactionState.COMMIT_MESSAGE;
case 2 :
return LocalTransactionState.ROLLBACK_MESSAGE;
default:
return LocalTransactionState.COMMIT_MESSAGE;
}
}
return LocalTransactionState.COMMIT_MESSAGE;
}
}

View File

@@ -0,0 +1,55 @@
package cn.lingniu.demo.web;
import cn.lingniu.framework.plugin.core.base.CommonResult;
import cn.lingniu.framework.plugin.web.apilog.ApiAccessLog;
import org.checkerframework.checker.units.qual.A;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/demo/web")
public class WebController {
@GetMapping("/errorResult")
public WebEntity testRrrorResult() {
WebEntity webEntity = new WebEntity();
webEntity.setId(1L);
webEntity.setName("error");
webEntity.setEmail("<EMAIL>");
return webEntity;
}
@GetMapping("/commonResult")
public CommonResult<WebEntity> test() {
WebEntity webEntity = new WebEntity();
webEntity.setId(1L);
webEntity.setName("lingniu");
webEntity.setEmail("<EMAIL>");
return CommonResult.success(webEntity);
}
@ApiAccessLog(responseEnable = true)
@GetMapping("/apiLog")
public CommonResult<WebEntity> apiLog() {
WebEntity webEntity = new WebEntity();
webEntity.setId(1L);
webEntity.setName("lingniu");
webEntity.setEmail("<EMAIL>");
return CommonResult.success(webEntity);
}
@ApiAccessLog(responseEnable = true)
@GetMapping("/apiEncrypt")
public CommonResult<WebEntity> apiEncrypt() {
WebEntity webEntity = new WebEntity();
webEntity.setId(1L);
webEntity.setName("lingniu");
webEntity.setEmail("<EMAIL>");
return CommonResult.success(webEntity);
}
}

View File

@@ -0,0 +1,10 @@
package cn.lingniu.demo.web;
import lombok.Data;
@Data
public class WebEntity {
private Long id;
private String name;
private String email;
}

View File

@@ -0,0 +1,12 @@
framework:
lingniu:
# 框架数据源配置
datasource:
# 开启框架 sql执行分析
# dev,local,lpt,fat,test,uat,sit 这些环境可开启
sqlLog: true
# druid 后台地址http://localhost:8080/druid/login.html
# druid 账号,默认值为 SpringApplicationProperties#name
druidUsername: "your_druid_username"
# druid 密码,默认值为 SpringApplicationProperties#name + "123"
druidPassword: "your_druid_password"

View File

@@ -0,0 +1,58 @@
framework:
lingniu:
jetcache:
# 需要隐藏的包路径(数组),默认为空
hiddenPackages: [ ]
# 统计信息输出间隔(分钟),默认为 0不输出
statIntervalMinutes: 10
# 是否在缓存名称中包含区域area信息默认为 true
areaInCacheName: true
# 是否开启缓存穿透保护,默认为 false
penetrationProtect: false
# 本地缓存配置
local:
# cache area 配置, 使用CacheManager或@Cache注解时 默认area为default
ca2:
# 本地缓存实现类类型支持linkedhashmap/caffeine
type: linkedhashmap
# 缓存key数量限制, 默认100
limit: 100
default:
# 本地缓存实现类类型支持linkedhashmap/caffeine
type: caffeine
# 缓存key数量限制, 默认100
limit: 100
# 过期时间0为不失效
expireAfterAccessInMillis: 0
# key 转换器用于序列化目前支持NONE、FASTJSON、JACKSON、FASTJSON2
keyConvertor: FASTJSON2
remote:
# cache area 配置, 使用CacheManager或@Cache注解时 默认area为default
ca2:
# 远程缓存实现类类型目前支持redisson
type: redisson
# 远程缓存客户端名称默认r1 -- todo 需要在application-redisson.yml中配置
redissonClient: r1
# key 前缀
keyPrefix: "cacheKeyPrefix:"
# 连接超时时间ms
timeout: 2000
# 重试次数
maxAttempt: 5
# 连接池配置
poolConfig:
maxTotal: 8
maxIdle: 8
minIdle: 0
# key 转换器用于序列化目前支持NONE、FASTJSON、JACKSON、FASTJSON2
keyConvertor: FASTJSON2
# JAVA KRYOKRYO5自定义spring beanName
valueEncoder: JAVA
# JAVA KRYOKRYO5自定义spring beanName
valueDecoder: JAVA
# cache area 配置, 使用CacheManager或@Cache注解时 默认area为default
default:
# 远程缓存实现类类型目前支持redisson
type: redisson
# 远程缓存客户端名称默认r1 -- todo 需要在application-redisson.yml中配置
redissonClient: r1

View File

@@ -0,0 +1,6 @@
framework:
lingniu:
prometheus:
enabled: true
port: 30290
allowAssignPort: false

View File

@@ -0,0 +1,44 @@
framework:
lingniu:
redisson:
remote:
r1:
# 应用id需在cachecloud申请
redisAddresses: 10.130.36.242:6387
# 客户端名称,默认为应用名 + IP
clientName: ""
# 单节点 Redis 默认数据库,默认为 0
database: 0
# 连接池最小空闲连接数,默认为 12
connectionMinimumIdleSize: 12
# 连接池最大连接数,默认为 32
connectionPoolSize: 32
# 空闲连接超时时间(毫秒),默认为 10000
idleConnectionTimeout: 10000
# 连接超时时间(毫秒),默认为 2000
connectTimeout: 2000
# 操作超时时间(毫秒),默认为 2000
timeout: 2000
# 操作重试次数,默认为 4
retryAttempts: 4
# 集群模式下是否检查 Slots 覆盖,默认为 true
checkSlotsCoverage: true
# 读取模式,默认为 "SLAVE"
# 可选值:
# - SLAVE: 从节点读取
# - MASTER: 主节点读取
# - MASTER_SLAVE: 主从节点读取
readMode: "SLAVE"
# 存储类型,默认为 "CLUSTER"
# 可选值:
# - CLUSTER: 集群模式
# - SINGLE: 单节点模式
# - SENTINEL: 哨兵模式
# - REPLICATED: 复制模式
storageType: "CLUSTER"
# 实例名称
r2:
# 应用id需在cachecloud申请
redisAddresses: 10.130.36.242:6387
# 单节点 Redis 默认数据库,默认为 0
database: 0

View File

@@ -0,0 +1,64 @@
framework:
lingniu:
# rocketmq所有配置示例
rocketmq:
# 是否开启数据源加密
encryptEnabled: false
# 消费者配置
consumers:
# 消费者bean名称
TestC1Consumer:
nameServer: mq_test_n1.tst.mid:9876
# 消费组
consumerGroup: consumer1
# 消费对象名字
consumerBeanName: TestC1Consumer
# Topic
topic: test1-yw-topic
# 订阅表达式,默认为 *
selectorExpress: "*"
# 消费者最小线程数
consumeThreadMin: 20
# 消费者最大线程数
consumeThreadMax: 32
# 批量消费数量
consumeMessageBatchMaxSize: 1
# 批量拉取消息数量
pullBatchSize: 32
# 消息的最大重试次数
maxRetryTimes: 16
# 生产者配置
producers:
# 生产者的bean名称
TestMqProducer:
nameServer: mq_test_n1.tst.mid:9876
# 生产者组
group: test1-yw-topic-producer
# 生产端Topic
topic: test1-yw-topic
# 发送超时ms默认 3000
sendMsgTimeout: 3000
# 消息体压缩阀值kb默认 4096
compressMsgBodyOverHowmuch: 4096
# 同步发送消息失败,是否重新发送,默认 2
retryTimesWhenSendFailed: 2
# 异步发送消息失败,是否重新发送,默认 2
retryTimesWhenSendAsyncFailed: 2
# 重试另一个Broker当发送消息失败, 默认 false
retryAnotherBrokerWhenNotStoreOk: false
# 默认不启用延迟容错通过统计每个队列的发送耗时情况来计算broker是否可用
sendLatencyFaultEnable: false
TestTransMqProducer:
group: test1-yw-trans-topic-producer
topic: test1-yw-trans-topic
# 是否事务型
isTransactionMQ: true
# 事务消息线程配置
transaction:
corePoolSize: 5
# 本地事务执行结果查询线程池配置
maximumPoolSize: 10
keepAliveTime: 200
queueCapacity: 2000

View File

@@ -0,0 +1,12 @@
framework:
lingniu:
web:
apiLog:
#开关
enable: true
apiEncrypt:
#开关
enable: false
algorithm: "AES"
requestKey: "xxx"
responseKey: "xxx"

View File

@@ -0,0 +1,21 @@
framework:
lingniu:
# XXL-JOB 配置
xxljob:
# 调度中心配置
admin:
# 调度中心部署根地址(多个地址用逗号分隔,为空则关闭自动注册)
adminAddresses: "http://10.130.119.181:8099/xxl-job-admin"
# 调度中心通讯TOKEN非空时启用
accessToken: "default_token"
# 执行器配置
executor:
# 执行器IP默认为空表示自动获取IP
ip: ""
# 执行器端口号小于等于0则自动获取默认9999
port: 9999
# 执行器日志文件保存天数大于等于3时生效-1表示关闭自动清理默认7天
logRetentionDays: 7
# 执行器运行日志文件存储磁盘路径(需对该路径拥有读写权限,为空则使用默认路径)
logPath: logs/applogs/xxl-job/jobhandler

View File

@@ -0,0 +1,48 @@
spring:
application:
name: lingniu-framework-demo
profiles:
active: dev,redisson,jetcache,xxljob,db,rocketmq,prometheus,web
cloud:
nacos:
enabled: true #开启微服务自定义注册自动获取当前框架信息启动时间等到metadata中
discovery:
server-addr: http://nacos-uat-new-inter.xx.net.cn:8848 #注册中心地址
username: nacos_test #注册中心用户名
password: nacos_test #注册中心密码
#todo db基本配置连接池请参考https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
datasource:
dynamic:
primary: master
datasource:
#如需连接mysql需修改下面的配置
master:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
password: sa
slaver:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:testdb
username: sa
password: sa
# http://localhost:8080/h2-console 访问 h2 数据库 账号: sa/sa
h2:
console:
enabled: true
path: /h2-console
# apollo 配置
framework:
lingniu:
apollo:
#namespaces必须配置配置文件列表以逗号分割
namespaces: application,applicationTest
# 是否开启 Apollo 配置默认true
enabled: true
# appId 等于 spring.application.name无需配置
appId: lingniu-framework-demo
# meta 地址,框架自动获取,无需配置
meta: http://10.130.36.237:8180

View File

@@ -0,0 +1,22 @@
apollo:
demo:
string-demo: "示例字符串"
boolean-demo: true
list-demo:
- "元素1"
- "元素2"
- "元素3"
set-demo:
- "集合元素1"
- "集合元素2"
hash-demo:
key1: "值1"
key2: "值2"
key3: "值3"
hash-object-demo:
obj1:
test-objcet: "对象示例1"
obj2:
test-objcet: "对象示例2"
object-demo:
test-objcet: "对象示例"

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL如果设置为WARN则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<!-- name的值是变量的名称value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后可以使“${}”来使用变量。 -->
<!-- <property name="log.path" value="/opt/application/config/logs"/>-->
<property name="log.path" value="/Users/likobe/logs/"/>
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<append>true</append>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/log-%d{yyyy-MM-dd-HH}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>30MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>7</maxHistory>
</rollingPolicy>
</appender>
<logger name="org.mybatis" level="debug"/>
<springProfile name="dev">
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="test">
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="pro">
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
</configuration>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>lingniu-framework-provider-demo</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-web</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-microservice-common</artifactId>
</dependency>
<dependency>
<groupId>cn.lingniu.framework</groupId>
<artifactId>lingniu-framework-plugin-microservice-nacos</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,13 @@
package cn.lingniu.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = {"cn.lingniu.*"})
@SpringBootApplication
public class ProviderDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderDemoApplication.class, args);
}
}

View File

@@ -0,0 +1,11 @@
package cn.lingniu.demo.web;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Contributor {
String login;
int contributions;
}

View File

@@ -0,0 +1,23 @@
package cn.lingniu.demo.web;
import cn.lingniu.framework.plugin.core.base.CommonResult;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping
public class GithubApiController {
@GetMapping("/repos/{owner}/{repo}/contributors")
public CommonResult<List<Contributor>> contributors(@PathVariable("owner") String owner, @PathVariable("repo") String repo) {
// 模拟返回贡献者列表
Contributor contributor1 = new Contributor("user1", 10);
Contributor contributor2 = new Contributor("user2", 5);
List<Contributor> response = new ArrayList<>();
response.add(contributor1);
response.add(contributor2);
return CommonResult.success(response);
}
}

View File

@@ -0,0 +1,9 @@
framework:
lingniu:
web:
apiLog:
#开关
enable: true
spring:
cloud:
isOkHttp: false

View File

@@ -0,0 +1,15 @@
server:
port: 8081
spring:
application:
name: lingniu-framework-provider-demo
profiles:
active: dev,web
cloud:
nacos:
enabled: true #开启微服务自定义注册自动获取当前框架信息启动时间等到metadata中
discovery:
server-addr: http://nacos-uat-new-inter.xx.net.cn:8848 #注册中心地址
username: nacos_test #注册中心用户名
password: nacos_test #注册中心密码

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL如果设置为WARN则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时配置文件如果发生改变将会被重新加载默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔如果没有给出时间单位默认单位是毫秒。当scan为true时此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时将打印出logback内部日志信息实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logback</contextName>
<!-- name的值是变量的名称value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后可以使“${}”来使用变量。 -->
<!-- <property name="log.path" value="/opt/application/config/logs"/>-->
<property name="log.path" value="/Users/likobe/logs/"/>
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<append>true</append>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/log-%d{yyyy-MM-dd-HH}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>30MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>7</maxHistory>
</rollingPolicy>
</appender>
<logger name="org.mybatis" level="debug"/>
<springProfile name="dev">
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="test">
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
<springProfile name="pro">
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
</configuration>