@author StormMa
@date 2017-01-22
生命不息,奋斗不止!
异常类型:
NullPointerException
问题描述
一个简单的表单提交,提交到后台绑定到model上,做业务逻辑处理,但是就在controller处理的时候,不幸发生了,NullPointerException,找了很久,检查来检查去,就是找不到哪有空指针。
前台传递数据
Model
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
/**
* @author StormMa
* Created by StormMa 2017/1/17.
*/
@Entity
public class Server implements Serializable{
//服务器id
@Id
@GeneratedValue
private Integer id;
//远程服务器ip
private String destIp;
//远程服务器登陆名
private String destLoginname;
//远程服务器登陆密码
private String destPassword;
//远程服务器的类型
private String destType;
//远程登陆端口
private Integer destPort = 22;
//一对多的映射
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "server_id")
private List<ServerInfo> serverInfos;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDestIp() {
return destIp;
}
public void setDestIp(String destIp) {
this.destIp = destIp;
}
public String getDestLoginname() {
return destLoginname;
}
public void setDestLoginname(String destLoginname) {
this.destLoginname = destLoginname;
}
public String getDestPassword() {
return destPassword;
}
public void setDestPassword(String destPassword) {
this.destPassword = destPassword;
}
public String getDestType() {
return destType;
}
public void setDestType(String destType) {
this.destType = destType;
}
public Integer getDestPort() {
return destPort;
}
public void setDestPort(Integer destPort) {
this.destPort = destPort;
}
public List<ServerInfo> getServerInfos() {
return serverInfos;
}
public void setServerInfos(List<ServerInfo> serverInfos) {
this.serverInfos = serverInfos;
}
@Override
public String toString() {
return "Server[id: " + id + ", destIp: " + destIp +
", destLoginname: " + destLoginname + ", destPassword: "
+ destPassword + ", destType: " + destType + ", destPort"
+ destPort + " " + this.getServerInfos().toString() + " ]";
}
}
controller处理
ExecuteShell.executeShell方法
/**
* 连接serevr执行命令
*
* @param server
*
* @return
*/
public Server executeShell(Server server)
throws CreateSessionFailedException, ConnectSessionFailedException {
logger.info("当前执行脚本的服务器: " + server);
ArrayList<String> stdout = new ArrayList<String>();
Session session;
ChannelExec channel;
try {
session = jSchUtil.createSession(server.getDestIp(), server.getDestLoginname(), server.getDestPassword
(), server.getDestPort());
//if create session failed
if (session == null) {
throw new CreateSessionFailedException("Create session failed! maybe loginname or password == null! "
+ "please check out it! ");
}
session.connect(10000);
channel = (ChannelExec) jSchUtil.openChannel(session, "exec");
channel.setCommand(commands);
channel.connect();
BufferedReader bufferedReader = new
BufferedReader(new InputStreamReader(channel.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
stdout.add(line);
}
logger.info("执行脚本获得的结果是: " + StringUtils.join(stdout, "\r\n"));
bufferedReader.close();
channel.disconnect();
session.disconnect();
} catch (JSchException e) {
//connect timed out maybe loginname or password is incorrent
logger.error("connect session failed !" + e.toString());
throw new ConnectSessionFailedException("connect timed out! maybe loginname or password is incorrent! "
+ "please check out it!");
} catch (IOException e) {
throw new RuntimeException(e);
}
return handleDataUtil.handleData(server, stdout);
}
发现问题
刚开始一直以为是server没有绑定上数据造成的空指针,但是事实并不是,最后实在想不出来什么问题,打个断点,走了一遍,发现executeShell这个方法抛的空指针,然后继续F5跳进去一看,log日志打印那出问题了,继续F5,原来是调用server.toString()时候出问题了。原因很简单,前台传的数据里面并没有serverInfos这个字段,这个字段是执行shell脚本时候获得的!问题解决,之前debug时候从来不用断点调试,感觉太麻烦,这次要不是断点发现问题根源,还不知道要调到什么时候,长见识了!