J2ee 高并发情况下监听器实例详解

J2ee 高并发情况下监听器实例详解

引言:在高并发下限制最大并发次数,在web.xml中用过滤器设置参数(最大并发数),并设置其他相关参数。详细见代码。
第一步:配置web.xml配置,不懂的地方解释一下:参数50通过参数名maxConcurrent用在filter的实现类中获取,filter-class就是写的实现类,

url-pattern就是限制并发时间的url,结束!

<filter>
  <filter-name>ConcurrentCountFilter</filter-name>
  <filter-class>com.procure.pass.ConcurrentCountFilter</filter-class>
  <init-param>
    <param-name>maxConcurrent</param-name>
    <param-value>50</param-value>
  </init-param>
 </filter>
 <filter-mapping>
  <filter-name>ConcurrentCountFilter</filter-name>
  <url-pattern>/a/pass/export</url-pattern>
 </filter-mapping>

第二步:写实现类实现filter,该接口有三个方法,详见代码。

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 

/**
 * Servlet Filter implementation class ConcurrentCountFilter
 */
public class ConcurrentCountFilter implements Filter {
  private static Logger log = LoggerFactory.getLogger(ConcurrentCountFilter.class);
  private FilterConfig filterConfig;
  private int maxConcurrent = -1;
  //总计数
  private static AtomicInteger count = new AtomicInteger(0); 

  /**
   * 获取当前并发数
   * @return
   */
  public static int get(){
      return count.get();
    }
  /**
   * 增加并发数量
   * @return
   */
   public static int increase(){
      return count.incrementAndGet();
    }
   /**
   * 减少并发数量
   * @return
   */
   public static int decrement(){
     return count.decrementAndGet();
   } 

  /**
   * 初始化
   */
    public void init(FilterConfig filterConfig) throws ServletException {
      //获取配置的最大并发数量
      String maxStr = filterConfig.getInitParameter("maxConcurrent");
      int num = -1;
      if(maxStr != null && !"".equals(maxStr)){
        num = Integer.parseInt(maxStr);
      }
      if(num >= 1){
        this.maxConcurrent = num;
      }else{
        this.maxConcurrent = -1;
      }
    }
    /**
     * 过滤主方法
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
      try{
      //增加并发数量
      int num = increase();
      if(maxConcurrent > 0){
        if(maxConcurrent >= num){
          chain.doFilter(request, response);
          log.info("第一次并发数量:"+count.get());
        }else{
          HttpServletResponse res = (HttpServletResponse) response;
          res.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,"达到最大并发数限制");
          log.info("达到最大并发数");
          log.info("最大并发数量:"+count.get());
        }
      }else{
        chain.doFilter(request, response);
        log.info("第二次并发数量:"+count.get());
      }
      }finally {
        decrement();
        log.info("减小的并发量:"+count.get());
      } 

    }
  /**
   * 退出销毁
   */
  public void destroy() {
    this.filterConfig = null;
    log.info("销毁......");
  }
}

代码到此完。

吐槽一下自己在项目中遇到的坑:

1.response.sendError( int, string);在本文代码中为res.sendError其中若直接如本文代码那样会返回一个503服务器带出来的页面,此页面粗暴及其难看,

在此为了友好通知用户,需做如下步骤,在web.xml中做如下配置代码:

<error-page>
  <error-code>503</error-code>
  <location>/WEB-INF/views/error/503.jsp</location>
 </error-page>

如果在web.xml中配置了上面信息,首先会过滤503(HttpServletResponse.SC_SERVICE_UNAVAILABLE)状态码下的此页面而不会抛服务器的页面。

其中503.jsp页面需自己完成在此仅仅贴出来一个示例做参考,代码如下:

<%
response.setStatus(503); 

// 获取异常类
Throwable ex = Exceptions.getThrowable(request);
if (ex != null){
  LoggerFactory.getLogger("500.jsp").error(ex.getMessage(), ex);
} 

// 编译错误信息
StringBuilder sb = new StringBuilder("错误信息:\n");
if (ex != null) {
  sb.append(Exceptions.getStackTraceAsString(ex));
} else {
  sb.append("未知错误.\n\n");
} 

// 如果是异步请求或是手机端,则直接返回信息
if (Servlets.isAjaxRequest(request)) {
  out.print(sb);
} 

// 输出异常信息页面
else {
%>
<%@page import="org.slf4j.Logger,org.slf4j.LoggerFactory"%>
<%@page import="com.xahl_oa.internal.common.web.Servlets"%>
<%@page import="com.xahl_oa.internal.common.utils.Exceptions"%>
<%@page import="com.xahl_oa.internal.common.utils.StringUtils"%>
<%@page contentType="text/html;charset=UTF-8" isErrorPage="true"%>
<%@include file="/WEB-INF/views/include/taglib.jsp"%>
<!DOCTYPE html>
<html>
<head>
  <title>503 - 服务暂时不可用</title>
  <%@include file="/WEB-INF/views/include/head.jsp" %>
</head>
<body>
  <div class="container-fluid">
    <div class="page-header"><h1>服务暂时不可用请稍后再试.</h1></div>
    <div class="errorMessage">
      错误信息:<%=ex==null?"未知错误.":StringUtils.toHtml(ex.getMessage())%> <br/> <br/>
      服务器暂时不可用请稍后再试,谢谢!<br/> <br/>
      <a href="javascript:" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" onclick="history.go(-1);" class="btn">返回上一页</a>
      <a href="javascript:" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" onclick="$('.errorMessage').toggle();" class="btn">查看详细信息</a>
    </div>
    <div class="errorMessage hide">
      <%=StringUtils.toHtml(sb.toString())%> <br/>
      <a href="javascript:" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" onclick="history.go(-1);" class="btn">返回上一页</a>
      <a href="javascript:" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" onclick="$('.errorMessage').toggle();" class="btn">隐藏详细信息</a>
      <br/> <br/>
    </div>
    <script>try{top.$.jBox.closeTip();}catch(e){}</script>
  </div>
</body>
</html>
<%
} out = pageContext.pushBody();
%>

此页面就比服务器抛出的页面友好甚多。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 分享J2EE的13种核心技术

    Java最初是在浏览器和客户端机器中粉墨登场的.当时,很多人质疑它是否适合做服务器端的开发.现在,随着对Java2平台企业版(J2EE)第三方支持的增多,Java被广泛接纳为开发企业级服务器端解决方案的首选平台之一. 在本文中我将解释支撑J2EE的13种核心技术:JDBC, JNDI, EJBs, RMI, JSP, Java servlets, XML, JMS, Java IDL, JTS, JTA, JavaMail 和 JAF. J2EE平台由一整套服务(Services).应用程序接口

  • J2EE验证码图片如何生成和点击刷新验证码

    验证码图片生成步骤 创建BufferedImage对象. 获取BufferedImage的画笔,即调用getGraphics()方法获取Graphics对象. 调用Graphics对象的setColor()方法和fillRect()方法设置图片背景颜色. 调用Graphics对象的setColor()方法和drawLine()方法设置图片干扰线. 调用BufferedImaged对象的setRGB()方法设置图片的噪点. 调用Graphics对象的setColor()方法.setFont()方法

  • J2EE 开发购物网站 经验篇 - 建表

    GO ON 继续进阶!!(本贴个人认为对初学者很有帮助,请大家认真看.因时间仓促,如有错误请指正)SQL*PLUS基础在上一贴中,我们掌握了些基本的oracle操作,如创建.授权用户,创建数据库等.在OEM(Oracle Enterprise Manager)可视化的窗口环境中,虽然我们也可以很方便地做这些事,但是事实上,用SQL语言书写在开发上更有效率!!oracle提供的SQL*Plus就是个不错的工具,如果大家喜欢窗口的开发环境,用SQLPlus Worksheet也行!下面说点基本的西西

  • JDK、J2EE、J2SE、J2ME四个易混淆概念区分

    JDK,J2EE,J2SE,J2ME的概念区别是什么呢? 1.这些是什么? JDK是Java development toolkit,相当于是Java的库函数,是编译,运行java程序的工具包. J2EE是Java 2 enterprise edition是Java的一种企业版用于企业级的应用服务开发 J2SE是Java 2 standard edition是Java的标准版,用于标准的应用开发 J2ME是Java 2 Micro Edition是Java的微型版,常用于手机上的开发 J2EE,

  • 实战 J2EE 开发购物网站 - 创建数据库

    二:创建数据库小试牛刀oracle 8i(顺便我们练练手)(为了方便,我就将oracle 8i简写8i了)8i和9i确实有些不一样,不过在界面上区别不大,还是以我的oracle 8i为例为大家讲解一下吧!既然是实战,首先我们为自己新建一个开发用户,并创建一个表!!在oracle里创建新用户和表的方法比较多,只要你有管理员的权限(废话!),首先用最简单的,在8i的程序组中启动DBA Studio程序项,在出现的数据库链接信息中输入管理用户名和口令即可,当然,在oracle中,你可以用用户名斜杠口令

  • 图解Eclipse j2ee开发环境的搭建过程

    Eclipse是一个开源的功能强大的ide开发环境,再加上他的扩展插件功能,使得他被广泛使用. J2ee有几种开发环境,eclipse+lomboz或者eclipse+myeclipse. Myeclipse是一个商用产品,较lomboz功能更加强,特别是在struts这样的mvc开发中. 为了能够测试,需要安装一个web server,我用的是tomcat   下面分别介绍安装和配置(win32平台).  1.jdk的安装,注意环境变量的设置,JAVA_HOME,CLASSPATH,PATH

  • 经常听朋友说什么J2EE,终于知道点什么是J2EE了,汗一个

    经常听朋友说什么J2EE,终于知道点什么是J2EE了,汗一个,上网搜了下这个说的比较详细了,J2EE,Java2平台企业版(Java 2 Platform Enterprise Edition), 是Sun公司为企业级应用推出的标准平台.Java平台共分为三个主要版本Java EE.Java SE和Java ME. Sun公司在1998年发表JDK1.2版本的时候,使用了新名称Java 2 Platform,即"Java2平台",修改后的JDK称为Java 2 Platform Sof

  • J2ee 高并发情况下监听器实例详解

    J2ee 高并发情况下监听器实例详解 引言:在高并发下限制最大并发次数,在web.xml中用过滤器设置参数(最大并发数),并设置其他相关参数.详细见代码. 第一步:配置web.xml配置,不懂的地方解释一下:参数50通过参数名maxConcurrent用在filter的实现类中获取,filter-class就是写的实现类, url-pattern就是限制并发时间的url,结束! <filter> <filter-name>ConcurrentCountFilter</filt

  • java高并发情况下高效的随机数生成器

    前言 在代码中生成随机数,是一个非常常用的功能,并且JDK已经提供了一个现成的Random类来实现它,并且Random类是线程安全的. 下面是Random.next()生成一个随机整数的实现: protected int next(int bits) { long oldseed, nextseed; AtomicLong seed = this.seed; do { oldseed = seed.get(); nextseed = (oldseed * multiplier + addend)

  • Redis高并发情况下并发扣减库存项目实战

    目录 第一种方案:纯MySQL扣减实现 MySQL架构升级 第二种方案:缓存实现扣减 第三种方案:数据库+缓存 顺序写的性能更好 顺序写的架构 扣减流程 相信大家从网上学习项目大部分人第一个项目都是电商,生活中时时刻刻也会用到电商APP,例如淘宝,京东等.做技术的人都知道,电商的业务逻辑简单,但是大部分电商都会涉及到高并发高可用,对并发和对数据的处理要求是很高的.这里我今天就讲一下高并发情况下是如何扣减库存的? 我们对扣减库存所需要关注的技术点如下: 当前剩余的数量大于等于当前需要扣减的数量,不

  • 高并发系统的限流详解及实现

    在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流.本文结合作者的一些经验介绍限流的相关概念.算法和常规的实现方式. 缓存 缓存比较好理解,在大型高并发系统中,如果没有缓存数据库将分分钟被爆,系统也会瞬间瘫痪.使用缓存不单单能够提升系统访问速度.提高并发访问量,也是保护数据库.保护系统的有效方式.大型网站一般主要是"读",缓存的使用很容易被想到.在大型"写"系统中,缓存也常常扮演者非常重要的角色.比如累积一些数据批量写入,内存里面的缓存队列(生产消费),以及

  • Android开发高仿课程表的布局实例详解

    先说下这个demo,这是一个模仿课程表的布局文件,虽然我是个菜鸟,但我还是想留给学习的人一些例子,先看下效果 然后再来看一下我们学校的app 布局分析 先上一张划分好了的布局图 首先整个页面放在一个LinearLayout布局下面,分为上面和下面两个部分,下面一个是显示课程表的详细信息 1:这个没什么好讲的,就是直接一个LinearLayout布局,然后将控件一个TextView用来显示年份,一个View用来当作竖线,一个Spinner用来显示选择周数 2:这个是显示星期几的部件,是我自定义的V

  • Django高并发负载均衡实现原理详解

    1 什么是负载均衡? 当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能.那么,在服务器集群中,需要有一台服务器充当调度者的角色,用户的所有请求都会首先由它接收,调度者再根据每台服务器的负载情况将请求分配给某一台后端服务器去处理. 那么在这个过程中,调度者如何合理分配任务,保证所有后端服务器都将性能充分发挥,从而保持服务器集群的整体性能最优,这就是负载均衡问题. 下面详细介绍负载均衡的四种实现方式 2 HTTP重定向实现负载均衡 过程描述 当用户向服务器发起请求时,请求首先

  • 数据库高并发情况下重复值写入的避免 字段组合约束

    10线程同时操作,频繁出现插入同样数据的问题.虽然在插入数据的时候使用了: insert inti tablename(fields....) select @t1,@t2,@t3 from tablename where not exists (select id from tablename where t1=@t1,t2=@t2,t3=@t3) 当时还是在高并发的情况下无效.此语句也包含在存储过程中.(之前也尝试线判断有无记录再看是否写入,无效). 因此,对于此类情况还是需要从数据库的根本

  • MySQL在不知道列名情况下的注入详解

    前言 最近感觉脑子空空,全在为了刷洞去挖洞,还是回归技术的本身让自己舒服些.好了,下面话不多说了,来一起看看详细的介绍吧 前提 以下情况适用于 MySQL < 5版本,或者在 MySQL >= 5 的版本[存在information_schema库],且已获取到库名和表名 ① 当只能获取到表名,获取不到列名或者只能获取到无有效内容的列名情况[例如 id] ② 当希望通过information_schema库中的表去获取其他表的结构,即表名.列名等,但是这个库被WAF过滤掉的情况 其实个人感觉这

  • Spring Boot 整合 Reactor实例详解

    目录 引言 1 创建项目 2 集成 H2 数据库 3 创建测试类 3.1 user 实体 3.2 UserRepository 3.3 UserService 3.4 UserController 3.5 SpringReactorApplication 添加注解支持 测试 总结 引言 Reactor 是一个完全非阻塞的 JVM 响应式编程基础,有着高效的需求管理(背压的形式).它直接整合 Java8 的函数式 API,尤其是 CompletableFuture, Stream,还有 Durat

  • java并发高的情况下用ThreadLocalRandom来生成随机数

    目录 一:简述 二:Random的性能差在哪里 三:ThreadLocalRandom的简单使用 四:为什么ThreadLocalRandom能在保证线程安全的情况下还能有不错的性能 一:简述 如果我们想要生成一个随机数,通常会使用Random类.但是在并发情况下Random生成随机数的性能并不是很理想,今天给大家介绍一下JUC包中的用于生成随机数的类--ThreadLocalRandom.(本文基于JDK1.8) 二:Random的性能差在哪里 Random随机数生成是和种子seed有关,而为

随机推荐