2020-09-08

原文引用: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

ClassPathResource classPathResource = new ClassPathResource("static/a.txt");

classPathResource.getInputStream();

其中,这个a.txt存放在resources/static目录下

通过上述方式可以获取a中的内容

 

实现

因为我们无法操作jar包内容,所以我们只能将文件存放在别的位置,与jar包同级的目录是一个不错的选择。

首先获取根目录

1

2

3

4

File path = new File(ResourceUtils.getURL("classpath:").getPath());

if(!path.exists()) {

path = new File("");

}

然后获取需要的目录,我们设定我们需要将文件存放在与jar包同级的static的upload目录下

1

2

3

4

File upload = new File(path.getAbsolutePath(),"static/upload/");

if(!upload.exists()) {

upload.mkdirs();

}

然后当我们要将上传的文件存储的时候,按照下面的方式去新建文件,然后使用你喜欢的方式进行存储就可以了。

1

2

File upload = new File(path.getAbsolutePath(),"static/upload/test.jpg");

FileUtils.copyInputStreamToFile(inputStream, uploadFile);

 

不要忘记

你需要在application.yml配置中加入以下代码,指定两个静态资源的目录,这样你上传的文件就能被外部访问到了。

1

2

3

4

spring:

# 静态资源路径

resources:

static-locations: classpath:static/,file:static/

这样就能实现上传文件

 

最后的封装

工具类:

https://github.com/LinkinStars/springBootTemplate/blob/master/src/main/java/com/linkinstars/springBootTemplate/util/FileHandleUtil.java

这个工具类依赖了

1

2

compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.1'

compile group: 'commons-io', name: 'commons-io', version: '2.4'

如何你不喜欢完全可以根据自己的喜欢改变

如何使用:

1

2

3

4

5

6

7

8

/**

* 测试文件上传

*/

@RequestMapping("/upload")

@ResponseBody

public String upload(MultipartFile file) throws IOException {

return "文件存放路径为" + FileHandleUtil.upload(file.getInputStream(), "image/", file.getOriginalFilename());

}

最后效果


 

Follow up

这个工具类只是实现了如何上传文件,入参也只有InputStream,后续如何你需要接入参数File或者加入文件名防重复等等,就由你来完成了。

总结

以上所述是小编给大家介绍的SpringBoot上传文件到本服务器 目录与jar包同级问题,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值