JAVA基于Slack实现异常日志报警详解

目录
  • 一、功能介绍
  • 二、Slack介绍
  • 三、前期准备
    • slack配置
    • pom.xml
  • 四、具体实现
    • 1.实现Slack发送消息
      • SlackUtil 给Slack发消息工具类
      • 向 webhook发起请求通过Urlencode
      • SlackUtil测试
    • 2.重写打印日志类
      • 常见异常打日志处理
      • 重写封装打印日志的方法
      • 测试日志类
  • 五、优化扩展想法
    • 其他代码

一、功能介绍

在我们日常开发中,如果系统在线上环境上,发生异常,开发人员不能及时知晓来修复,可能会造成重大的损失,因此后端服务中加入异常报警的功能是十分必要的,而开发一个功能全面的异常报警服务,可能会花费较长的周期,今天给大家带来一种基于Slack实现异常日志报警的办法。

实现逻辑:一般情况下,代码中都会对会出现异常的地方,进行处理,最基本的就是打印日志,本文将实现在打印日志时,同时将异常信息发送到Slack频道中,开发或运维人员创建Slack账号,加入频道,便可实时收到异常信息的告警。

二、Slack介绍

Slack 它是一种基于Web的实时通信工具,可作为台式机/笔记本电脑、移动设备的单个应用程序以及Web应用程序使用。基本上,它是您的私人聊天和协作室。对于许多公司而言,它已取代电子邮件/私人论坛/聊天室成为主要的内部基于文本的沟通渠道。

可以理解为它是聊天群组 + 大规模工具集成 + 文件整合 + 统一搜索。截至2014年底,Slack 已经整合了电子邮件、短信、Google Drives、Twitter、Trello、Asana、GitHub 等 65 种工具和服务,可以把各种碎片化的企业沟通和协作集中到一起。几个重要的概念:

工作区:相当去工作空间,用户可以加入或者创建不同的工作区,很多时候,工作区的名称和URL将是公司名称。

频道:频道可以区分为不同的团队或者主题,也可以理解成相当于微信,频道中的成员共享频道中的信息。

三、前期准备

slack配置

  • 创建账号,登录,可以使用app或者用浏览器登录网页版
  • 创建自己的工作区,还可以邀请其他人加入工作区。
  • 创建频道,邀请同事加入,此时可以往频道中发信息,加入频道的人都可以看到信息

工作区添加应用Incoming WebHook,选择频道,保存Webhook URL,后面将通过Webhook实现程序往频道中发消息。

pom.xml

<dependencies>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.83</version>
    </dependency>
    <dependency>
        <groupId>commons-configuration</groupId>
        <artifactId>commons-configuration</artifactId>
        <version>1.10</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
        <scope>test</scope>
    </dependency>
</dependencies>

四、具体实现

1.实现Slack发送消息

SlackUtil 给Slack发消息工具类

package com.yy.operation;
import com.yy.common.CommonThreadFactory;
import com.yy.common.ConnUtil;
import org.apache.commons.lang.StringUtils;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * @author :Max
 * @date :Created in 2022/8/26 下午12:54
 * @description:
 */
public class SlackUtil {
    private static final Logger logger = Logger.getLogger(SlackUtil.class.getCanonicalName());
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final String SEND_USER_NAME ="运维机器人";
    private static int MAX_RETRY =3;
    /**
     * 线程池 抛弃策略DiscardPolicy:这种策略,会默默的把新来的这个任务给丢弃;不会得到通知
      */
    private static ExecutorService executor = new ThreadPoolExecutor(10,30,60,TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(200),new CommonThreadFactory("Slack"), new ThreadPoolExecutor.DiscardPolicy());
    private static String MSG_FORMAT ="payload='{'"channel": "{0}", "username": "{1}", "text": "{2}", "icon_emoji": ":ghost:"'}'" ;
    /**
     * 保存的Webhook URL ,需要初始化
     */
    private static String WEBHOOK_URL ;
    private static boolean SLACK_ABLE;
    public static void setSlackConfig(String webhookUrl){
        WEBHOOK_URL = webhookUrl;
        SLACK_ABLE = true;
    }
    /**
     * slack异步发消息,保证不能影响到主功能
      * @param channel
     * @param msg
     */
    public static void send(final String channel, final String msg){
        if(!SLACK_ABLE){
            return;
        }
        if(StringUtils.isBlank(msg)){
            return;
        }
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    SlackUtil.send(channel,sdf.format(System.currentTimeMillis())+"   "+msg,MAX_RETRY);
                } catch (Exception e) {
                    logger.log(Level.SEVERE, e.getMessage(), e);
                }
            }
        });
    }
    /**
     * 如果slask发消息失败,会最多尝试发三次,三次都失败,会打印异常信息
      * @param channel
     * @param msg
     * @param retry
     * @throws Exception
     */
    public static void send(String channel, String msg, int retry) throws Exception {
        if(msg.indexOf(""")>=0 ||msg.indexOf("{")>=0 ||msg.indexOf("}")>=0){
            msg =msg.replace(""","'").replace("{","[").replace("}","]");
        }
        String payload = MessageFormat.format(MSG_FORMAT, channel,SEND_USER_NAME,msg);
        String result = ConnUtil.getContentByPostWithUrlencode(WEBHOOK_URL,payload);
        logger.info("result:"+result);
        if(StringUtils.isEmpty(result) ||!result.startsWith("ok")){
            --retry;
            if(retry>0){
                try {
                    TimeUnit.SECONDS.sleep(retry*5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                send(channel,msg,retry);
            }else{
                throw new Exception("Fail to send slack:"+result+"\nmsg:"+msg);
            }
        }
    }
}

向 webhook发起请求通过Urlencode

package com.yy.common;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * @author :Max
 * @date :Created in 2022/8/26 下午1:44
 * @description:
 */
public class ConnUtil {
    private static final Logger logger = Logger.getLogger(ConnUtil.class.getCanonicalName());
    public static String getContentByPostWithUrlencode(String url,String msg){
        StringEntity entity = new StringEntity(msg, "UTF-8");
        entity.setContentEncoding("UTF-8");
        entity.setContentType(" application/x-www-form-urlencoded");
        HttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost request = new HttpPost(url);
        request.setEntity(entity);
        HttpResponse response = null;
        try {
            response = httpClient.execute(request);
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                InputStream instream = responseEntity.getContent();
                BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
                StringBuffer contents = new StringBuffer();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    contents.append(line);
                    contents.append("\n");
                }
                return contents.toString();
            }
        } catch (Exception ex) {
            logger.log(Level.SEVERE, ex.getMessage(), ex);
        }
        return null;
    }
}

SlackUtil测试

package com.yy.test;
import com.yy.common.SlackChannelEnum;
import com.yy.operation.SlackUtil;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
/**
 * @author :Max
 * @date :Created in 2022/8/28 下午2:37
 * @description:
 */
public class SlackTest {
    static {
        SlackUtil.setSlackConfig("https://hooks.slack.com/services/*******");
    }
    @Test
    public void test(){
        SlackUtil.send(SlackChannelEnum.EXCEPTION.channel,"test ~");
        try {
            TimeUnit.MINUTES.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Assert.assertTrue(true);
    }
}

发送成功,可以在频道中看到信息

2.重写打印日志类

常见异常打日志处理

public class LoggerTest {
    private static final Logger logger = Logger.getLogger(LoggerTest.class.getCanonicalName());
    @Test
    public void test() {
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
        }
    }
}

重写封装打印日志的方法

package com.yy.operation;
import com.yy.common.SlackChannelEnum;
import org.apache.commons.lang.StringUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.text.MessageFormat;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
/**
 * @author  Max
 * @date :Created in 2022/8/4 下午5:14
 * @description:
 */
public class CommonLogger {
    private Logger logger;
    private CommonLogger(String className) {
        logger = Logger.getLogger(className);
    }
    private static String SERVER;
    private static String EXCEPTION_ALARM_FORMAT = "EXCEPTION 发生异常!\n环境 :{0}\n信息 :{1}\n详情 :{2}";
    private static String WARNING_ALARM_FORMAT = "WARNING 发生告警!\n环境 :{0}\n信息 :{1}";
    private static String SEVERE_ALARM_FORMAT = "SEVERE 发生告警!\n环境 :{0}\n信息 :{1}";
    private static String LOG_ALARM_FORMAT = "LOG 发生告警!\n环境 :{0}\n信息 :{1}";
    private static String USER_BEHAVIOR_FORMAT = "CUSTOMER \n环境 :{0}\n信息 :{1}";
    static {
        try{
            InetAddress ip4 = Inet4Address.getLocalHost();
            SERVER = ip4.getHostAddress();
        }catch (Exception e){
            SERVER ="undefined server";
        }
    }
    public static CommonLogger getLogger(String name) {
        return new CommonLogger(name);
    }
    /**
     * Print exception information, send slack
     *
     * @param level
     * @param msg
     * @param e
     */
    public void log(Level level, String msg, Throwable e) {
        if(StringUtils.isBlank(msg)){
            return;
        }
        msg =dolog(level,msg, e);
        msg = MessageFormat.format(EXCEPTION_ALARM_FORMAT, SERVER, formatMsg(msg), getErrmessage(e));
        SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
    }
    /**
     * Print user behavior information, send slack
     *
     * @param msg
     */
    public void userBehaviorInfo(String msg) {
        if(StringUtils.isBlank(msg)){
            return;
        }
        msg =dolog(Level.INFO,msg);
        msg = MessageFormat.format(USER_BEHAVIOR_FORMAT, SERVER, formatMsg(msg));
        SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
    }
    public String formatMsg(String msg){
        StringBuilder source =new StringBuilder(logger.getName());
        msg=transferMsgSource(source,msg);
        return source.toString()+" "+msg;
    }
    /**
     * Print warning severe information, send slack
     *
     * @param msg
     */
    public void severe(String msg) {
        if(StringUtils.isBlank(msg)){
            return;
        }
        msg = dolog(Level.SEVERE,msg);
        msg = MessageFormat.format(SEVERE_ALARM_FORMAT, SERVER, formatMsg(msg));
        SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
    }
    /**
     * Print warning severe information, send slack
     *
     * @param msg
     */
    public void warning(String msg) {
        if(StringUtils.isBlank(msg)){
            return;
         }
        msg = dolog(Level.WARNING,msg);
        msg = MessageFormat.format(WARNING_ALARM_FORMAT, SERVER, formatMsg(msg));
        SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
    }
    /**
     * Print warning log information, send slack
     *
     * @param msg
     */
    public void log(Level severe, String msg) {
        if(StringUtils.isBlank(msg)){
            return;
        }
        msg =dolog(severe,msg);
        msg = MessageFormat.format(LOG_ALARM_FORMAT, SERVER, formatMsg(msg));
        SlackUtil.send(SlackChannelEnum.EXCEPTION.channel, msg);
    }
    public static String getErrmessage(Throwable t) {
        return getThrowable(t);
    }
    public void info(String msg) {
        dolog(Level.INFO,msg);
    }
    public void fine(String msg) {
        logger.fine(msg);
    }
    public void setLevel(Level level) {
        logger.setLevel(level);
    }
    public String dolog(Level level, String msg) {
        return dolog(level,msg,null);
    }
    /**
     *
      * @param level
     * @param msg
     * @param thrown
     * @return msg="["+currentThread.getName()+"] "+a.getMethodName()+" "+msg;
     */
    public String dolog(Level level, String msg, Throwable thrown) {
        LogRecord lr = new LogRecord(level, msg);
        lr.setLevel(level);
        if(thrown!=null){
            lr.setThrown(thrown);
        }
        Thread currentThread = Thread.currentThread();
        StackTraceElement[] temp=currentThread.getStackTrace();
        StackTraceElement a=(StackTraceElement)temp[3];
        lr.setThreadID((int) currentThread.getId());
        lr.setSourceClassName(logger.getName());
        lr.setSourceMethodName(a.getMethodName());
        lr.setLoggerName(logger.getName());
        logger.log(lr);
        return "["+currentThread.getName()+"] "+a.getMethodName()+" "+msg;
    }
    public static String getThrowable(Throwable e) {
        String throwable = "";
        if (e != null) {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            pw.println();
            e.printStackTrace(pw);
            pw.close();
            throwable = sw.toString();
        }
        return throwable;
    }
    public static String transferMsgSource(StringBuilder source,String msg){
        if(msg.indexOf(" ")>0){
            String threadName = msg.substring(0,msg.indexOf(" "))+ " ";
            msg=msg.substring(threadName.length());
            source.insert(0,threadName);
            if(msg.indexOf(" ")>0) {
                String method = msg.substring(0, msg.indexOf(" "));
                source.append( "." + method);
                msg = msg.substring(method.length()+1);
            }
        }
        return msg;
    }
}
package com.yy.operation;
import java.text.MessageFormat;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggerUtil {
   private static Logger curLogger = Logger.getLogger(LoggerUtil.class.getCanonicalName());
   private static ConcurrentHashMap<String, CommonLogger> loggers = new ConcurrentHashMap<String, CommonLogger>();
   public static CommonLogger getLogger(Class<?> clazz) {
      String className = clazz.getCanonicalName();
      CommonLogger logger = loggers.get(className);
      if (logger == null) {
         logger = CommonLogger.getLogger(className);
         curLogger.fine(MessageFormat.format("Register logger for {0}", className));
         loggers.put(className, logger);
      }
      return logger;
   }
}

测试日志类

定义日志类时发生改变,调用出的代码无需更改,以较小的代价,集成异常报警功能

public class LoggerTest {
    private static final Logger logger = Logger.getLogger(LoggerTest.class.getCanonicalName());
    @Test
    public void test() {
        try {
            int i = 1 / 0;
        } catch (Exception e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
        }
    }
}

测试结果,频道中出现打印的异常信息,方便开发运维人员定位

五、优化扩展想法

  • 可以不仅仅实现打印异常日志,也可以打印用户的一些关键行为,如充值等,频道可以设置多个,发送不同主题的消息
  • 可以优化线程池
  • 如果开发人员不能及时查看slack,也可以集成电子邮件,Slack中可以添加mailclark应用(单独收费),经过配置后,发动频道中的信息,可以自动邮件发送给任意邮箱,接受者无需创建slack账号。具体配置可参考链接

其他代码

package com.yy.common;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * @author :Max
 * @date :Created in 2022/8/26 下午1:51
 * @description:
 */
public class CommonThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String threadNamePrefix;
    private final String nameSpecific;
    private final boolean isDaemon;
    public CommonThreadFactory(String nameSpecific) {
        this(nameSpecifihttps://juejin.cn/post/7136858841756467230#heading-4c, false);
    }
    public CommonThreadFactory(String nameSpecific, boolean isDaemon) {
        SecurityManager s = System.getSecurityManager();
        this.group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        this.threadNamePrefix = "eg-pool-" + poolNumber.getAndIncrement() + "-thread";
        this.nameSpecific = nameSpecific;
        this.isDaemon = isDaemon;
    }
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, String.format("%s-%d-%s",
                this.threadNamePrefix, threadNumber.getAndIncrement(), this.nameSpecific), 0);
        t.setDaemon(isDaemon);
        t.setPriority(Thread.NORM_PRIORITY);
        return t;
    }
}
public enum SlackChannelEnum {
    EXCEPTION("#test-example");
    public String channel;
    SlackChannelEnum(String channel) {
        this.channel = channel;
    }
}

以上就是JAVA基于Slack实现异常日志报警详解的详细内容,更多关于JAVA Slack异常日志报警的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java实现日志文件监听并读取相关数据的方法实践

    目录 项目需求 Apache Commons-IO 核心知识 代码实现 总结 项目需求 由于所在数据中台项目组需要实现监听文件夹或者日志文件并读取对应格式的脏数据的需求,以便在文件.文件夹发生变化时进行相应的业务流程:所以在这里记录下相关业务的实现及技术选型. Apache Commons-IO 首先需要添加对应依赖: <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</

  • Java异常日志堆栈丢失的原因与排查

    前言 查日志是我们排查问题的重要手段之一,直接又方便.其中异常日志堆栈信息可以让我们快速的发现问题所在,但稍微有点经验的开发应该会遇到过日志堆栈信息丢失的情况. 堆栈只打印了一行:java.lang.NullPointerException,然后什么信息都没有了,这是怎么回事? 如果面试中,就可以提一些问题: 什么情况下Java的异常日志堆栈信息会丢失?其原因是什么? 异常堆栈丢失情况下要如何排查问题? 原因 JVM内部同一个方法被调用多次的时候,会被JIT编译器进行优化,在Oracle官方文档

  • java常见log日志的使用方法解析

    目录 前言 1. Java.util.Logger 2. org.apache.logging.log4j 3. org.slf4j.Logger 前言 log日志可以debug错误或者在关键位置输出想要的结果 java日志使用一般有原生logger.log4j.Slf4j等 一般的日志级别都有如下(不同日志不一样的方法参数,注意甄别) 参数 描述 OFF.ON 不输出或者输出所有级别信息,通常使用在setLevel方法中 FATAL 致命错误 ERROR 错误error WARN 告警信息 I

  • java底层JDK Logging日志模块处理细节深入分析

    日志输出是所有系统必备的,很多开发人员可能因为常常使用log4j而忽视了JDK logging模块,两者之间是否有联系?是怎样的联系?JDK logging处理细节是怎么样的?本周抛砖引玉,先分析JDK logging机制. 从例子开始 JDK Logging的使用很简单,如下代码所示,先使用Logger类的静态方法getLogger就可以获取到一个logger,然后在任何地方都可以通过获取到的logger进行日志输入.比如类似logger.info("Main running.")的

  • 在日志中记录Java异常信息的正确姿势分享

    目录 日志中记录Java异常信息 遇到的问题 原因分析 正确的做法 java异常在控制台和日志里面的打印记录 1.e.printStackTrace()打印在哪里 2.e.printStackTrace()打印的内容是什么 3.如果将e.printStackTrace()的信息打印在日志里应该怎么做呢? 日志中记录Java异常信息 遇到的问题 今天遇到一个线上的BUG,在执行表单提交时失败,但是从程序日志中看不到任何异常信息. 在Review源代码时发现,当catch到异常时只是输出了e.get

  • Java十分钟精通Log4j日志的使用

    目录 为什么要用日志? 下载: 详细步骤: 一.打开IDEA 二.创建日志对象 为什么要用日志? 我们知道,程序在运行过程中会产生很多很多信息,比如在几点几分的时候运行了,运行的结果是怎么样的?为了我们更加了解程序运行的情况,可以通过日志来查看,日志可以在控制台输出,也可以输出至指定的文件内,在下面的文章中具体的给大家介绍. 下载: Log4J是Apache公司的开源项目,用于日志处理.下载地址: https://logging.apache.org/log4j/2.x/download.htm

  • java通过AOP实现全局日志打印详解

    目录 几个常用的切点注解,这次使用了@Before和@Around 切Controller打印请求的接口.参数.返回值以及耗时情况. 切Service打印日志,URL,请求方式,IP,类名,方法 总结 几个常用的切点注解,这次使用了@Before和@Around 1.@Before 前置增强(目标方法执行之前,执行注解标注的内容) 2.@AfterReturning 后置增强(目标方法正常执行完毕后,执行) 3.@Around 环绕增强(目标方法执行前后,分别执行一些代码) 4.@AfterTh

  • JAVA基于Slack实现异常日志报警详解

    目录 一.功能介绍 二.Slack介绍 三.前期准备 slack配置 pom.xml 四.具体实现 1.实现Slack发送消息 SlackUtil 给Slack发消息工具类 向 webhook发起请求通过Urlencode SlackUtil测试 2.重写打印日志类 常见异常打日志处理 重写封装打印日志的方法 测试日志类 五.优化扩展想法 其他代码 一.功能介绍 在我们日常开发中,如果系统在线上环境上,发生异常,开发人员不能及时知晓来修复,可能会造成重大的损失,因此后端服务中加入异常报警的功能是

  • java异常处理throws完成异常抛出详解

    已检查异常抛出 对于已检查异常(checked exceptions),编译器强制要求捕获并处理可能发生的异常,不处理就不能通过编译.但调用的方法没有能力处理这种异常,对于这种情况,可以在方法声明处使用throws子句来声明抛出异常,而是调用层次向上传递,谁调用这个方法,这个异常就由谁来处理.如:在service层读取文件,如果文件不存在,则需要将文件不存在的这条信息反馈给用户.要求在service层将此异常向上抛,用户层调用services层获取此条信息,反馈给用户.示例代码如下: 创建类Re

  • 优雅地在Java 8中处理异常的方法详解

    前言 Java 8 引入的流 (Stream) API 和 lambda 表达式为我们打开了新世界的大门,自此之后我们也可以在 Java 中进行函数式编程了.然而,在实际工作中,许多小伙伴并不知道如何正确的在 lambda 中处理异常,今天就来给大家讲解一下. 小编给大家推荐一个Java技术交流群:937053620!群内提供设计模式.spring/mybatis源码分析.高并发与分布式.微服务.性能优化,面试题整合文档等免费资料!给大家提供一个交流学习的平台! 我们都知道,Java 异常分为检

  • Java基于链表实现栈的方法详解

    本文实例讲述了Java基于链表实现栈的方法.分享给大家供大家参考,具体如下: 在上几小节中我们实现了基本的链表结构,并在上一节的底部给出了有关链表的源码,此处在贴一次吧,猛戳 在开始栈的实现之前,我们再来看看关于链表的只在头部进行的增加.删除.查找操作,时间复杂度均为O(1),基于链表的这几个优势,我们在此基础上实现栈. 前言,在写本小节之前,我们已经实现了一个基于静态数组的栈,转到查看.此处我们实现基于链表的栈. 1.链表类拷贝到Stack 包下: 在实现基于静态数组的栈的时候,我们已经新建了

  • Java基于Socket实现网络编程实例详解

    一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机. 而TCP层则提供面向应用的可靠(tcp)的或非可靠(UDP)的数据传输机制,这是网络编程的主要对象,一般不需要关心IP层是如何处理数据的. 目前较为流行的网络编程模型是客户机/服务器(C/S)结构.即通信双方一方作为服务器等待客户提出请求并予以响应.客户则

  • 基于Java中throw和throws的区别(详解)

    系统自动抛出的异常 所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,并且 Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行. 语句抛出的异常 用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常. throw是语句抛出一个异常. 语法:throw (异常对象); throw e; throws是方法可能抛出异常的声明.(用在声明方法时,表示该方法可能要抛出异常) 语法:[(修饰符)](返回

  • 基于nginx access日志格式详解

    nginx的nginx.cnf中,使用log_format字段可以指定日志的格式文件. log.fromat: log_format access ' [$time_local] | $host | $remote_addr | $request | $request_time | $body_bytes_sent | $status |' '| $upstream_addr | $upstream_response_time | $upstream_status |' ' "$http_ref

  • 详解Java中NullPointerException异常的原因详解以及解决方法

    NullPointerException是当您尝试使用指向内存中空位置的引用(null)时发生的异常,就好像它引用了一个对象一样. 当我们声明引用变量(即对象)时,实际上是在创建指向对象的指针.考虑以下代码,您可以在其中声明基本类型的整型变量x: int x; x = 10; 在此示例中,变量x是一个整型变量,Java将为您初始化为0.当您在第二行中将其分配给10时,值10将被写入x指向的内存中. 但是,当您尝试声明引用类型时会发生不同的事情.请使用以下代码: Integer num; num

  • java 异常的实例详解

    java 异常的实例详解 1.异常的定义:程序在运行时出现不正常情况. 异常的划分: Error:严重的问题,对于error一般不编写针对性的代码对其进行处理. Exception:非严重的问题,对于exception可以使用针对性的处理方式进行处理. 2.异常的处理:(固定格式) try {需要被检测的代码:} catch(异常类 变量) {处理异常的代码(处理方式):}//这里应当是要有针对性的处理方式 finally {一定会执行的语句:}//通常是关闭资源的代码,因为资源必须得到释放 对

随机推荐