记录我一天的debug之路

本文介绍了一个关于表单提交导致的NullPointerException问题排查过程。通过详细分析Controller层代码及使用断点调试,最终定位到问题所在并成功解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@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时候从来不用断点调试,感觉太麻烦,这次要不是断点发现问题根源,还不知道要调到什么时候,长见识了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值