commit 3fc61eb9d89a3a58eed2b70a7be2f86955f19c3c Author: lijiayao <13831655+xiao-yao-charge-forward@user.noreply.gitee.com> Date: Sun Mar 24 16:53:55 2024 +0800 初始化 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f01ff37 --- /dev/null +++ b/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + com.example + demo + 0.0.1-SNAPSHOT + demo + Demo project for Spring Boot + + 11 + UTF-8 + UTF-8 + 2.3.12.RELEASE + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + javax.servlet + javax.servlet-api + 3.1.0 + + + org.springframework.cloud + spring-cloud-starter-bootstrap + 3.1.7 + + + + org.projectlombok + lombok + 1.18.22 + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.5 + + + + org.bouncycastle + bcpkix-jdk15on + 1.70 + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + 11 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + com.example.DemoApplication + true + + + + repackage + + repackage + + + + + + + + diff --git a/src/main/java/com/example/DemoApplication.java b/src/main/java/com/example/DemoApplication.java new file mode 100644 index 0000000..909a1ec --- /dev/null +++ b/src/main/java/com/example/DemoApplication.java @@ -0,0 +1,13 @@ +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + +} diff --git a/src/main/java/com/example/demos/web/BasicController.java b/src/main/java/com/example/demos/web/BasicController.java new file mode 100644 index 0000000..7a927b8 --- /dev/null +++ b/src/main/java/com/example/demos/web/BasicController.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.demos.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * @author theonefx + */ +@Controller +public class BasicController { + + // http://127.0.0.1:8080/hello?name=lisi + @RequestMapping("/hello") + @ResponseBody + public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) { + return "Hello " + name; + } + + // http://127.0.0.1:8080/user + @RequestMapping("/user") + @ResponseBody + public User user() { + User user = new User(); + user.setName("theonefx"); + user.setAge(666); + return user; + } + + // http://127.0.0.1:8080/save_user?name=newName&age=11 + @RequestMapping("/save_user") + @ResponseBody + public String saveUser(User u) { + return "user will save: name=" + u.getName() + ", age=" + u.getAge(); + } + + // http://127.0.0.1:8080/html + @RequestMapping("/html") + public String html(){ + return "index.html"; + } + + @ModelAttribute + public void parseUser(@RequestParam(name = "name", defaultValue = "unknown user") String name + , @RequestParam(name = "age", defaultValue = "12") Integer age, User user) { + user.setName("zhangsan"); + user.setAge(18); + } +} diff --git a/src/main/java/com/example/demos/web/MQTT/PublishSample.java b/src/main/java/com/example/demos/web/MQTT/PublishSample.java new file mode 100644 index 0000000..91171c2 --- /dev/null +++ b/src/main/java/com/example/demos/web/MQTT/PublishSample.java @@ -0,0 +1,47 @@ +package com.example.demos.web.MQTT; + +import lombok.extern.log4j.Log4j2; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; + +/** + * @Author: LiJiaYao + * @Date: 2024/3/20 + */ +@Log4j2 +public class PublishSample { + public static void main(String[] args) throws Exception { + String broker = "tcp://broker.emqx.io:1883"; + String topic = "mqtt/test"; + String username = "emqx"; + String password = "public"; + String clientid = "publish_client"; + String content = "Hello MQTT"; + int qos = 0; + + MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); + + //连接参数 + MqttConnectOptions options = new MqttConnectOptions(); + //设置用户名和密码 + options.setUserName(username); + options.setPassword(password.toCharArray()); + options.setConnectionTimeout(60); + options.setKeepAliveInterval(60); + + //连接 + client.connect(options); + //创建消息并设置Qos + MqttMessage message = new MqttMessage(content.getBytes()); + message.setQos(qos); + client.publish(topic,message); + log.info("Message published"); + System.out.println("topic "+topic); + System.out.println("message content "+content); + client.disconnect(); + client.close(); + } +} diff --git a/src/main/java/com/example/demos/web/MQTT/SSLUtils.java b/src/main/java/com/example/demos/web/MQTT/SSLUtils.java new file mode 100644 index 0000000..7ee18f6 --- /dev/null +++ b/src/main/java/com/example/demos/web/MQTT/SSLUtils.java @@ -0,0 +1,74 @@ +package com.example.demos.web.MQTT; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import java.io.*; +import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * @Author: LiJiaYao + * @Date: 2024/3/20 + */ +public class SSLUtils { + + public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile) throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException { + + String broker = "tcp://broker.emqx.io:1883"; + // TLS/SSL +// String broker = "ssl://broker.emqx.io:8883"; + String username = "emqx"; + String password = "public"; + String clientid = "publish_client"; + + Security.addProvider(new BouncyCastleProvider()); + //load CA certificate + + X509Certificate caCert = null; + FileInputStream fis = new FileInputStream(crtFile); + BufferedInputStream bis = new BufferedInputStream(fis); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + while (bis.available() > 0) { + caCert = (X509Certificate) cf.generateCertificate(bis); + } + bis = new BufferedInputStream(new FileInputStream(crtFile)); + X509Certificate cert = null; + while (bis.available() > 0) { + cert = (X509Certificate) cf.generateCertificate(bis); + } + + PEMParser pemParser = new PEMParser(new FileReader(keyFile)); + Object object = pemParser.readObject(); + JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); + KeyPair keyPair = converter.getKeyPair((PEMKeyPair) object); + pemParser.close(); + + KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); + + caKs.load(null, null); + caKs.setCertificateEntry("ca-certificate", caCert); + TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); + tmf.init(caKs); + + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null, null); + ks.setCertificateEntry("certificate", cert); + ks.setKeyEntry("private-key", keyPair.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert}); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password.toCharArray()); + SSLContext context = SSLContext.getInstance("TLSv1.2"); + context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + return context.getSocketFactory(); + } + +} diff --git a/src/main/java/com/example/demos/web/MQTT/SubscribeSample.java b/src/main/java/com/example/demos/web/MQTT/SubscribeSample.java new file mode 100644 index 0000000..9bdcf20 --- /dev/null +++ b/src/main/java/com/example/demos/web/MQTT/SubscribeSample.java @@ -0,0 +1,51 @@ +package com.example.demos.web.MQTT; + +import org.eclipse.paho.client.mqttv3.*; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; + +public class SubscribeSample { + public static void main(String[] args) { + String broker = "tcp://broker.emqx.io:1883"; + String topic = "mqtt/test"; + String username = "emqx"; + String password = "public"; + String clientid = "subscribe_client"; + int qos = 0; + + try { + MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); + // 连接参数 + MqttConnectOptions options = new MqttConnectOptions(); + options.setUserName(username); + options.setPassword(password.toCharArray()); + options.setConnectionTimeout(60); + options.setKeepAliveInterval(60); + // 设置回调 + client.setCallback(new MqttCallback() { + + @Override + public void connectionLost(Throwable cause) { + System.out.println("connectionLost: " + cause.getMessage()); + } + + @Override + public void messageArrived(String topic, MqttMessage message) { + System.out.println("topic: " + topic); + System.out.println("Qos: " + message.getQos()); + System.out.println("message content: " + new String(message.getPayload())); + + } + + @Override + public void deliveryComplete(IMqttDeliveryToken token) { + System.out.println("deliveryComplete---------" + token.isComplete()); + } + + }); + client.connect(options); + client.subscribe(topic, qos); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/example/demos/web/PathVariableController.java b/src/main/java/com/example/demos/web/PathVariableController.java new file mode 100644 index 0000000..09cf9f7 --- /dev/null +++ b/src/main/java/com/example/demos/web/PathVariableController.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.demos.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * @author theonefx + */ +@Controller +public class PathVariableController { + + // http://127.0.0.1:8080/user/123/roles/222 + @RequestMapping(value = "/user/{userId}/roles/{roleId}", method = RequestMethod.GET) + @ResponseBody + public String getLogin(@PathVariable("userId") String userId, @PathVariable("roleId") String roleId) { + return "User Id : " + userId + " Role Id : " + roleId; + } + + // http://127.0.0.1:8080/javabeat/somewords + @RequestMapping(value = "/javabeat/{regexp1:[a-z-]+}", method = RequestMethod.GET) + @ResponseBody + public String getRegExp(@PathVariable("regexp1") String regexp1) { + return "URI Part : " + regexp1; + } +} diff --git a/src/main/java/com/example/demos/web/Service.java b/src/main/java/com/example/demos/web/Service.java new file mode 100644 index 0000000..7b425fc --- /dev/null +++ b/src/main/java/com/example/demos/web/Service.java @@ -0,0 +1,78 @@ +package com.example.demos.web; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; + +/** + * @author DongXiaoDong + * @version 1.0 + * @date 2024/3/20 9:47 + * @description + */ +public class Service { + /** + * 线程池优化 + */ + private final ExecutorService executorService; + + /** + * 构造函数,初始化线程池 + */ + public Service() { + this.executorService = Executors.newFixedThreadPool(1); + } + + /** + * 优化后的线程池 + * @param userIds + * @return + */ + public Map get(List userIds) { + Map resultMap = new ConcurrentHashMap<>(); + List> batches = splitIntoBatches(userIds, 1000); + + + List>> tasks = new ArrayList<>(); + for (List batch : batches) { + tasks.add(() -> UserService.getUserMap(batch)); + } + + try { + List>> futures = executorService.invokeAll(tasks); + + for (Future> future : futures) { + resultMap.putAll(future.get()); + } + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + executorService.shutdown(); + + return resultMap; + } + + /** + * 分割成小批次 + * @param userList + * @param batchSize + * @return + */ + private List> splitIntoBatches(List userList, int batchSize) { + List> batches = new ArrayList<>(); + int size = userList.size(); + + for (int i = 0; i < size; i += batchSize) { + if (i + batchSize > size) { + batches.add(userList.subList(i, size)); + } else { + batches.add(userList.subList(i, i + batchSize)); + } + } + + return batches; + } +} diff --git a/src/main/java/com/example/demos/web/Test.java b/src/main/java/com/example/demos/web/Test.java new file mode 100644 index 0000000..06d1147 --- /dev/null +++ b/src/main/java/com/example/demos/web/Test.java @@ -0,0 +1,44 @@ +package com.example.demos.web; + +import lombok.extern.log4j.Log4j2; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author DongXiaoDong + * @version 1.0 + * @date 2024/3/20 10:05 + * @description + */ +@Slf4j +public class Test { + /** + * 测试 + * @param args + */ + public static void main(String[] args) { + Service service = new Service(); + List userIds = generateUserIds(); + long start = System.currentTimeMillis(); + Map stringMap = service.get(userIds); + long end = System.currentTimeMillis(); + long l=end - start; + log.info("耗时:" + (end-start) +"ms"); + log.info("结果:" + stringMap); + } + + /** + * 生成1000用户id + * @return + */ + private static List generateUserIds() { + List userIds = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + userIds.add((long) i); + } + return userIds; + } +} diff --git a/src/main/java/com/example/demos/web/User.java b/src/main/java/com/example/demos/web/User.java new file mode 100644 index 0000000..09c23e2 --- /dev/null +++ b/src/main/java/com/example/demos/web/User.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.demos.web; + +/** + * @author theonefx + */ +public class User { + + private String name; + + private Integer age; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } +} diff --git a/src/main/java/com/example/demos/web/UserService.java b/src/main/java/com/example/demos/web/UserService.java new file mode 100644 index 0000000..203ff67 --- /dev/null +++ b/src/main/java/com/example/demos/web/UserService.java @@ -0,0 +1,44 @@ +package com.example.demos.web; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author DongXiaoDong + * @version 1.0 + * @date 2024/3/20 9:55 + * @description + */ +public class UserService { + /** + * 通过userId获取用户信息 + * @param userIds + * @return + */ + public static Map getUserMap(List userIds) { + //模拟耗时100ms请求 + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + Map userMap = new ConcurrentHashMap<>(); + for (Long userId : userIds) { + String userInfo = getUserInfo(userId); + userMap.put(userId, userInfo); + } + return userMap; + } + + /** + * 模拟获取用户信息 + * @param userId + * @return + */ + private static String getUserInfo(Long userId) { + return "User" + userId; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..e52b498 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,3 @@ +# 应用服务 WEB 访问端口 +server.port=8080 + diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html new file mode 100644 index 0000000..e2d94a2 --- /dev/null +++ b/src/main/resources/static/index.html @@ -0,0 +1,6 @@ + + +

hello word!!!

+

this is a html page

+ + \ No newline at end of file diff --git a/src/test/java/com/example/DemoApplicationTests.java b/src/test/java/com/example/DemoApplicationTests.java new file mode 100644 index 0000000..c900efb --- /dev/null +++ b/src/test/java/com/example/DemoApplicationTests.java @@ -0,0 +1,13 @@ +package com.example; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoApplicationTests { + + @Test + void contextLoads() { + } + +}