Java内部重定向死循环问题处理

原创|其它|编辑:郝浩|2010-02-09 10:17:10.000|阅读 2244 次

概述:java多人并行开发是很出色,但是只要是并行的那么就会存在一些问题。

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

  java多人并行开发是很出色,但是只要是并行的那么就会存在一些问题。

  比如:A程序员在A页面写了以个逻辑,当逻辑判断满足就内部重定向到B程序员写的B页面,但是刚好B程序员在B页面中的逻辑是满足某些条件就跳转到A页面,于是乎当某些特定条件下,两个页面就在不停的重定向一直到jvm的溢出。

  平时我们遇到这种问题可能找一会就找到了,也基本上没有什么影响。但是在一个成熟的业务系统中遇到这样的问题就是致命的。可能会导致服务器挂掉。。或者整个集群的连锁反应(集体挂掉)。当然你的用户也就访问不到你的站点了,在工业标准中我们考虑更多的就是怎么让系统更稳定。比如:淘宝一天都宕机了,该有多少商家要发疯。

  再次进入正题,如何来解决这种问题保证系统的绝对稳定呢?很简单一个fielter就搞定了。


view plaincopy to clipboardprint?
  package org.fielter.test;
  import java.io.IOException;
  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.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  /**
  * 过滤形成环路的fielter 
  *
  * @author yuezhen
  */
  public class CircleFilter implements Filter {
  public void init(FilterConfig filterConfig) throws ServletException {
  }
  public void doFilter(ServletRequest request, ServletResponse response,
  FilterChain filterChain) {
  try{
  HttpServletRequest req = (HttpServletRequest) request;
  String original="";
  // 获取原始的请求来源
  if(req.getAttribute("javax.servlet.forward.request_uri")!=null){
  original=(String)req.getAttribute("javax.servlet.forward.request_uri");
  }
  // 用System.out来代替log
  System.out.println("[info] the original url is:"+original);
  System.out.println("[info] the request url is:"+req.getRequestURI());
  // 如果原始请求地址和需要跳转的地址一致,抛出异常
  if(original.equals(req.getRequestURI())){
  System.out.println("[error] find circle");
  // 可以选择抛出异常,或者用其他的处理方式
  throw new Exception();
  }
  filterChain.doFilter(request, response);
  }catch(Exception e){
  // 发现了重定向的死循环的后续处理
  try {
  // 页面显示发现死循环
  response.getOutputStream().print("has circle");
  } catch (IOException e1) {
  e1.printStackTrace();
  }
  }
  }
  public void destroy() {
  }
  }


 package org.fielter.test;
  import java.io.IOException;
  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.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  /**
  * 过滤形成环路的fielter 
  *
  * @author yuezhen
  */
  public class CircleFilter implements Filter {
  public void init(FilterConfig filterConfig) throws ServletException {
  }
  public void doFilter(ServletRequest request, ServletResponse response,
  FilterChain filterChain) {
  try{
  HttpServletRequest req = (HttpServletRequest) request;
  String original="";
  // 获取原始的请求来源
  if(req.getAttribute("javax.servlet.forward.request_uri")!=null){
  original=(String)req.getAttribute("javax.servlet.forward.request_uri");
  }
  // 用System.out来代替log
  System.out.println("[info] the original url is:"+original);
  System.out.println("[info] the request url is:"+req.getRequestURI());
  // 如果原始请求地址和需要跳转的地址一致,抛出异常
  if(original.equals(req.getRequestURI())){
  System.out.println("[error] find circle");
  // 可以选择抛出异常,或者用其他的处理方式
  throw new Exception();
  }
  filterChain.doFilter(request, response);
  }catch(Exception e){
  // 发现了重定向的死循环的后续处理
  try {
  // 页面显示发现死循环
  response.getOutputStream().print("has circle");
  } catch (IOException e1) {
  e1.printStackTrace();
  }
  }
  }
  public void destroy() {
  }
  }

  上面这个fielter会检测请求的原始来源地址,然后判断与当前需要跳转的地址是否一致,如果一致那么肯定会形成以个环路,于是jvm就在不停执行跳转一直到堆栈溢出。

  当我们检测到这种环路,我们就可以抛出异常,定义统一的错误页面。。。。等等来友好的解决之。。。

  如下fielter的配置就可以看到,我们过滤了所有forward跳转的请求


view plaincopy to clipboardprint?
<filter>  
        <filter-name>CircleFilter</filter-name>  
        <filter-class>org.fielter.test.CircleFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>CircleFilter</filter-name>  
        <url-pattern>/*</url-pattern>  
        <dispatcher>FORWARD</dispatcher>  
    </filter-mapping> 

  如果有其他需求,类似的配置就OK了

  接下来附带一个maven搭的测试列子,直接mvn jetty:run,然后再浏览器中http://localhost:8080/fielter/index.htm 就可以看到拦截的效果了


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:网络转载

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP