Linux上开发常见问题整理

Linux上开发常见问题整理

1.java工程在linux上运行测试

 ①首先要有一个main方法作为主类,程序的入口,右键-->Run As-->javaapplication生成配置文件入口

 ②右键该工程-->Export-->Runnable JAR file-->选择上一步生成的配置文件作为该jar运行入口,确定即可

 ③运行java  -jar  jar名+后缀(ps –ef|grep job)

总结:Linux后台运行Jar方法

·        linux服务器上运行Jar文件时通常的方法是:

$ java -jar test.jar

·        这种方式特点是ssh窗口关闭时,程序中止运行.或者是运行时没法切出去执行其他任务,有没有办法让Jar在后台运行呢:

·        方法一:

$ nohup java -jar test.jar &

//nohup 意思是不挂断运行命令,当账户退出或终端关闭时,程序仍然运行

//当用 nohup 命令执行作业时,缺省情况下该作业的所有输出被重定向到nohup.out的文件中

//除非另外指定了输出文件。

·        方法二:

$ nohup java -jar test.jar >temp.txt &

//这种方法会把日志文件输入到你指定的文件中,没有则会自动创建

·        jobs命令和 fg命令:

$ jobs

//那么就会列出所有后台执行的作业,并且每个作业前面都有个编号。

//如果想将某个作业调回前台控制,只需要 fg + 编号即可。

$ fg 2

·        查看某端口占用的线程的pid

netstat -nlp |grep :8080

2.linux命令

 ①实时查看日志:tail –f 日志文件名称+后缀 (如:tail –f cat.out)

 ②查看某程序运行状况:ps –ef|grep 程序名 (如: ps –ef|grep redis)

3. linux虚拟机下安装jdk失败显示如下

./jdk-6u13-linux-i586.bin:./install.sfx.1956: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory Failed to extract the files.Please refer to the Troubleshooting section of the Installation Instructions onthe download p…
解答:Linux操作系统是64位的。软件包jdk-6u13-linux-i586.bin的名字中包含了i586,表示,他是32位的软件。将jdk改成64位的重新安装,错误解决。

4.日历类calendar

 // calendar实例设置小时为当前小时减一

calendar.set(Calendar.HOUR_OF_DAY,calendar.get(Calendar.HOUR_OF_DAY) - 1);

5. HBase正则匹配

// HBase正则匹配

RegexStringComparatorcomp = newRegexStringComparator("20171116\\d|$");

filters.addFilter(newSingleColumnValueFilter(Bytes.toBytes("info"), Bytes.toBytes("time"), CompareOp.EQUAL, comp ));

6.map排序

 ①单个值的map排序

 把每一个map放到list中,比较mapkeyvalue,冒泡时整体移动

 // 以时间冒泡排序

for (inti = 0; i < mapList.size() - 1; i++) {

    for (int j = 0; j < mapList.size() - i - 1; j++) {

        int a = Integer.valueOf(mapList.get(j).get("time").toString());

        int b = Integer.valueOf(mapList.get(j+1).get("time").toString());

        if(a > b){

            Map temp = mapList.get(j+1);

            mapList.set((j + 1),mapList.get(j));

            mapList.set(j, temp);

        }

    }

}

 ②多个值的map按value大小排序

 publicclass MapSortUtil {

    /**

     * map值大小降序排列(float类型)

     * @param oriMap

     * @return

     */

    publicstatic Map sortMapByValue(Map oriMap) {

        if (oriMap == null || oriMap.isEmpty()) {

            returnnull;

        }

        Map sortedMap = newLinkedHashMap();

        List>entryList = newArrayList>(

                oriMap.entrySet());

        Collections.sort(entryList, new MapValueComparator());

   

        Iterator> iter = entryList.iterator();

        Map.Entry tmpEntry = null;

        while (iter.hasNext()) {

            tmpEntry = iter.next();

            sortedMap.put(tmpEntry.getKey(),tmpEntry.getValue());

        }

        return sortedMap;

    }

}

 

publicclassMapValueComparator implements Comparator> {

    @Override

    publicintcompare(java.util.Map.Entry o1,java.util.Map.Entry o2) {

        returno2.getValue().compareTo(o1.getValue()); //降序

    }

}

7.SVN更新/提交报错,信息显示xx文件被锁定

 解决方案:找到被锁定的文件/文件夹 右键-->term--> Refresh/Cleanup清除锁即可更新/提交

8.float类型计算结果保留两位小数

①方法一:(float) Math.round(a*100)/100  //afloat类型

②方法二:

BigDecimal bg = new BigDecimal(f);

double f1 = bg.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();

③方法三:

float num= (float)2/3;  

DecimalFormat df = new DecimalFormat("0.00");//格式化小数   

String s = df.format(num);//返回的是String类型 

9.kafka客户端服务消费数据刷入流程

①进入kafka

cd kafka_2.10-0.10.0.0      (/home/hxxtsx/kafka_2.10-0.10.0.0)

②启动客户端

bin/kafka-console-producer.sh

③创建kafka消息和主题

--broker-listNM-304-SA5212M4-BIGDATA-659:9091 --topic systemlog --producer.configconfig/producer.properties

具体操作:

bin/kafka-console-producer.sh --broker-listNM-304-SA5212M4-BIGDATA-659:9091 --topic systemlog --producer.configconfig/producer.properties

④设置json格式消息

{"system":"scheduler","module":"listener","host":"192.168.1.1","comm":"hello! this isalert!","logTime":"20171123102333","logType":"system","flag":"Exception"}

10.Hbase shell命令,根据某个字段值查询

语法:scan '表名',{FILTER => “ColumnPrefixFilter('列名') AND  ValueFilter( = , 'substring:列的值')”}

示例:scan 'log:analysis_notice_state',{FILTER =>"ColumnPrefixFilter('workerID') AND ValueFilter ( = , 'substring:W111')"}

11.HBase java API过滤器问题,根据某个字段过滤时,出现多个为空的情况(有些记录没有这个列值默认不会过滤)

SingleColumnValueFilter:用一列的值决定这一行的数据是否被过滤。在它的具体对象上,可以调用setFilterIfMissing(true)或者setFilterIfMissing(false),默认的值是false,其作用是,对于咱们要使用作为条件的列,如果这一列本身就不存在,那么如果为true,这样的行将会被过滤掉,如果为false,这样的行会包含在结果集中。

1. SingleColumnValueFilter scvf = new SingleColumnValueFilter(  

2.         Bytes.toBytes("colfam1"),   

3.         Bytes.toBytes("qual2"),   

4.         CompareFilter.CompareOp.NOT_EQUAL,   

5.         new SubstringComparator("BOGUS"));  

6. scvf.setFilterIfMissing(false);  

7. scvf.setLatestVersionOnly(true); // OK 

12. 导入的包报错:The import java.util cannot be resolved

解决方案:右键项目----àbuildpath----à最下面那个configuration的选择libraries找到JRE(这个时候你会发现这个jre前面有!或者是红X)选中remove掉重新为该项目选择一个JRE选中项目,project----clean,也可能未添加JRE。

13.eclipse/myeclipse解决editor does not contain a main type的方法

检查发现原来的包全部变成文件夹格式,我是右击src--àbuildpath--àuseas source folder就行了,就变回包格式的了,记得运行之后重启

14. java中Double类型的运算精度丢失的问题

在使用Java,double 进行运算时,经常出现精度丢失的问题,总是在一个正确的结果左右偏0.0000**1。特别在实际项目中,通过一个公式校验该值是否大于0,如果大于0我们会做一件事情,小于0我们又处理其他事情。 这样的情况通过double计算出来的结果去和0比较大小,尤其是有小数点的时候,经常会因为精度丢失而导致程序处理流程出错。

15.kafka客户端服务消费数据刷入流程

①进入kafka

cd kafka_2.10-0.10.0.0    (/home/hxxtsx/kafka_2.10-0.10.0.0)

②具体操作

bin/kafka-console-producer.sh --broker-listNM-304-SA5212M4-BIGDATA-659:9091 --topic systemlog --producer.configconfig/producer.properties

注:

 bin/kafka-console-producer.sh (启动客户端)

--broker-listNM-304-SA5212M4-BIGDATA-659:9091 --topic systemlog --producer.configconfig/producer.properties (创建kafka消息和主题)

③设置json格式消息

{"system":"scheduler","module":"listener","host":"192.168.1.1","comm":"hello! this isalert!","logTime":"20171123102333","logType":"system","flag":"Exception"}

16.java Timer定时每个整点触发

1.  public class OneHour {  

2.      private final static long JOB_INTERNAL = 1000 * 60 * 60;//隔一个小时运行一次,如果是测试,可以改小一点  

3.      public static void main(String[] args) {  

4.          Timer timer = new Timer();  

5.          Calendar currentTime = Calendar.getInstance();  

6.          currentTime.setTime(new Date());  

7.    

8.          int currentHour = currentTime.get(Calendar.HOUR);  

9.          currentTime.set(Calendar.HOUR, currentHour + 1);  

10.         currentTime.set(Calendar.MINUTE, 0);  

11.         currentTime.set(Calendar.SECOND, 0);  

12.         currentTime.set(Calendar.MILLISECOND, 0);  

13.           //下面几行是相隔时间短一点的测试代码  

14.         /* 

15.         currentTime.set(Calendar.HOUR, currentTime.get(Calendar.HOUR)); 

16.         currentTime.set(Calendar.MINUTE, currentTime.get(Calendar.MINUTE)); 

17.         currentTime.set(Calendar.SECOND, currentTime.get(Calendar.SECOND)); 

18.         currentTime.set(Calendar.MILLISECOND, currentTime.get(Calendar.MILLISECOND)); 

19.         */  

20.         Date NextHour = currentTime.getTime();  

21.         System.out.println(NextHour);  

22.         timer.scheduleAtFixedRate(new MyTask(), NextHour, JOB_INTERNAL);  

23.     }  

24. }

17.读取配置文件

System.getProperty("user.dir")获取项目目录,配置文件和项目放在同一目录下

allProperties.getProperty(“配置文件key”);获取配置参数

System.getProperty("file.separator");路径分隔符

KafkaConsumerconsumer = new KafkaConsumer<>(props); 通过配置文件创建kafka消费者

consumer.subscribe(Arrays.asList("topicName")); 消费者订阅主题

privatestatic  Properties allProperties = new Properties();

       publicstaticvoid main(String[] args) {

       try {

           InputStream in = new BufferedInputStream(newFileInputStream(System.getProperty("user.dir")+"/kafka_consumer_config.properties"));

           allProperties.load(in);

       } catch (Exception e) {

           logger.error("读取Kafka配置文件出错!" + e);

       }

}

//消费消息

while(true) {

       ConsumerRecordsrecords = consumer.poll(100);

       for (ConsumerRecordrecord: records) { // 消息内容record.value()

            Map map =(Map) JSON.parse(record.value().toString());

            System.out.println(i +"======"+map.toString());

              

            // 写入文件

            if(!TextUtil.isEmpty(msg)){

               System.out.println("=====Prepare to write to the log file !");

               writeFile(file, msg);

            }else{

              logger.error("日志消息为空,无法写入文件!");

           }

        }

}

/**

     * 写入文件方法

     * @param file

     * @param msg

     */

    publicstaticvoid writeFile(Filefile, String msg){

       BufferedWriter bw = null;

       // 文件不存在,创建文件

       if(!file.exists()){

           try {

              System.out.println("file:"+file.getPath());

              file.createNewFile();

           } catch (IOException e) {

              logger.error("文件" + file.getPath()+ "创建失败! " + e);

           }

       }

        try {

            // utf-8格式追加写

           bw = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(file, true),"UTF-8"));

           bw.write(msg);

           bw.flush();

           bw.newLine(); //换行

           System.out.println("===== 日志消息 " + msg + " 写入文件成功! " + file.getPath());

        } catch (Exception e) {

            logger.error("日志消息 " + msg + " 写入文件失败!" + e);

        }finally{

            try {

               bw.close();

            } catch (IOException e){

               e.printStackTrace();

            }

        }

    }

18.eclipse修改maven的本地仓库位置

eclipse中安装maven2插件之后,maven默认的本地库的路径是在${user}/.m2/repository/下,也就是在c盘的C:\Users\admin.m2\repository位置下。但是我们一般是不想放在C盘下,想将其放在别的盘符下,这里以D:\IDE\personalEclipse\repository为例: 
1
、手动创建本地仓库的地址为,在对应路径D:\IDE\personalEclipse\下创建repository文件夹,然后将D:\IDE\personalEclipse\apache-maven-3.3.9\conf\setting.xml这个路径下的文件复制到D:\IDE\personalEclipse\repository该文件夹下。 
2
、从windows的环境变量中增加了:M2_REPO=D:/IDE/personalEclipse/repository,同时把这个变量增加到path变量中。 

3、修改D:\IDE\personalEclipse\apache-maven-3.3.9\conf\setting.xml文件,在localRepository标签中添加D:/IDE/personalEclipse/repository表示maven的本地库的路径

4、从eclipse->preferences->maven->installationsadd一个已经安装到d盘的maven: 

5、从eclipse->preferences->maven->installations下修改user setting 选项为:D:/IDE/personalEclipse/repository/settings.xml,接着修改global setting 
D:\IDE\personalEclipse\apache-maven-3.3.9\conf\setting.xml
,找到对应的文件路径即可 
并点击updatesettings,然后点击下面的reindex按钮更新索引。

6、点击配置窗口的apply按钮即可

7、配置修改后,eclise会自动更新索引,当完成后重启myeclipse,会发现M2_REPO变量的值变成了D:/IDE/personalEclipse/repository

注意:在新建一个maven工程时,有时会遇到,pom文件一切正常,某个类下报某包找不到的错误,但看build path时却发现该包已经添加到maven依赖里边(buildpath里),仔细查看buildpath发现该类是存在但是不完整,部分方法点进去有个红色X,这种原因通常是本地仓库配置有问题或者网络问题,导致jar包下载不完善,调整后重新build,问题解决。

19."yyyyMMddHHmmss"字符串转成"yyyy-MM-dd HH:mm:ss"字符串

/**

     *"yyyyMMddHHmmss"字符串转成"yyyy-MM-dd HH:mm:ss"字符串

     * @param str

     * @return

     */

    privatefinalstatic SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    privatefinalstatic SimpleDateFormat sdfTimes = new SimpleDateFormat("yyyyMMddHHmmss");

    publicstatic String strToDateStr(String str){

       Date date = null;

       String dateStr = null;

       try {

           if(!TextUtil.isEmpty(str)){

              date = sdfTimes.parse(str);

              dateStr = sdfTime.format(date);

           }

       } catch (ParseException e) {

           e.printStackTrace();

       }

       return dateStr;

    }

20.Xshell映射,不同网段/虚拟机映射到本地访问

①打开Xshell,属性à隧道(ssh里边)à添加

②在弹出的窗口填写要映射的机器IP及端口号,及映射到本地的IP及端口号,确认后连接即可通过映射的本地端口号访问目标机器

21.elasticsearch-head不能连接管理elasticsearch

命令行运行grunt server

grunt server
Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://localhost:9100

打开http://localhost:9100进入管理页面,填写好地址点连接,然后连接不上elasticsearch 浏览器错误详情提示不安全

Firefox Console已拦截跨源请求:同源策略禁止读取位于 http://localhost:9200/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

Chrome Console:XMLHttpRequest cannot load http://localhost:9200/. No'Access-Control-Allow-Origin' header is present on the requested resource.Origin 'http://localhost:9100' is therefore not allowed access.

因为端口不一样,所以浏览器自带的安全策略是不允许去请求不同源的资源。

修改Elasticsearch配置

elasticsearch.yml 添加下面配置,重启后即可生效

http.cors.enabled: true
http.cors.allow-credentials: true
http.cors.allow-methods: OPTIONS,HEAD,GET,POST,PUT,DELETE
http.cors.max-age: 0
http.cors.allow-origin: /http?:\/\/localhost(:[0-9]+)?/
http.cors.allow-headers : X-Requested-With,X-Auth-Token,Content-Type,Content-Length

可以用 Nginx 做下反代, 然后加下Header。然后地址改为http://localhost:9201

server {
    listen   9201;
    location~ /* {
        add_header Access-Control-Allow-Origin *;
        proxy_pass http://127.0.0.1:9200;
    }
 }

之前也是碰到楼主上面的问题,跨域问题~ 修改elasticsearch elasticsearch.yml 文件后解决,版本都是5.x 版本~

http.host:192.168.x.x (elasticsearch ip 一般 elasticsearch head 是同一台上面~) http.cors.enabled: truehttp.cors.allow-origin: "*"

因为都是内网的IP所以还是http.cors.allow-origin:"*"简单暴力好用

火狐和谷歌不支持访问,换IE后连接成功!

22.Elasticsearch之head插件Browser为空

问题描述:es里有几个index,在概览下是可以看到的,但是在数据浏览页却什么都没有

 
解决方法:原来用的是火狐浏览器,换成chrome浏览器就好了

23.Eclipse修改注释颜色/设置注释模板

①修改注释颜色:window -->preferences --> java --> editor --> syntax coloring --> comments 中的前两个就是修改注释颜色的。点击右边的color修改颜色就行了。右侧还有Italy,Bold等字体样式,自己也可以选择。

②设置注释模板:window -->preferences --> java --> code style --> code Templates --> comments--> types --> edit

24. ES进行聚合操作时提示Fielddata is disabled on text fields by default ...

①遇到这个错误是因为你尝试对一个text类型的字段做排序,而text类型的字段是要分词的。一来词典很大,性能会很差;二来排序结果是词典里的词,而并非整个text的内容。出于这2点原因,ES5.x以后对于text类型默认禁用了fielddata,防止对text字段一些错误的操作(排序,聚合,script)而给heap造成很大的压力。

②ElasticSearch 5.x后对排序,聚合这些操作用单独的数据结构(fielddata)缓存到内存里了,需要单独开启,官方解释在此https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html

③简单来说就是在聚合前执行如下操作

PUT megacorp/_mapping/employee/

{

 "properties": {

   "interests": {

     "type":     "text",

     "fielddata": true

    }

  }

}

④附java API说明文档 https://www.elastic.co/guide/e ... .html

⑤字段.keyword

25. log4j报错ERROR StatusLogger No log4j2 configuration file found. Usingdefault configuration: logging only errors to the console.

26. 在使用eclipse构建maven项目时,突然出现错误提示:An error occurred while filtering resources,在项目中到处都找不到哪里有问题,最后在国外网站找到解决办法:

右键项目--maven--update project 

27. 详解maven的pom.xml用解决版本问题

    用maven管理库依赖,有个好处就是连同库的依赖的全部jar文件一起下载,免去手工添加的麻烦,但同时也带来了同一个jar会被下载了不同版本的问题,好在pom的配置里面允许用来排除一些不需要同时下载的依赖jar 。

使用exclusion排除依赖

假设有这样一种依赖关系,A->B->C,这个时候由于某些原因,我们不需要对C的依赖,但是我们又必须要对B的依赖,这个时候该怎么办呢?针对这种情况,Maven给我们提供了一个exclusion功能,我们可以在添加A对B的依赖时申明不需要引进B对C的依赖。具体做法如下:

  1.   
  2.       
  3.      groupB  
  4.      artifactB  
  5.      1.0  
  6.        
  7.           
  8.             groupC  
  9.             artifactC  
  10.           
  11.        
  12.      
  13.        ...  
  14.   

28. ElasticSearch执行报错:Exception in thread "main" java.lang. UnsupportedClassVersionError:org/elasticsearch/common/transport/TransportAddress: Unsupported major.minor version 52.0

原因是因为JDK版本过低,ES仅支持JDK1.8及以上版本

29.Spring-@value用法详解

为了简化读取properties文件中的配置值,spring支持@value注解的方式来获取,这种方式大大简化了项目配置,提高业务中的灵活性。

一、两种使用方法

1@Value("#{configProperties['key']}")

2@Value("${key}")

二、配置

2.1 @Value("#{configProperties['key']}")使用

2.1.1配置文件:

30.tomcat启动初始化参数

31. spring中InitializingBean接口使用理解

InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法。

测试程序如下:

ApplicationContext.xml配置文件如下:

Main主程序如下:

运行Main程序,打印如下结果:

这说明在spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法。

问题

实现InitializingBean接口与在配置文件中指定init-method有什么不同?

修改配置文件,加上init-method配置,修改如下:

在配置文件中加入init-method="testInit"

运行Main程序,打印如下结果:

由结果可看出,在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。

这方式在spring中是怎么实现的?

通过查看spring的加载bean的源码类(AbstractAutowireCapableBeanFactory)可看出其中奥妙

AbstractAutowireCapableBeanFactory类中的invokeInitMethods讲解的非常清楚,源码如下:

总结

1springbean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用

2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖

3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。

32. java获取文件大小的方法

目前Java获取文件大小的方法有两种:

1、通过filelength()方法获取;

2、通过流式方法获取;

通过流式方法又有两种,分别是旧的java.io.*FileInputStreamavailable()方法和新的java..nio.*中的FileChannel

下面依次介绍这几种方法:

一、通过length方法:

1、创建一个文件:

 

2、获取文件大小:

3、查看结果:可见,使用length方法获取的文件大小与windows中显示的大小一致!

二、通过file.io.*中的流式方法获取

1、创建一个文件

依旧使用上面的文件

2、使用available方法获取:

3、查看结果:通过这种方法获取的文件大小是2147483647,很明显,这是int类型所能表示的最大值2^31-1,究其原因是因为文件的大小超过了int所能表示的最大值!!!

file.length()方法返回的类型:

available()方法返回的类型:

三、通过file.nio.*中的FileChannel工具来获取文件大小:

1、创建一个文件

依旧使用相同的大文件:

2、使用FileChannel获取文件大小:

3、查看结果:

33.double转long类型

long count = new Double(8.9).longValue() // 结果为8

34. 启动eclipse时出现“Failed to load the JNI sharedlibrary jvm.dll”错误及解决

昨晚安装另一个版本的eclipse,启动时出现了“Failed to load the JNI sharedlibrary jvm.dll”错误;

1、刚开始以为是因为当时没有将旧版本删除干净,于是就找了原来的安装目录,并没有发现残留的配置文件以及启动文件什么的;

2、于是猜测,新安装的这个版本目录下没有jvm.dll这个文件,可是发现是存在的;

    路径1C:\Program Files (x86)\Java\jre6\bin\client\jvm.dll(该路径下安装的是32位的Java jdk

    路径2C:\Program Files\Java\jre6\bin\client\jvm.dll(该路径下安装的是64位的Java jdk

3、后来网上查了一下,说是有可能是版本原因,于是用notepad++看了下eclipse的配置文件(位于eclipse目录下configuration文件夹中config.ini文件),发现新安装的eclipse32位的,而我所用的jdk64位的;(此为问题所在)

既然找到了问题,那就好办了,随即在自己的云盘里下了32位的jdk,并将环境变量中JAVA_HOME路径改为32jdk的路径;32位的jdk64位的jdk因为安装位置的不同,因此可以共存,需要用哪个,改一下JAVA_HOME路径就OK了。

35.读取配置文件的几中方式

正常在Java工程中读取某路径下的文件时,可以采用绝对路径和相对路径,绝对路径没什么好说的,相对路径,即相对于当前类的路径。在本地工程和服务器中读取文件的方式有所不同,以下图配置文件为例。

本地读取资源文件

java类中需要读取properties中的配置文件,可以采用文件(File方式进行读取:

1 File file = new File("src/main/resources/properties/basecom.properties");
2 InputStream in = new FileInputStream(file);

当在eclipse中运行(不部署到服务器上),可以读取到文件。

服务器(Tomcat)读取资源文件

方式一:采用流+Properties

当工程部署到Tomcat中时,按照上边方式,则会出现找不到该文件路径的异常。经搜索资料知道,Java工程打包部署到Tomcat中时,properties的路径变到顶层(classes下),这是由Maven工程结构决定的。由Maven构建的web工程,主代码放在src/main/java路径下,资源放在src/main/resources路径下,当构建为war包的时候,会将主代码和资源文件放置classes文件夹下:

并且,此时读取文件需要采用流(stream的方式读取,并通过JDKProperties类加载,可以方便的获取到配置文件中的信息,如下:

1 InputStream in = this.getClass().getResourceAsStream("/properties/basecom.properties");
2 Properties properties = new Properties();
3 properties.load(in);
4 properties.getProperty("property_name");

 其中properties前的斜杠,相对于调用类,共同的顶层路径。

方式二:采用Spring注解

如果工程中使用Spring,可以通过注解的方式获取配置信息,但需要将配置文件放到Spring配置文件中扫描后,才能将配置信息放入上下文。

1 <context:component-scan base-package="com.xxxx.service"/>
2 <context:property-placeholder location="classpath:properties/xxx.properties" ignore-unresolvable="true"/>

然后在程序中可以使用 @Value进行获取properties文件中的属性值,如下:

1 @Value("${xxxt.server}")
2 private static String serverUrl;

方式三:采用Spring配置

也可以在Spring配置文件中读取属性值,赋予类成员变量

 1 xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 5     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
 6     
 7     <bean id=propertyConfigurer class=org.springframework.beans.factory.config.PropertyPlaceholderConfigurer>
 8         ="location" value="classpath:properties/xxx.properties"/>
 9     bean>
10     
11     <bean id="service" class="com.xxxx.service.ServiceImpl">
12         <property name="serverUrl" value="${xxxt.server}">
13     bean>
14 
15 beans>

参考:

Resourcefrom src/main/resources not found after building with maven        

[Java] jar 文件中读取resources 目录下的文件

36.JAVA中request.getParameterMap()用法

根据Java规范:request.getParameterMap()返回的是一个Map类型的值,该返回值记录着前端(如jsp页面)所提交请求中的请求参数和请求参数值的映射关系。这个返回值有个特别之处——只能读。不像普通的Map类型数据一样可以修改。这是因为服务器为了实现一定的安全规范,所作的限制。比如WebLogicTomcatResinJBoss等服务器均实现了此规范。

   如果实在有必要在取得此值以后做修改的话,要新建一个map对象,将返回值复制到此新map对象中进行修改,用新的map对象代替使用之前的返回值。

37.split(" ") 和 split(" ",-1) 区别

1.如果字符串最后一位有值,则没有区别,

2.如果最后n位都是切割符,split(" ")不会继续切分,split(" ", -1)会继续切分

38.svn导入Maven项目报错:

原因是由于JDK1.8新特性Lambda表达式 project Facets引用的是1.7版本,选中项目右键 --> Build Path --> Configure Build Path --> Maven -->project Facets --> java修改成1.8点击应用即可。

39.操作集群redis报错,(error) MOVED 1157710.142.119.3:6379

原因是没有启动集群模式(即缺少了那个"-c"):

启动命令:redis-cli -h10.142.119.9 -p 6379

修改为:redis-cli -c -h10.142.119.9 -p 6379

40.操作redis报错,WRONGTYPE Operation against a key holding

使用jedis插入数据时出现了一个问题:

1. redis.clients.jedis.exceptions.JedisDataException: WRONGTYPE Operation against a key holding the wrong kind of value  

代码大概是这样实现的:

1. HashMap<String,String> map = new HashMap<String,String>();  

2. map.put("mapKey", "20145");   

3. jedis.hmset("key", map);  

看起来没有值类型不对的样子。后来发现原来是因为redis数据库中已经存在了相同的key, 而且key对应的值类型并不是HashMap;再调用hmset时,就会抛出此错误。

把原来的数据清掉,重新运行就没问题了。

41.Linux下grep显示前后几行信息

标准unix/linux下的grep通过下面參数控制上下文

grep-C 5 foo file 显示file文件里匹配foo字串那行以及上下5

grep-B 5 foo file 显示foo及前5

grep-A 5 foo file 显示foo及后5

42. /dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null

$command > /dev/null

/dev/null是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

如果希望屏蔽 stdout stderr,可以这样写:

$command > /dev/null 2>&1

注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

43. java主线程等待所有子线程执行完毕在执行(常见面试题)

java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个处理都可以用一个线程来执行,所有处理完成了之后才会返回给用户下单成功,下面就说一下我能想到的方法,欢迎大家批评指正:

1.用sleep方法,让主线程睡眠一段时间,当然这个睡眠时间是主观的时间,是我们自己定的,这个方法不推荐,但是在这里还是写一下,毕竟是解决方法

2.使用Thread的join()等待所有的子线程执行完毕,主线程在执行,thread.join()把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。

下面结合这个问题我介绍一些并发包里非常有用的并发工具类

3.等待多线程完成的CountDownLatch

在这里说明一点,countDownLatch不可能重新初始化或者修改CountDownLatch对象内部计数器的值,一个线程调用countdown方法happen-before另外一个线程调用await方法

4.同步屏障CyclicBarrier

写到这里大家不免有些疑问,countDownLatch和cyclicBarrier有什么区别呢,他们的区别:countDownLatch只能使用一次,而CyclicBarrier方法可以使用reset()方法重置,所以CyclicBarrier方法可以能处理更为复杂的业务场景。

我曾经在网上看到一个关于countDownLatch和cyclicBarrier的形象比喻,就是在百米赛跑的比赛中若使用countDownLatch的话冲过终点线一个人就给评委发送一个人的成绩,10个人比赛发送10次,如果用CyclicBarrier,则只在最后一个人冲过终点线的时候发送所有人的数据,仅仅发送一次,这就是区别。

44. CountDownLatch使用场景及分析

JDk1.5提供了一个非常有用的包,Concurrent包,这个包主要用来操作一些并发操作,提供一些并发类,可以方便在项目当中傻瓜式应用。

  JDK1.5以前,使用并发操作,都是通过Thread,Runnable来操作多线程;但是在JDK1.5之后,提供了非常方便的线程池(ThreadExecutorPool),主要代码由大牛Doug Lea完成,其实是在jdk1.4时代,由于java语言内置对多线程编程的支持比较基础和有限,所以他写了这个,因为实在太过于优秀,所以被加入到jdk之中;

  这次主要对CountDownLatch进行系统的讲解

  使用场景:比如对于马拉松比赛,进行排名计算,参赛者的排名,肯定是跑完比赛之后,进行计算得出的,翻译成Java识别的预发,就是N个线程执行操作,主线程等到N个子线程执行完毕之后,在继续往下执行。

      代码示例

 1 public static void testCountDownLatch(){
3         int threadCount = 10;
5         final CountDownLatch latch = new CountDownLatch(threadCount);
7         for(int i=0; i< threadCount; i++){
9             new Thread(new Runnable() {
11                 @Override
12                 public void run() {
14                     System.out.println("线程" + Thread.currentThread().getId() + "开始出发");
16                     try {
17                         Thread.sleep(1000);
18                     } catch (InterruptedException e) {
19                         e.printStackTrace();
20                     }
22                     System.out.println("线程" + Thread.currentThread().getId() + "已到达终点");
24                     latch.countDown();
25                 }
26             }).start();
27         }
29         try {
30             latch.await();
31         } catch (InterruptedException e) {
32             e.printStackTrace();
33         }
35         System.out.println("10个线程已经执行完毕!开始计算排名");
36     }

  执行结果:

线程10开始出发
线程13开始出发
线程12开始出发
线程11开始出发
线程14开始出发
线程15开始出发
线程16开始出发
线程17开始出发
线程18开始出发
线程19开始出发
线程14已到达终点
线程15已到达终点
线程13已到达终点
线程12已到达终点
线程10已到达终点
线程11已到达终点
线程16已到达终点
线程17已到达终点
线程18已到达终点
线程19已到达终点
10个线程已经执行完毕!开始计算排名

源码分析:

1、CountDownLatch:Asynchronization aid that allows one or more threads to wait until a set ofoperations being performed in other threads completes.

    大致意思:也就是说主线程在等待所有其它的子线程完成后再往下执行

2、构造函数:CountDownLatch(int count)//初始化count数目的同步计数器,只有当同步计数器为0,主线程才会向下执行

主要方法:void await()//当前线程等待计数器为0 
boolean await(long timeout, TimeUnit unit)//与上面的方法不同,它加了一个时间限制。
              void countDown()//计数器减1
              long getCount()//获取计数器的值

3.它的内部有一个辅助的内部类:sync.

  它的实现如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

/**

     * Synchronization control For CountDownLatch.

     * Uses AQS state to represent count.

     */

    private static final class Sync extends AbstractQueuedSynchronizer {

        private static final long serialVersionUID = 4982264981922014374L;

 

        Sync(int count) {

            setState(count);

        }

 

        int getCount() {

            return getState();

        }

 

        protected int tryAcquireShared(int acquires) {

            return (getState() == 0) ? 1 : -1;

        }

 

        protected boolean tryReleaseShared(int releases) {

            // Decrement count; signal when transition to zero

            for (;;) {

                int c = getState();

                if (c == 0)

                    return false;

                int nextc = c-1;

                if (compareAndSetState(c, nextc))

                    return nextc == 0;

            }

        }

    }

4.await()方法的实现
 
sync.acquireSharedInterruptibly(1);
     -->if (tryAcquireShared(arg) < 0)//
调用3中的tryAcquireShared()方法
            doAcquireSharedInterruptibly(arg);//
加入到等待队列中
5.countDown()方法的实现
 
sync.releaseShared(1);
     --> if (tryReleaseShared(arg))//
调用3中的tryReleaseShared()方法
               doReleaseShared();//
解锁

 

 

 

 

 

 

 

你可能感兴趣的:(开发常见问题)