原文引用:https://www.cnblogs.com/zhuyeshen/p/11435793.html 下面有详细摘抄↓↓↓↓↓↓
自己代码中用:
package com.ecolord.changshu.server;
import com.ecolord.changshu.utils.MySQLUtils;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
import java.io.*;
import java.math.BigDecimal;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Iterator;
import java.util.TimeZone;
import java.util.UUID;
public class SocketServer {
//解码buffer
private Charset cs = Charset.forName("UTF-8");
//接受数据缓冲区
private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
//发送数据缓冲区
private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
//选择器(叫监听器更准确些吧应该)
private static Selector selector;
private static Logger logger = LoggerFactory.getLogger(SocketServer.class);
/**
* 启动socket服务,开启监听
*
* @param port
* @throws IOException
*/
public void startSocketServer(int port) {
try {
//打开通信信道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//设置为非阻塞
serverSocketChannel.configureBlocking(false);
//获取套接字
ServerSocket serverSocket = serverSocketChannel.socket();
//绑定端口号
serverSocket.bind(new InetSocketAddress(port));
//打开监听器
selector = Selector.open();
//将通信信道注册到监听器
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//监听器会一直监听,如果客户端有请求就会进入相应的事件处理
while (true) {
// 等待某信道就绪
int selectInt = selector.select();
if (selectInt == 0) {
continue;
}
// 取得迭代器.selectedKeys()中包含了每个准备好某一I/O操作的信道的SelectionKey
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext())
{
SelectionKey selectionKey = iterator.next();
// 有客户端连接请求时
if (selectionKey.isAcceptable()) {
handleAccept(selectionKey);
}
// 从客户端读取数据
if (selectionKey.isReadable()) {
handleRead(selectionKey);
}
// 向客户端发送数据
if (selectionKey.isWritable()) {
handleWrite(selectionKey);
}
iterator.remove();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 有客户端连接请求时
* @param selectionKey
* @throws IOException
*/
private void handleAccept(SelectionKey selectionKey) throws IOException {
try {
// 返回创建此键的通道,接受客户端建立连接的请求,并返回 SocketChannel 对象
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
SocketChannel clientChannel = serverSocketChannel.accept();
// 非阻塞式
clientChannel.configureBlocking(false);
// 注册到selector
//clientChannel.register(selector, SelectionKey.OP_READ);
clientChannel.register(selectionKey.selector(), SelectionKey.OP_READ);//liweihua
String msg = readConfig();
sendInfo(clientChannel, msg);
System.err.println("client IP :" + clientChannel.socket().getRemoteSocketAddress());
}
catch(Exception ex) {
logger.info(ex.getMessage());
}
}
/**
* 从客户端读取数据
* @param selectionKey
* @throws IOException
*/
private void handleRead(SelectionKey selectionKey) throws IOException {
try
{
String requestMsg = "";
SocketChannel clientChannel = (SocketChannel) selectionKey.channel();
while(clientChannel.read(rBuffer) > 0){
//读取数据
rBuffer.flip();
requestMsg = String.valueOf(cs.decode(rBuffer).array());
/*while(rBuffer.hasRemaining()) {
requestMsg += String.valueOf(cs.decode(rBuffer.get(new byte[rBuffer.limit()])).array());
}*/
String responseMsg = "收到客户端的消息:" + requestMsg;
String yuan = "";
String zhuan = "";
byte[] rBufferBytes = rBuffer.array();
for (int i=0;i<rBufferBytes.length;i++){
yuan += rBufferBytes[i] + " ";
zhuan += Integer.toHexString(0xff & rBufferBytes[i]) + " ";
}
logger.info("元数据:" + yuan + "\n ascii码:" + zhuan + "\n 转成字符串:" + responseMsg);
rBuffer.clear();
sBuffer = ByteBuffer.allocate(responseMsg.getBytes("UTF-8").length);
sBuffer.put(responseMsg.getBytes("UTF-8"));
sBuffer.flip();
clientChannel.write(sBuffer);
String[] array = responseMsg.split(";");
if(array.length==6)
{
String NH3 = array[3];
String H2S = array[4];
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+08:00"));
double dNH3 = Double.parseDouble(NH3.substring(NH3.indexOf("=")+1));
double dH2S = Double.parseDouble(H2S.substring(H2S.indexOf("=")+1));
double NH3Value = 0;
double H2SValue = 0;
if(dNH3 >0)
{
NH3Value = 1.67 * Math.log(dNH3) + 2.38;
}
if(dH2S >0)
{
H2SValue = 0.95 * Math.log(dH2S) + 4.14;
}
double value = new BigDecimal(NH3Value>H2SValue?NH3Value:H2SValue).setScale(2,BigDecimal.ROUND_DOWN).doubleValue();;
int standard = 1;
if(value > 2)
{
standard = 0;
}
boolean result = MySQLUtils.insert(UUID.randomUUID().toString().replace("-",""),dNH3,dH2S,value,standard,new Timestamp(calendar.getTime().getTime()));
}
}
}
catch(Exception ex) {
logger.info(ex.getMessage());
}
}
/**
* 向客户端写数据
* @param key
*/
private void handleWrite(SelectionKey key) throws Exception {
sendInfo((SocketChannel)key.channel(), "服务端发送信息!");
System.out.println("服务端发送信息!");
}
public static void sendInfo(SocketChannel clientChannel, String msg) throws Exception
{
// 向客户端发送连接成功信息
clientChannel.write(ByteBuffer.wrap(msg.getBytes()));
}
/**
* 读取配置文件
* 打包成jar包运行时,读取外部文件需要在yml里配置
* spring
* # 静态资源路径
* resources:
* static-locations: classpath:config/,file:config/
*/
private static String readConfig(){
String msg = "";
try {
//获取根目录
File path = new File(ResourceUtils.getURL("classpath:").getPath());
if(!path.exists()) {
path = new File("");
}
File config = new File(path.getAbsolutePath(),"config/");
if(!config.exists()) {
config.mkdirs();
}
File configXml = new File(path.getAbsolutePath(),"config/config.xml");
if (!configXml.exists()) {
configXml.createNewFile();// 创建目标文件
//向目标文件中写入内容 弃:FileWriter writer = new FileWriter(config, true);FileWriter会有中文乱码的问题
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(configXml,true), "UTF-8"));//append为true时为追加模式,false或缺省则为覆盖模式
writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
writer.append("<msg>连接服务器成功!</msg>");
writer.flush();
writer.close();
}
//读取配置文件内容 弃:String msg = txt2String(new File(configPath.getAbsolutePath(),"config.txt"))
SAXReader reader = new SAXReader();
InputStream inputStream = new FileInputStream(configXml);
Document document = reader.read(inputStream);
msg = String.valueOf(document.content().get(0).getText());
} catch (Exception e){
logger.info(e.getMessage());
}
return msg;
}
/**
* -----------------------------------------------------------------------
* getAppPath需要一个当前程序使用的Java类的class属性参数,它可以返回打包过的
* Java可执行文件(jar,war)所处的系统目录名或非打包Java程序所处的目录
*
* @param cls 为Class类型
* @return 返回值为该类所在的Java程序运行的目录
* -------------------------------------------------------------------------
*/
public static String getAppPath(Class cls) {
//检查用户传入的参数是否为空
if (cls == null)
throw new java.lang.IllegalArgumentException("参数不能为空!");
ClassLoader loader = cls.getClassLoader();
//获得类的全名,包括包名
String clsName = cls.getName() + ".class";
//获得传入参数所在的包
Package pack = cls.getPackage();
String path = "";
//如果不是匿名包,将包名转化为路径
if (pack != null) {
String packName = pack.getName();
//此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库
if (packName.startsWith("java.") || packName.startsWith("javax."))
throw new java.lang.IllegalArgumentException("不要传送系统类!");
//在类的名称中,去掉包名的部分,获得类的文件名
clsName = clsName.substring(packName.length() + 1);
//判定包名是否是简单包名,如果是,则直接将包名转换为路径,
if (packName.indexOf(".") < 0) path = packName + "/";
else {//否则按照包名的组成部分,将包名转换为路径
int start = 0, end = 0;
end = packName.indexOf(".");
while (end != -1) {
path = path + packName.substring(start, end) + "/";
start = end + 1;
end = packName.indexOf(".", start);
}
path = path + packName.substring(start) + "/";
}
}
//调用ClassLoader的getResource方法,传入包含路径信息的类文件名
java.net.URL url = loader.getResource(path + clsName);
//从URL对象中获取路径信息
String realPath = url.getPath();
//去掉路径信息中的协议名"file:"
int pos = realPath.indexOf("file:");
if (pos > -1) realPath = realPath.substring(pos + 5);
//去掉路径信息最后包含类文件信息的部分,得到类所在的路径
pos = realPath.indexOf(path + clsName);
realPath = realPath.substring(0, pos - 1);
//如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名
if (realPath.endsWith("!"))
realPath = realPath.substring(0, realPath.lastIndexOf("/"));
/*------------------------------------------------------------
ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径
中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要
的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的
中文及空格路径
-------------------------------------------------------------*/
try {
realPath = java.net.URLDecoder.decode(realPath, "utf-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
return realPath;
}//getAppPath定义结束
/**
*
* @param file
* @return
*/
public static String txt2String(File file){
StringBuilder result = new StringBuilder();
try{
BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
String s = null;
while((s = br.readLine())!=null){//使用readLine方法,一次读一行
result.append(System.lineSeparator()+s);
}
br.close();
}catch(Exception e){
e.printStackTrace();
}
return result.toString();
}
public static void main(String[] args) {
byte[] bytes = new byte[5];
bytes[0] = 11;
bytes[1] = 127;
bytes[2] = 11;
bytes[3] = 11;
bytes[4] = 11;
System.out.println(bytes[1]);
}
}
目录
前言
看标题好像很简单的样子,但是针对使用jar包发布SpringBoot项目就不一样了。
当你使用tomcat发布项目的时候,上传文件存放会变得非常简单,因为你可以随意操作项目路径下的资源。但是当你使用SpringBoot的jar包发布项目的时候,你会发现,你不能像以前一样操作文件了。当你使用File file = new File()的时候根本不知道这个路径怎么办。而且总不能很小的项目也给它构建一个文件服务器吧。所以这次就来解决这样的问题。
不想知道细节的,可以直接跳转到最后封装的部分,里面有相应的实现。
原因
其实原因你也想的到,你无法对jar包里面的资源进行操作,而对于springboot项目来说,你只能读取里面的文件,只能使用InputStream。使用如下方式针对资源文件进行读取:
1 2 |
|
其中,这个a.txt存放在resources/static目录下
通过上述方式可以获取a中的内容
实现
因为我们无法操作jar包内容,所以我们只能将文件存放在别的位置,与jar包同级的目录是一个不错的选择。
首先获取根目录
1 2 3 4 |
|
然后获取需要的目录,我们设定我们需要将文件存放在与jar包同级的static的upload目录下
1 2 3 4 |
|
然后当我们要将上传的文件存储的时候,按照下面的方式去新建文件,然后使用你喜欢的方式进行存储就可以了。
1 2 |
|
不要忘记
你需要在application.yml配置中加入以下代码,指定两个静态资源的目录,这样你上传的文件就能被外部访问到了。
1 2 3 4 |
|
这样就能实现上传文件
最后的封装
工具类:
这个工具类依赖了
1 2 |
|
如何你不喜欢完全可以根据自己的喜欢改变
如何使用:
1 2 3 4 5 6 7 8 |
|
最后效果
Follow up
这个工具类只是实现了如何上传文件,入参也只有InputStream,后续如何你需要接入参数File或者加入文件名防重复等等,就由你来完成了。
总结
以上所述是小编给大家介绍的SpringBoot上传文件到本服务器 目录与jar包同级问题,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!