㈠ java 命令行交互输入库 JLine 入门
软件的用户界面通常分为两种:GUI(图形用户界面)和CLI(命令行用户界面)。对于经常使用linux的人来说,命令行界面非常熟悉,无论是Shell中的命令输入界面,还是像GDB这样的软件内部交互界面。当开发自己的软件时,编写一个CLI变得困难,因为好的命令行界面需要支持额外的常见功能。
一个合格的命令行软件界面应具备以下三个功能:
这些功能是GNU Readline的一部分。使用库而非手写功能可以简化开发,因为众多GNU/Linux软件采用GNU Readline,使其成为事实上的命令行交互标准。GNU Readline是C语言库,使用其他语言时,需要依赖封装了底层GNU Readline的库,Java语言中的JLine就是这样一种库。
本文将通过一个例子介绍JLine3的基本用法。JLine3没有提供标准示例,其wiki文档也相对简略。示例程序Example.java较为复杂,难以理解。本文旨在帮助理解JLine3的用法。
我们为软件Fog设计命令行用户界面,用户可以输入四种命令。首先,使用JLine3搭建基础的REPL(Read-Eval-Print Loop)框架。
框架包含设置命令提示符(prompt)和原样打印用户输入的功能。当用户输入Ctrl+D(End of line)时,程序退出。此时,程序已经具备JLine3默认提供的命令历史和行编辑功能。使用上、下方向键显示上一条/下一条命令,或使用Ctrl+A、Ctrl+E等Emacs快捷键进行行内编辑。
由于命令补全与程序命令格式紧密相关,我们需自定义补全方式。JLine3中定义命令补全的常见方式是创建Completer类的实例,将其传递给LineReader。JLine3内置多个Completer,如FileNameCompleter(补全文件名)和StringsCompleter(根据预定义字符串补全命令名或参数名)。例如,Fog程序的四个命令以CREATE、OPEN、WRITE、CLOSE开头,使用StringsCompleter对命令第一个单词进行补全。
然而,简单补全仅支持命令的第一个单词补全。若需在命令的任意位置补全,需使用复合补全。复合补全由多个Completer组成,每个Completer负责补全命令中的一个单词。ArgumentCompleter是补全整条命令的复合补全方式。以CREATE命令为例,该命令有两条补全需求:第一个单词需要字符串补全,第二个单词需要文件名补全。我们通过ArgumentCompleter将StringsCompleter和FileNameCompleter组合起来,以实现完整补全。
在实测中发现一个问题:当你输入CREATE和文件名后,试图进行补全,在第三个单词处补全时,仍会出现文件名补全。这是因为ArgumentCompleter在使用完所有Completer后,默认使用最后一个Completer。为解决此问题,添加NullCompleter。这确保从第三个单词开始,不会进行多余的补全。
类似地,我们加入OPEN命令的补全定义。
WRITE命令的补全需考虑程序语义。只有在OPEN命令中定义的文件变量,才能在WRITE命令中使用。因此,在补全时需要动态调整补全候选词。在运行时修改补全候选词,实现动态补全功能。通过继承并重写Completer类的complete()方法实现动态候选词调整。
当调用setFileVars()方法时,会创建新的StringsCompleter并扩充候选词。在REPL中,只需在用户输入OPEN命令后调用setFileVars()方法。
默认情况下,JLine3支持命令历史查找功能。为了去除干扰,避免将注释内容加入命令历史,我们继承并重写History类的add()方法,过滤注释内容。然后设置LineReader以实现此功能。
本文示例程序完整代码见jline3-demo。
JLine3功能设计清晰,提供了对应的接口和默认实现。若需自定义特性,通常可通过继承并重写实现。JLine3源代码易于理解,遇到问题时,可阅读源代码寻找解决方案。
㈡ 有没有开源的java制作的类似“百科”或者“维基”的组件
jspWiki 是一套非常容易安装的系统,使用到JSP与Servlet技术。
DevWiki是一个把页面存储在CVS中的Wiki引擎。
Chiki 点击次数:944
基于Struts的Wiki系统。
SnipSnap 是一个基于java的wiki + WebLog
FITNesse是一个 基于FIT的测试环境,. 它内建Wiki服务器,简单易用。
Friki部署简单,非常小只有67k
XWiki是一个强大的Java开源的Wiki引擎。它支持一些受欢迎的特性如:
* 内容管理(浏览/编辑/预览/保存),
* 支持附件,
* 版本控制,
* 全文本搜索,
* 权限管理
* 使用Hibernate进行数据存储,
* RSS输出与显示外部的RSS feeds,
* 多语言支持,
* 提供XML/RPC的API,
* WYSIWYG HTML编辑器,
* 导出为PDF
* Groovy脚本支持等等....。
ButorWiki这是一个基于java的Wiki,它是一个web应用程序,使用Butor Java 框架与struts MVC 框架。ButorWiki不需要数据库,而是使用文件系统进行数据存储。
Very Quick Wiki是一个JSPs与JavaServlets开发的WikiWiki。在Tomcat或其它容器上安装与运行都很简单。
UseModj这个Wiki引荐运用到Struts框架与Velocity模板。它具有一些新的特性:多语言支持,支持RSS 1.0(rdf),文件/图片的上传与下载,图片大小调整,可以用多种语言命名文件/图片
Platypus Wiki一个Semantic(语义的) Wiki Wiki Web.它提供一个简单的使用基于W3C标准元数据(metadata)的用户接口来创建Wiki页面.Platypus Wiki使用RDF(Resource Description Framework:资源描述框架),RDF Schema和OWL(Web Ontology Language:Web实体语言)来创建实体(Ontology)与管理元数据.
CsaWiki是一个利用Java开发的wiki引擎。它具有以下特点:100%Java(J2EE没有EJB),基于文件没有数据库,版本控制,PDF导出,简单的Wiki sintax等。
Elsie是一个用Java开发的Wiki引擎。它支持大多数流行wiki所应具备的特性包括:简单的wiki markup语法,内容管理(查看, 编辑,附件等...), 版本控制,访问控制列表和用户/组管理,可使用布局模板和CSS来控制外观,一个用于创建公共文档的文档模板,支持I18N和多种语言,搜索等. Elsie实现一个基于IoC的wiki内核并提供一组定义清晰,独立于servlet的wiki API 以便于使整个Wiki易于扩展和可定制。
Corendal Wiki是一个开源并已经被实际公司所使用的Wiki应用软件。它的界面非常简洁;不需要学习wiki语法, 通过使用WYSIWYG在线编辑器来代替;不需要用户管理,它实时连到活动目录(Active Directory)来重复使用用户账号和组,它应该是唯一一个与活动目录组相集成的Wiki,本地账号和组都可以用它来创建;所有的文章都具有一个层次结构,以使得内容易于管理;可以针对每一个页面设置不同的访问权限或自由更新或锁定或发布;用户可以使用订阅机制来获得更新通知,更新可以是每天或每周或立即通知;可以自定义界面布局(使用Velocity模板和CSS实现) 。Corendal Wiki基于Tomcat和MySQL运行。
JAMWiki采用Java/JSP开发的Wiki引擎。它提供许多MediaWiki应具有大部份的功能。JAMWiki不需要数据库支持,数据采用文件系统存储(但)并且易于安装。
㈢ java解决逻辑问题-》“Zebra Puzzle” http://en.wikipedia.org/wiki/Zebra_puzzle
本来以为是很简单的,没想到越写越僵了...总之,我的思路就是不断的尝试,遇到发生矛盾的话就回溯,直到所有的条件都满足,下面贴的代码在main方法中调用ZebraPuzzle的方法创建题目中的条件,最后打印出推导出来的表格,有了表格就什么信息都有了。当然可能还有(几乎是肯定有)很多漏洞,因为一个测试例子是不足以检测所有逻辑的。。。另外这里也没有包括纠错的逻辑,比如如果题目本身是矛盾的话,我就不知道会发生什么了。。。
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String[] args) {
String[] attributeName =
{ "Color", "Nationality", "Drink", "Cigarette", "Pet" };
ZebraPuzzle puzzle = new ZebraPuzzle(5, attributeName);
puzzle.bindCondition("Nationality", "ENG", "Color", "Red");
puzzle.bindCondition("Nationality", "ESP", "Pet", "Dog");
puzzle.bindCondition("Drink", "Coffee", "Color", "Green");
puzzle.bindCondition("Nationality", "UKR", "Drink", "Tea");
puzzle.bindNeighbour("Color", "Ivory", "Color", "Green", true);
puzzle.bindCondition("Cigarette", "OldGold", "Pet", "Snail");
puzzle.bindCondition("Cigarette", "Kool", "Color", "Yellow");
puzzle.bindOrdinal("Drink", "Milk", 3);
puzzle.bindOrdinal("Nationality", "NOW", 1);
puzzle.bindNeighbour("Cigarette", "Chester", "Pet", "Fox", false);
puzzle.bindNeighbour("Cigarette", "Kool", "Pet", "Horse", false);
puzzle.bindCondition("Cigarette", "Lucky", "Drink", "Juice");
puzzle.bindCondition("Nationality", "JPN", "Cigarette", "Parliament");
puzzle.bindNeighbour("Nationality", "NOW", "Color", "Blue", false);
boolean result = puzzle.solve();
System.out.println(result);
puzzle.printTable();
}
}
class ZebraPuzzle {
private List<Fact> conditions;
private String[] attributes;
private Unit[] units;
public ZebraPuzzle(int n, String[] attrs) {
attributes = attrs;
conditions = new ArrayList<Fact>();
units = new Unit[n];
for (int i = 0; i < n; ++i) {
units[i] = new Unit(i+1, attributes);
}
}
public void bindCondition(String type1, String attr1, String type2, String attr2) {
conditions.add(new BinderFact(type1, attr1, type2, attr2));
}
public void bindNeighbour(String type1, String attr1, String type2,
String attr2, boolean sideSensitive) {
if (sideSensitive) {
conditions.add(new SideSensitiveNeighbourFact(type1, attr1, type2, attr2));
} else {
conditions.add(new NeighbourFact(type1, attr1, type2, attr2));
}
}
public void bindOrdinal(String type, String attr, int ordinal) {
conditions.add(new OrdinalFact(type, attr, ordinal));
}
public boolean solve() {
applyOrdinalFact();
applyDeterministicFactor();
return solve(0);
}
private boolean solve(int depth) {
if (depth == conditions.size()) {
return true;
}
Fact fact = conditions.get(depth);
List<PossibleFact> possibles = fact.getPossibleFacts(units);
if (possibles.size() == 0) {
return false;
}
for (PossibleFact pf : possibles) {
pf.apply(units);
if (solve(depth + 1)) {
return true;
}
pf.cancel(units);
}
return false;
}
private void directApply(OrdinalFact fact) {
units[fact.ordinal-1].setOrdinalFact(fact);
}
private void applyOrdinalFact() {
Iterator<Fact> iter = conditions.iterator();
while (iter.hasNext()) {
Fact fact = iter.next();
if (fact instanceof OrdinalFact) {
directApply((OrdinalFact) fact);
iter.remove();
}
}
}
private void applyDeterministicFactor() {
boolean modified;
while (!conditions.isEmpty()) {
modified = false;
Iterator<Fact> iter = conditions.iterator();
while (iter.hasNext()) {
Fact fact = iter.next();
if (fact.tryApply(units)) {
iter.remove();
modified = true;
}
}
if (!modified) {
break;
}
}
}
public void printTable() {
System.out.print("\t\t");
for (String attribute : attributes) {
System.out.printf("%s\t\t", attribute);
}
System.out.print("\n");
for (Unit unit : units) {
System.out.printf("%d\t\t", unit.ordinal);
for (String attribute : attributes) {
System.out.printf("%s\t\t", unit.getAttribute(attribute));
}
System.out.print("\n");
}
System.out.println();
}
}
enum AttributeState { UNKNOWN, DIFFERENT, SELF }
class Unit {
Unit(int ordinal, String[] attributes) {
this.ordinal = ordinal;
map = new HashMap<String, String>();
for (String attr : attributes) {
map.put(attr, Fact.UNKNOWN);
}
}
void setOrdinalFact(OrdinalFact fact) {
map.put(fact.type, fact.attribute);
}
void setAttribute(String type, String attribute) {
map.put(type, attribute);
}
boolean containsAttribute(String type, String attribute) {
return attribute.equals(map.get(type));
}
boolean containsDifferentOne(String type, String attribute) {
String s = map.get(type);
return s != Fact.UNKNOWN && !s.equals(attribute);
}
AttributeState consultAttribute(String type, String attribute) {
String s = map.get(type);
if (s == Fact.UNKNOWN) {
return AttributeState.UNKNOWN;
}
if (s.equals(attribute)) {
return AttributeState.SELF;
}
return AttributeState.DIFFERENT;
}
Unit getRightUnit(Unit[] units) {
if (ordinal == units.length) {
return null;
}
return units[ordinal];
}
String getAttribute(String attributeName) {
return map.get(attributeName);
}
Map<String, String> map;
int ordinal;
}
interface Fact {
static final String UNKNOWN = "Unknown";
public List<PossibleFact> getPossibleFacts(Unit[] units);
public boolean tryApply(Unit[] units);
}
interface PossibleFact {
public void apply(Unit[] units);
public void cancel(Unit[] units);
}
abstract class AbstractFact implements Fact {
public boolean tryApply(Unit[] units) {
return false;
}
protected Unit findOwner(Unit[] units, String type, String attribute) {
for (Unit unit : units) {
if (unit.containsAttribute(type, attribute)) {
return unit;
}
}
return null;
}
public List<PossibleFact> getPossibleFacts(Unit[] units) {
return Collections.emptyList();
}
}
class BinderFact extends AbstractFact {
String type1, attribute1;
String type2, attribute2;
BinderFact(String t1, String attr1, String t2, String attr2) {
type1 = t1;
attribute1 = attr1;
type2 = t2;
attribute2 = attr2;
}
public boolean tryApply(Unit[] units) {
Unit unit = super.findOwner(units, type1, attribute1);
if (unit != null) {
return tryApply(unit, type2, attribute2);
}
unit = super.findOwner(units, type2, attribute2);
if (unit != null) {
return tryApply(unit, type1, attribute1);
}
return false;
}
protected boolean tryApply(Unit unit, String type, String attribute) {
if (unit.containsDifferentOne(type, attribute)) {
throw new RuntimeException();
}
unit.setAttribute(type, attribute);
return true;
}
public List<PossibleFact> getPossibleFacts(Unit[] units) {
List<PossibleFact> list = new ArrayList<PossibleFact>();
for (Unit unit : units) {
AttributeState as1 = unit.consultAttribute(type1, attribute1), as2 = unit.consultAttribute(type2, attribute2);
if (as1 != AttributeState.DIFFERENT && as2 != AttributeState.DIFFERENT) {
list.add(new PossiblebBinderFact(unit.ordinal, this,
as1 == AttributeState.UNKNOWN,
as2 == AttributeState.UNKNOWN
));
}
}
return list;
}
private static class PossiblebBinderFact implements PossibleFact {
BinderFact fact;
boolean firstNew, secondNew;
int n;
PossiblebBinderFact(int n, BinderFact fact, boolean fn, boolean sn) {
this.fact = fact;
firstNew = fn;
secondNew = sn;
this.n = n;
}
public void apply(Unit[] units) {
if (firstNew) {
units[n-1].setAttribute(fact.type1, fact.attribute1);
}
if (secondNew) {
units[n-1].setAttribute(fact.type2, fact.attribute2);
}
}
public void cancel(Unit[] units) {
if (firstNew) {
units[n-1].setAttribute(fact.type1, Fact.UNKNOWN);
}
if (secondNew) {
units[n-1].setAttribute(fact.type2, Fact.UNKNOWN);
}
}
}
}
class NeighbourFact extends BinderFact {
NeighbourFact(String t1, String attr1, String t2, String attr2) {
super(t1, attr1, t2, attr2);
}
public boolean tryApply(Unit[] units) {
if (tryApply(units, type1, attribute1, type2, attribute2)) {
return true;
}
if (tryApply(units, type2, attribute2, type1, attribute1)) {
return true;
}
return false;
}
protected boolean tryApply(Unit[] units, String t1, String attr1,
String t2, String attr2) {
Unit unit = super.findOwner(units, t1, attr1);
if (unit == null) {
return false;
}
Unit right = unit.getRightUnit(units);
if (right == null) {
return false;
}
return super.tryApply(right, t2, attr2);
}
public List<PossibleFact> getPossibleFacts(Unit[] units) {
List<PossibleFact> list = new ArrayList<PossibleFact>();
getPossibleFacts(units, list, type1, attribute1, type2, attribute2);
getPossibleFacts(units, list, type2, attribute2, type1, attribute1);
return list;
}
protected void getPossibleFacts(Unit[] units, List<PossibleFact> list,
String t1, String attr1, String t2, String attr2) {
for (int i = 0; i < units.length - 1; ++i) {
Unit unit1 = units[i], unit2 = units[i + 1];
AttributeState as1 = unit1.consultAttribute(t1, attr1), as2 = unit2.consultAttribute(t2, attr2);
if (as1 != AttributeState.DIFFERENT && as2 != AttributeState.DIFFERENT) {
list.add(new PossibleNeighbourFact(t1, attr1, t2, attr2,
i, i+1, as1 == AttributeState.UNKNOWN,
as2 == AttributeState.UNKNOWN
));
}
}
}
private static class PossibleNeighbourFact implements PossibleFact {
String type1, attribute1, type2, attribute2;
boolean firstNew, secondNew;
int n1, n2;
PossibleNeighbourFact(String t1, String a1, String t2, String a2,
int n1, int n2, boolean fn, boolean sn) {
type1 = t1;
attribute1 = a1;
type2 = t2;
attribute2 = a2;
firstNew = fn;
secondNew = sn;
this.n1 = n1;
this.n2 = n2;
}
public void apply(Unit[] units) {
if (firstNew) {
units[n1].setAttribute(type1, attribute1);
}
if (secondNew) {
units[n2].setAttribute(type2, attribute2);
}
}
public void cancel(Unit[] units) {
if (firstNew) {
units[n1].setAttribute(type1, Fact.UNKNOWN);
}
if (secondNew) {
units[n2].setAttribute(type2, Fact.UNKNOWN);
}
}
}
}
class SideSensitiveNeighbourFact extends NeighbourFact {
SideSensitiveNeighbourFact(String t1, String attr1, String t2, String attr2) {
super(t1, attr1, t2, attr2);
}
public boolean tryApply(Unit[] units) {
return super.tryApply(units, type1, attribute1, type2, attribute2);
}
public List<PossibleFact> getPossibleFacts(Unit[] units) {
List<PossibleFact> list = new ArrayList<PossibleFact>();
getPossibleFacts(units, list, type1, attribute1, type2, attribute2);
return list;
}
}
class OrdinalFact extends AbstractFact {
String type, attribute;
int ordinal;
OrdinalFact(String t, String attr, int ord) {
type = t;
attribute = attr;
ordinal = ord;
}
}
㈣ 请问有没有好些的java编写的开源论坛代码,最好是近期的产品
mvnForum
mvnForum是基于javaJ2EE 技术(Jsp/Servlet)的一个开源论坛.,安装简单。mvnForum兼容任何Servlet容器,支持Jsp 1.2 and Servlet 2.3。
更多mvnForum信息
JForum
JForum 是一个功能强大 ,易于管理的论坛。它的设计完全遵从MVC设计模式,能够在任何Servlet容器与EJB服务器上运行。而且可以轻松的定制与扩展JForum论坛。
更多JForum信息
xforum
国人开发的一个开源论坛,基于 Struts 技术,是学习 Struts 的一个非常好的范例。它用到 JAAS 实现 Security ,中文问题的解决,数据层用到 DAO ,以及基于 Struts 应用的基本架构,都是个非常好的学习。
更多xforum信息
jGossip
jGossip是一个简单,功能强大的java论坛。可运用j2EE在平台上。采用Struts framework技术。
更多jGossip信息
FreeForums
一个基于XML的Java2企业级的论坛解决方案。FreeForums页面采用CSS, DHTML 与JavaScript等技术。这样用户可以定制自已喜欢的界面。它还提供一个在Windows下的客户端程序。
更多FreeForums信息
Sk Forum
SK Forum是一个开源的基于web的J2EE论坛应用程序。它是一个功能比较齐全的系统,包括很多功能比如:投票,wiki,定时跟踪,地址薄,好友薄以及其它一些小的功能。
更多Sk Forum信息
JsForum
JsForum是只用到jsp与Servlet技术的论坛,容易使用。具有一般论坛的功能。但是目前只能支持MYSQL数据库。
更多JsForum信息
nemesis-forum
一个使用J2EE技术的论坛。它的功能包括用户与用户组权限管理,支持i18n,内容过滤,综合搜索引擎,支持多种数据库。
更多nemesis-forum信息
Yazd
Yazd是一个使用JDBC连接数据库的论坛。它的特性包括:
1.提供在线安装和配置。
2.内容过滤(把Html代码转换成可显示的文件,自定义关键字过滤列表,隐藏urls的实现路径)。
3.集成Lucene1.3提供关键字搜索功能。
4.支持的数据库包括:Oracle,MySQL,DB2,Microsoft SQLServer,Sybase,Interbase,Hypersonic SQL,Pointbase,Informix和Postgres
5.还有其它一些一个论坛应具备的基本功能。
这个论坛提供多语言支持其中包括简体中文。
更多Yazd信息
JavaBB
JavaBB基于java技术的类似于phpbb的论坛。
更多JavaBB信息
JForumFusion
JForumFusion是一个Java开源论坛。它主要的一些功能包括常规论坛功能,文件附件上传,个人信息,基于web的管理工具,UBBCode,和高性能的搜索引擎等。支持主流数据库包括:Oracle, DB2, MySQL, PostgreSQL, Sybase, SAP DB, HypersonicSQL, Microsoft SQL Server...
更多JForumFusion信息
jzForum
这是一个利用Java开发的简单论坛.以下列出它的几点特性:
* 完全支持BBCode,
* 在新贴提交时利用AJAX技术提供无刷新页面预览功能.
* 利用lucene提供全文本搜索功能.
* 用户可监控主题.
* 可以容易更改样式(利用CSS几乎没有用到table).
* 安装简单只有一个war文件没有数据库(其实是内嵌hypersonic数据库)但 也支持其它数据库.
* 包括一个投票系统.
* jzForum还提供RSS阅读功能并利用缓存技术提高整个论坛的速度.
更多jzForum信息
BBS-CS
天乙社区是一套基于JAVA技术的网络虚拟社区,采用了Hibernate+Spring+Struts的轻量级J2EE框架.
1、全文检索:天乙社区6.0采用Lucene全文检索,并支持完全国际化多语言的全文检索。
2、MVC框架:天乙社区6.0继续了5.x的Struts框架,但经过优化,WEB端更加简洁高效。
3、集群支持:系统可以运行在集群上。
4、功能方面:大大加强了管理功能,用户可以多样化的定制系统的各项信息,包括用户级别、封锁IP、过滤字等等,论坛功能上主要增加了投票帖、上传附件类型多样、帖子中显示用户信息等等功能等。
更多BBS-CS信息
EasyJF
简易java框架开源论坛系统拥有常用论坛系统的基本功能,集前台后台代码为一体,支持UBB。该论坛系统使用基于OO的方法设计,采用多层B/S构架,数据库持久层主要使用简易数据库开源框架EasyDBO,Web层使用EasyJWeb框架,java代码与页面完全分离,易扩展。
更多EasyJF信息
参见:http://www.open-open.com/09.htm
㈤ 如何安装配置JIRA和CONFLUENCE WIKI
JIRA的安装
1.java安装和设置JAVA_HOME
首先下载到sun官网下载jdk-6u20-linux-i586.bin(版本根据实际决定)。linux下可以使用wget命令。由于url忘记了,详细命令不写了。由于我们的开发服务器不在本地,我只能通过wget下载。(当然还有很多别的方法,见下文)我先把jdk-6u20-linux-i586.bin下载到/home/acm,然后执行sh自解压脚本
sh jdk-6u20-linux-i586.bin
yes人家的相关条款。如果顺利的话,当前目录会多一个jdk1.6.0_20。将该目录移动到/usr/local/,并改为名java。
设置环境变量JAVA_HOME
这一步有很多方法,修改各种配置文件中的一个。我采取的方法是
vi /etc/profile
在文件后面两行加上
export JAVA_HOME=/usr/local/java
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
export JIRA_HOME=/usr/local/jira/
后面一行加粗的是后面配置JIRA_HOME时候加上去的www.linuxidc.com(可选,因为JIRA本身有配置文件配置这个路径)。
修改完了配置文件,echo $JAVA_HOME一下必定得到空值。因为配置文件还没有生效,最简单的方法是 source一下
source /etc/profile
这个时候echo $JAVA_HOME 就会圆满了。
[root@dev ~]# echo $JAVA_HOME
/usr/local/java
不放心的话也可以验证一下其他路径。可以输入
java -version
看看是否得到如下结果:
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Server VM (build 16.3-b01, mixed mode)
顺便提一句,我之前在安装CentOS时候,选安装了gcj,
rpm -aq|grep gcj
出来一堆东东。效果给不了了,因为写blog之前已经执行了如下命令
yum -y remove java-1.4*
删除gcj,JIRA官网说仅有这个的话。JIRA是不会正常工作的,常常会发生一些莫名其妙的bug。为了避免一起混乱,我首先删除之。