目录
Java
java保留两位小数
1、使用String.format()方法:
public static void stringFormatdecimalFormatKeepTwoDecimalPlaces(){
double number = 3.1415926;
String result = String.format("%.2f", number);
System.out.println(result);
}
输出:3.14
2、BigDecimal保留两位小数
import java.math.BigDecimal;
public static void bigdecimalKeepTwoDecimalPlaces(){
double number = 3.1415926;
BigDecimal decimal = new BigDecimal(number);
BigDecimal rounded = decimal.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println(rounded);
}
输出:3.14
3、使用DecimalFormat类:
public static void decimalFormatKeepTwoDecimalPlaces(){
double number = 3.1415926;
DecimalFormat decimalFormat = new DecimalFormat("#.00");
String result = decimalFormat.format(number);
System.out.println(result);
}
输出:3.14
基本数据类型
/**
* 基本数据类型,在定义的时候根据不同的类型在内存中分配不同的大小进行存储。
*
*
* 整数:
* byte(1字节byte=8位)
* 1000 0000 ~ 01111111 最高位是符号位0表示正 1表示负
* byte值的范围:-128 ~ 127
*
*
* short(2字节) -32768~32767
*
* \ int(4字节) -2,147,483,648 ~ 21 4748 3647(21亿多)
*
* \ long(8字节)
*
* 浮点型:
* float(4字节) 定义float类型变量时,变量要以"f"或"F"结尾
* 单精度浮点数 提供大约6-7位的有效数字。
*
* \ double(8字节)
* 双精度浮点数 提供大约15-16位的有效数字。
* 推荐使用double,因为现代计算机硬件通常更擅长处理双精度浮点数。
*
* 简单来说double精度更高,可以表示更细的浮点数,通俗的讲就是小数点后面可以表示更多的数字。
*
* 布尔型:
* boolean(1字节)
*
* 字符型:
* char(2字节)
*
*
*/
/**
* 运算
*
* 整数除法运算,结果是取整
* 浮点数除整数 结果为 浮点数
* 整数 除 浮点数 结果为 浮点数
*
* 文件大小 23435.12 MB
*
* 速率 = 文件大小 / 用时
* 用时
*/
@Test
public void test3(){
int fileSizeB = 46960880; // 44.7 MB
int fileSizeMB = fileSizeB / 1024 / 1024;
System.out.println(fileSizeMB);// 44 整数除整数结果也是取整
double fileSizeMB1 = fileSizeB / 1024 / 1024;
System.out.println(fileSizeMB1); // 44.0 只是将整数赋值给了一个浮点数double
double fileSizeB1 = 46960880;
double fileSizeMB2 = fileSizeB1 / 1024 / 1024;
System.out.println(fileSizeMB2);// 44.78538513183594 浮点数除整数 结果为 浮点数
// 结果保留一位小数
System.out.println(String.format("%.1f", fileSizeMB2));// 44.8 会自动四舍五入
DecimalFormat decimalFormat = new DecimalFormat("#.0");
System.out.println(decimalFormat.format(fileSizeMB2));// 44.8 会自动四舍五入
// 向下截断小数部分
System.out.println(Math.floor(fileSizeMB2));// 44.0
// 向上截断小数部分
System.out.println(Math.ceil(fileSizeMB2));// 45.0
// 保留一位小数,不进行四舍五入
System.out.println((int) (fileSizeMB2 * 10));
double truncatedNumber = (int) (fileSizeMB2 * 10) / 10.0; // 整数 除 浮点数 结果为 浮点数
System.out.println(truncatedNumber);// 44.7
int mil = 23435; // 毫秒
double second = mil / 1000.0;
System.out.println(second);
double speed = (int)((fileSizeMB2 / second) * 10) / 10.0;
System.out.println(speed + " MB/S");// 1.9 MB/S
}
分页查询
https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
yml配置
pagehelper:
helperDialect: mysql或者oracle
supportMethodsArguments: true
params: count=countSql
helperDialect: mysql
:指定了数据库方言为 MySQL。supportMethodsArguments: true
:开启了支持方法参数,允许在方法中传递参数进行分页。params: count=countSql
:通过传递count
参数来执行 countSql,这通常是用于执行查询总记录数的 SQL。
// 分页
if(highSearchVO.getPageNo() != null) PageHelper.startPage(highSearchVO.getPageNo(),highSearchVO.getPageSize());
List<Map<String, Object>> maps = dynamicDataRetrievalMapper.highSearch(highSearchVO);
在需要分页查询之前调用PageHelper.startPage设置,会自动limit
websocket实时通信
业务中,客户端和服务端经常需要实时返回一些状态等消息,现总结一下websocket实时通信用法。
服务端
服务端一般用来接收客户端的ws连接,然后给客户端发送消息,不能主动发送连接。
<!--ws-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 开启WebSocket
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
package com.lin.ws;
/**
*
*/
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lin.entity.vo.UploadMsgVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;
import javax.swing.Timer;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@Component
@ServerEndpoint("/webSocket/{topic}")
@Slf4j
public class WebSocketServer {
private Session session;
private String topic;
/**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
private static int onlineCount = 0;
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
private static List<UploadMsgVO> uploadMsgList = new ArrayList<>(3);
private javax.swing.Timer timer = new Timer(3000, e -> {
sendMessage(JSONObject.toJSONString(uploadMsgList),"upload");
uploadMsgList.clear();
});
/**
* concurrent包的线程安全set,用来存放每个客户端对应的MyWebSocket对象
*/
private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap();
/**
* 保存ws会话
* 为了保存在线用户信息,在方法中新建一个list存储一下【实际项目依据复杂度,可以存储到数据库或者缓存】
*/
private final static List<Session> SESSIONS = Collections.synchronizedList(new ArrayList<>());
/**
* 建立连接
* ws://192.168.31.47:9988/webSocket/{topic}
* 当客户端发送: ws://192.168.31.47:9988/webSocket/upload ws请求,就可以和这个ws服务端建立ws连接了。
*
* @param session ws连接会话
* @param topic ws连接主题
*/
@OnOpen
public void onOpen(Session session, @PathParam("topic") String topic) {
this.session = session;
this.topic = topic;
webSocketSet.add(this);
SESSIONS.add(session);
if (webSocketMap.containsKey(topic)) {
webSocketMap.remove(topic);
webSocketMap.put(topic,this);
} else {
webSocketMap.put(topic,this);
addOnlineCount();
}
if("upload".equals(topic)) timer.start();
// log.info("【websocket消息】有新的连接, 总数:{}", webSocketSet.size());
log.info("[连接topic:{}] 建立连接, 当前连接数:{}", this.topic, webSocketMap.size());
System.out.println(this);
}
/**
* 断开连接
*/
@OnClose
public void onClose() {
webSocketSet.remove(this);
if (webSocketMap.containsKey(topic)) {
webSocketMap.remove(topic);
subOnlineCount();
}
if("upload".equals(topic)) timer.stop();
// log.info("【websocket消息】连接断开, 总数:{}", webSocketSet.size());
log.info("[连接topic:{}] 断开连接, 当前连接数:{}", topic, webSocketMap.size());
}
/**
* 发送错误
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.info("[连接topic:{}] 错误原因:{}", this.topic, error.getMessage());
error.printStackTrace();
}
/**
* 收到消息
* @param message
*/
@OnMessage
public void onMessage(String message) {
// log.info("【websocket消息】收到客户端发来的消息:{}", message);
log.info("[连接topic:{}] 收到消息:{}", this.topic, message);
UploadMsgVO uploadMsgVO = null;
try {
uploadMsgVO = JSON.parseObject(message, UploadMsgVO.class);
} catch (Exception e) {
e.printStackTrace();
}
if (uploadMsgVO != null) {
int index = uploadMsgList.indexOf(uploadMsgVO);
if(index == -1) uploadMsgList.add(uploadMsgVO);
else uploadMsgList.set(index,uploadMsgVO);
}
// sendMessage(uploadMsgList.toString(),"upload");
}
/**
* 发送消息
* @param message 消息
* @param topic 接收消息的主题(只要订阅这个主题都会收到消息)
*/
public void sendMessage(String message,String topic) {
WebSocketServer webSocketServer = webSocketMap.get(topic);
if (webSocketServer!=null){
log.info("【websocket消息】推送消息, message={}", message);
try {
webSocketServer.session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
log.error("[连接topic:{}] 发送消息失败, 消息:{}", this.topic, message, e);
}
}
}
/**
* 发送object消息
* @param message
* @param topic
*/
public void sendObjectMessage(Object message,String topic) {
WebSocketServer webSocketServer = webSocketMap.get(topic);
if (webSocketServer!=null){
log.info("【websocket消息】推送消息, message={}", message);
try {
webSocketServer.session.getBasicRemote().sendObject(message);
} catch (Exception e) {
e.printStackTrace();
log.error("[连接topic:{}] 发送消息失败, 消息:{}", this.topic, message, e);
}
}
}
/**
* 群发消息
* @param message
*/
public void sendMassMessage(String message) {
try {
for (Session session : SESSIONS) {
if (session.isOpen()) {
session.getBasicRemote().sendText(message);
log.info("[连接topic:{}] 发送消息:{}",session.getRequestParameterMap().get("topic"),message);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取当前连接数
* @return
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 当前连接数加一
*/
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
/**
* 当前连接数减一
*/
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
Java客户端
有个需求需要Java发送ws连接,将业务处理后的消息都汇总到ws服务端,由ws服务端汇总处理发送给客户端。
<!--websocket作为客户端-->
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.5</version>
</dependency>
Java客户端代码
package com.example.web.socket;
import com.example.config.MyConfig;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
@Component
@Slf4j
public class MyWebSocketClient {
@Autowired
private MyConfig myConfig;
@Bean
public WebSocketClient webSocketClient() throws URISyntaxException, UnknownHostException {
String IP = InetAddress.getLocalHost().getHostAddress();
// 建立ws连接对象
org.java_websocket.client.WebSocketClient webSocketClient =
new org.java_websocket.client.WebSocketClient(
new URI("ws://"+myConfig.getJavaIP()+":"+myConfig.getJavaPort()+"/webSocket/" + IP),
new Draft_6455()) {
@Override
public void onOpen(ServerHandshake handshakedata) {
log.info("[websocket] 连接成功");
}
@Override
public void onMessage(String message) {
log.info("[websocket] 收到消息={}", message);
}
@Override
public void onClose(int code, String reason, boolean remote) {
log.info("[websocket] 退出连接");
}
@Override
public void onError(Exception ex) {
log.info("[websocket] 连接错误={}", ex.getMessage());
}
};
// 连接
webSocketClient.connect();
return webSocketClient;
}
}
使用
@Autowired
private WebSocketClient webSocketClient;
// 发送消息
webSocketClient.send(JSON.toJSONString(uploadMsg));
excel导入导出
直接使用阿里的easy-excel
EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel (alibaba.com)
我的代码在gitee:excel-process: excel导入、导出、下载数据模板
随机数
// 获取0-6不包含6的随机整数
Random random = new Random();
random.nextInt(6);
IO流
字节流
字节流是处理所有 I/O 操作的基础。它用于处理原始二进制数据(例如图片、音频文件、视频文件等),它不管数据的内容是文本、图片还是其他格式,都是以字节的形式进行读写。
字节流的两个最常用的基类是:
InputStream:所有字节输入流的父类。
OutputStream:所有字节输出流的父类
字节流提供的常见实现类:
FileInputStream 和 FileOutputStream:用于从文件读取或写入字节数据。
BufferedInputStream 和 BufferedOutputStream:用于提高输入输出效率,使用缓冲区减少读取次数。
DataInputStream 和 DataOutputStream:可以处理基本数据类型(例如 int, float 等)的读取和写入。
ObjectInputStream 和 ObjectOutputStream:用于序列化和反序列化对象。
字符流
字符流用于处理文本数据,字符流通过字符编码(通常是 UTF-8 或 GBK 等)来处理文本,因此它专门用于处理文本文件。
字符流的两个最常用的基类是:Reader:所有字符输入流的父类。Writer:所有字符输出流的父类。
字符流提供的常见实现类:
FileReader 和 FileWriter:用于从文件中读取和写入字符数据。
BufferedReader 和 BufferedWriter:可以使用缓冲区来提高读取和写入字符数据的效率。
PrintWriter:用于打印格式化的文本。
缓冲流(Buffered Streams)
缓冲流是对字节流和字符流的封装,提供了一个缓冲区,减少了磁盘和内存之间的读写次数,从而提高性能。
BufferedInputStream 和 BufferedOutputStream:适用于字节流。
BufferedReader 和 BufferedWriter:适用于字符流。
数据流(Data Streams)
数据流允许你读写原始数据类型(如 int, float, long 等),并提供了一个标准的格式,可以跨平台读写数据。
DataInputStream:用于从输入流中读取原始数据。
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class DataInputStreamExample {
public static void main(String[] args) {
try (DataInputStream dis = new DataInputStream(new FileInputStream("example.dat"))) {
int number = dis.readInt();
System.out.println("Read number: " + number);
} catch (IOException e) {
e.printStackTrace();
}
}
}
DataOutputStream:用于向输出流写入原始数据。
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamExample {
public static void main(String[] args) {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("example.dat"))) {
int number = 42;
dos.writeInt(number);
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象流(Object Streams)
对象流用于对象的序列化和反序列化。通过对象流,我们可以将 Java 对象保存到文件中(序列化)或从文件中恢复 Java 对象(反序列化)。
ObjectInputStream:用于从输入流中读取 Java 对象。
ObjectOutputStream:用于将 Java 对象写入输出流。
调用第三方接口
Java API
使用标准的 Java API 中的 java.net
包来进行 HTTP 请求。GET
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class ApiCaller {
public static void main(String[] args) {
try {
// 第三方接口的URL
String apiUrl = "https://api.example.com/data";
// 创建 URL 对象
URL url = new URL(apiUrl);
// 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法
connection.setRequestMethod("GET");
// 获取响应代码
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// 读取响应内容
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// 处理响应内容
System.out.println("Response: " + response.toString());
} else {
System.out.println("HTTP Request Failed with response code: " + responseCode);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
post
public static String sendPostRequest(String remoteUrl,String requestBody){
String result = null;
try {
// 创建 URL 对象
URL url = new URL(remoteUrl);
// 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法为 POST
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
// 启用输入输出流
connection.setDoOutput(true);
// 设置请求体
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(requestBody.getBytes(StandardCharsets.UTF_8));
}
// 获取响应代码
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
// 读取响应内容
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// 处理响应内容
log.info("响应内容:{}",response.toString());
result = response.toString();
} else {
log.error("请求失败,响应码是:{} " , responseCode);
}
} catch (Exception e) {
e.printStackTrace();
log.error("出错了:",e);
}
return result;
}
Apache HttpClient
Apache HttpClient 是一个功能强大、灵活且可扩展的 HTTP 客户端库,它提供了更高级的功能,如连接池、Cookie 管理等。
<!-- http通信 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>