noHup - java
type: channel
link: http://www.nohup.cc/tag/java/
items: Java后台获取客户端ip地址的注意事项
items: PhosphoPrediction项目总结
items: Java程序调用Shell命令及脚本文件
items: The First Step To Use Weka
items: Java处理文件名加时间戳
items: 关于日志部分的简单介绍
items: Maven中自动生成关于项目站点的一些坑

Java后台获取客户端ip地址的注意事项
type: item
date: 2016-07-23T13:09:00+00:00
description: Overview1.修改hosts文件2.设置eclipse Overview 前面讲到，消息队列需要用到客户端的ip地址和时间戳，获取客户端的ip地址就需要下面几行简单的代码。 import javax.servlet.http.HttpServletRequest; HttpServletRequest request = ServletActionContext.getRequest(); String ipAddress = request.getHeader("X-FORWARDED-FOR"); if (ipAddress == null) { ipAddress = request.getRemoteAddr(); } System.out.println(ipAddress); 我将上面几行代码，放入之前的PhosphoPredict项目的action中做实验，结果显示如下： 0:0:0:0:0:0:0:1 这和我们平时的认知不同，下面就是解决办法。 1.修改hosts文件 我在ubuntu14.04系统下，打开/etc/hosts文件，看到如下信息： # Localhost 127.0.0.1 localhost 127.0.0.1 young 255.255.255.255 broadcasthost ::1 localhost fe80::1%lo0 localhost 我们将 ::1 localhost 这句注释掉，再提交， 127.0.0.1 正确答案就出现了。 其他系统，请自行查找文件目录并修改。 2.设置eclipse 我们在eclipse运行本程序的时候，可以配置一下运行参数： 依次点击Run→Run Configurations…→Apache Tomcat→Tomcat v7.0 Server at localhost,这时候点击右边的Arguments，在下面的VM arguments框中加上一句： -Djava.net.preferIPv4Stack=true 最后点击Apply。然后就可以了。 总结：这是因为，只有在本机提交的时候，才会出现，客户端提交就会显示真实ip地址了。而系统会优先显示ipv6格式的本机ip。我们两种方法，第一种是屏蔽掉ipv6的表示方法，第二种则是指定优先ipv4表示。 两种方法更推荐第二种。 这篇文章主要参考了stackoverflow.

PhosphoPrediction项目总结
type: item
date: 2015-11-14T02:53:00+00:00
description: Overview1.Java web服务器实现的功能1.1 前端接收序列传入后台1.2 后台处理序列，并展示在jsp页面1.3 jsp页面同时添加导出结果按钮2.需要注意的地方2.1 struts.xml文件配置2.2 action之间传值2.3 处理输入的序列2.4 初始化问题 Overview PhosphoPrediction项目是Chris和我做的一个新项目，主要是为本地客户端程序添加一个相同功能的web server。由于出差新疆，只能晚上回酒店自己加班写代码，在Chris的帮助下，前前后后忙了大约两周总算有了个不错的小成果，心中颇感欣慰。这段时间，Chris不仅给了我技术上的指导，更给我排解了心中的许多烦恼，在此感谢我最好的朋友Chris(我知道你不喜欢我当面夸奖感谢你，哈哈)。 1.Java web服务器实现的功能 1.1 前端接收序列传入后台 很多类似的项目一次只能接收一条序列，本项目可以同时接收多条序列，包含名字的FASTA格式的序列和不包含名字的raw序列。在webserver界面可以选择model，默认为ATM；同时可以选择threshold，默认全部显示。 1.2 后台处理序列，并展示在jsp页面 后台共接收3个参数，即seqString、model、threshold，并生成getters和setters。 private String seqString; private String model; private double threshold; public String getSeqString() { return seqString; } public void setSeqString(String seqString) { this.seqString = seqString; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public double getThreshold() { return threshold; } public void setThreshold(double threshold) { this.threshold = threshold; } 我们在前端得到的threshold，仅仅是double类型的value，我们处理成String类型并展示在result界面。我们可以根据选择的阈值threshold，展示我们所需要的结果。为此，我们将处理result的模块剥离出来，放在formatResults.java类中。该类提供两个方法，是重载关系，唯一的区别是传入的参数threshold。 //不包含threshold的方法，得到全部的sites对应的results public ArrayList getFormatResults(String originSeqString, String model) { RemoteWork robot = new RemoteWork(); ArrayList results = robot.formatInput(originSeqString); ArrayList allResults = new ArrayList<>(); String seq_name=""; String seq=""; int input_count=1; String input_replace=""; Result res; for(int i=0; i<results.size(); i++){ res=results.get(i); if(res.getName().substring(0, 5).equals("input")) { input_replace = "-" + input_count; res.setName(res.getName().replaceAll("-input", input_replace)+" *"); input_count++; } seq_name = res.getName(); seq = res.getSeq(); res.setDiso(robot.runDiso(seq)); res.setSs(robot.runSable_ss(seq)); res.setSa(robot.runSable_sa(seq)); robot.getFunc(seq_name); res.setSites(robot.Predict(seq, model, seq_name)); allResults.add(res); } ret…

Java程序调用Shell命令及脚本文件
type: item
date: 2015-08-28T08:14:00+00:00
description: Overview1.直接运行Shell命令2.执行Shell脚本文件 Overview 最近需要用到数个Python程序处理蛋白质序列以输出特征值，而这些Python文件需要在Shell脚本中传入文本文件（该文本文件记录了某些蛋白质序列）做参数，进而依次被Shell调用。我们在Java程序中建立Shell脚本的运行时环境Runtime，这其中用到了一个类，即java.lang.Runtime，下面对该类进行探讨和记录。 1.直接运行Shell命令 java.lang.Runtime类有一个特点，官方文档说明如下： Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method. An application cannot create its own instance of this class. 大意就是：Java程序不能实例化(所以也没有构造方法)，如需获取当前的运行环境只能通过无参的getRuntime()方法，该方法返回值为Runtime，进而使用它的exec(String command)或者exec(String[] cmdarray)，返回一个Process。代码如下： Process process; List<String> processList = new ArrayList<String>(); try { process = Runtime.getRuntime().exec(“pwd”); BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = input.readLine()) != null) { processList.add(line); } input.close(); } catch (IOException e) { e.printStackTrace(); } for (String line : processList) { System.out.println(line); } "pwd"命令运用之后，帮助我们得到当前的工作目录为/root，从而为下一步执行Shell脚本文件也提供了有利条件。 2.执行Shell脚本文件 Runtime的exec()方法还有另外一种重载形式exec(String[] cmdarray, String[] envp, File dir)，其作用更为强大，开发人员可以将命令全部写入脚本文件，使得命令连续执行，而且可以指定脚本文件的工作目录。 public void read(String str) throws NullPointerException{ String command = "/bin/bash" + " " + ServletActionContext.getServletContext().getRealPath("/") + "useful_scripts/feature_calc.sh"+" "+str; File dir = new File(ServletActionContext.getServletContext().getRealPath("/") + "useful_scripts"); System.out.println(command);//测试command命令 Process process; List<String> processList = new ArrayList<String>(); try { process = Runtime.getRuntime().exec(command, null, dir);//环境变量通常为null，表明使用当前环境。 BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = input.readLine()) != null) { processList.add(line); } input.close(…

The First Step To Use Weka
type: item
date: 2015-08-13T02:57:00+00:00
description: Overview Weka is easy to use when we do feature selection and classification. Using Weka's friendly graphic user interface, we can try and validate multiple feature selection methods and classifiers that have already been implemented into Weka. This article tries to give a quick start guide about this wonderful tool. 1. Download Weka 1.1 About different versions You can download Weka with different versions from Weka's Download page. There are Stable book 3rd ed. version(3.6.12) and Developer version(3.7.12+) available. Stable book 3rd ed. version is a stable version for use. If this version can meet all your demands or you don't know what functions you need, use this one. Compared to the former versions of Weka, Developer version(3.7.12+) adopts a new architecture, which provides a package manager in the tool menu. Unlike that Stable book 3rd ed. version(3.6.12) provides all the methods and classifier it can, Developer version(3.7.12+) only provides a series of basic methods and classifiers in default, however, with a new-developed package manager. If you want some classifier, open the package manager and download this classifier, then you can use it in Weka. Taking feature selection as an instance, we want to use mRMR method to select features. Fortunately, mRMR is involved in weka at version 3.5.15. We don't need to update a new version since we only need this function. Open the package manager in the existing 3.7.12 version, we can easily download and use it. 1.2 For users in different platforms Weka provides a series of versions that can run on Windows, Mac and other platforms(a zip file). For Windows and Mac users, you can directly download the corresponding version, install it and use it. However, I recommend you to download a zip version to use. When you wanna use SVM classifier in Weka 3.6.12, you will need the zip version. (How to involve libSVM in weka 3.6.12 will be depicted in another article) 2. Use Weka If you download the non-zip version, I guess you…

Java处理文件名加时间戳
type: item
date: 2015-08-09T14:24:00+00:00
description: Overview1.FileTimeStamp获取包含时间戳的文件名2.建立一个调用FileTimeStamp类的FileFullName类 Overview 第一个项目中，输入框内的sequence传入后台，并在Action中用String类型的seq接收，继而处理成txt文件形式保存。由于以后的项目均要频繁使用io以及这种中间处理方式，故在参考了前人的类似处理方法之后，提取出适合本项目的Java类FileTimeStamp。 该Java类负责以“sequence_input_时间戳”的形式命名文本文件。以下便是该处理类的代码，而参考资料也会在最后给出，以尊重原作者。 1.FileTimeStamp获取包含时间戳的文件名 import java.text.SimpleDateFormat; import java.util.Date; public class FileTimeStamp { private SimpleDateFormat sdf = null; //获取时间戳 public String getTimeStamp(){ sdf = new SimpleDateFormat("yyyyMMddHHmmssZ"); String timeStamp = sdf.format(new Date()); return timeStamp; } //获取添加了时间戳和扩展名的文件名 //并将StringBuffer类型的buf转换为字符串 //于是便得到完整的文件名 public String getTimeName(){ StringBuffer buf = new StringBuffer("sequence_input_"); buf.append(this.getTimeStamp()).append(".txt"); return buf.toString(); } } 2.建立一个调用FileTimeStamp类的FileFullName类 该类负责产生文件全名，并在后面运用。 package edu.monash.file; public class FileFullName { public String getFullName() { FileTimeStamp fts = new FileTimeStamp(); String fullName = fts.getTimeName(); return fullName; } } 参考资料

关于日志部分的简单介绍
type: item
date: 2015-01-10T07:23:00+00:00
description: Java日志体系概览 关于Java的日志API可以概括为日志记录的封装API和日志记录实现两类。前一种的典型代表是Apache Commons Logging和SLF4J，后一种的典型代表有JDK自带的日志实现（java.util.logging 包，JUL）以及著名的Log4j。日志封装API是为日志使用者提供了一种统一的接口，使用者可以根据需求来切换具体日志实现方案。 Java日志API 一般来说，日志API一般包括： 记录器（Logger）：日志 API 的使用者通过记录器来发出日志记录请求，并提供日志的内容。在记录日志时，需要指定日志的严重性级别。 格式化器（Formatter）：对记录器所记录的文本进行格式化，并添加额外的元数据。 处理器（Handler）：把经过格式化之后的日志记录输出到不同的地方。常见的日志输出目标包括控制台、文件和数据库等。 Java日志封装API 在这主要介绍一下目前使用较多的SLF4J日志库，SLF4J 库中核心的 API 是提供工厂方法的 org.slf4j.LoggerFactory 类和记录日志的 org.slf4j.Logger 接口。通过 LoggerFactory 类的 getLogger 方法来获取日志记录器对象。Logger 接口中的方法也是按照不同的严重性级别来进行分组的。 参考：Java日志最佳实践 Jeesite中Log4j的使用分析 Jeesite中使用了Log4j日志记录作为实现，下面依次分析一下Log4j的配置文件和封装了Log4j的Manager类。 Log4j的配置 Log4j支持使用Java properties和xml作为配置文件。相对于xml的格式，Java properties更易读。下面以Jeesite中的log4j.properties为例，所有配置项均以log4j开头，主要配置项为rootlogger,输出终端，输出布局模式。 log4j.rootLogger=WARN, Console, RollingFile Logger是日志记录器，而rootLogger则是所有Logger的祖先，可以通过Logger.getRootLogger()来获取。 #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n #RollingFile log4j.appender.RollingFile=org.apache.log4j.DailyRollingFileAppender log4j.appender.RollingFile.File=../logs/jeesite.log log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout log4j.appender.RollingFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n Log4j的输出终端，由Appender接口定义。其有多种实现，不同实现就对应则不同的日志输出保存方式。例如： ConsoleAppender(控制台) FileAppender(文件) DailyRollingFileAppender(每天都产生一个日志文件) RollingFileAppender(文件大小达到指定尺寸时产生一个新的日志文件，文件名称上会自动添加数字序号。) WriterAppender(将日志信息以流的格式发送到任意指定的地方) 而所有子类Logger均将继承父类Logger的Appender配置。 至于输出布局模式——由Layout接口定义——也有多种实现： PatternLayout（可以灵活地指定布局模式） HTMLLayout（以HTML表格形式布局） SimpleLayout（包含日志信息的级别和信息字符串） TTCCLayout（包含日志产生的时间、线程、类别等信息） ConversionPattern使用的是类似于C语言中printf的格式化输出参数： %c：输出所属的类目，通常就是所在类的全名。 %d：输出日志时间点的日期或时间，默认格式为ISO8601，推荐使用“%d{ABSOLUTE}” %t：输出产生该日志线程的线程名。 %p：输出优先级。 %m：输出代码中指定的消息。 %n：输出一个回车换行符。Windows平台为“\r\n…

Maven中自动生成关于项目站点的一些坑
type: item
date: 2014-12-26T12:43:00+00:00
description: Overview 主要使用使用Maven自动生成项目站点的一些坑。 List maven-site-plugin 插件需要使用3.3版本，如果使用3.2，由于兼容性问题可能在site阶段报错。 Eclipse中启动mvn site阶段找不到JAVA_HOME： 报错信息如下： Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.9.1:jar (attach-javadocs) on project suppress-warnings: MavenReportException: Error while creating archive: Unable to find javadoc command: The environment variable JAVA_HOME is not correctly set. 已经在本地的配置中设置了JAVA_HOME： export JAVA_HOME=$(/usr/libexec/java_home) 在命令行运行 mvn clean site:site， javadoc 可以找到JAVA_HOME，但是在eclipse中执行maven构建，还是会报一样的错误，这是由于，在本地设置的JAVA_HOME不能被A bundled GUI app like Eclipse识别，需要在全局配置中添加该信息。 找到/etc/launchd.conf文件，如果该目录不存在这个文件，sudo vim launchd.conf创建改文件，必须使用sudo，不然无法写入该文件，添加一行： setenv JAVA_HOME /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home 注意：不能使用 setenv JAVA_HOME $(/usr/libexec/java_home) 这样的小技巧，否则，这里不能识别这种写法。 保存，并重启电脑，配置生效。