Struts2拦截器实现异常处理[通俗易懂]

Struts2拦截器实现异常处理[通俗易懂]Struts2拦截器实现异常处理机制在j2ee项目中,系统内部难免会出现一些异常,如果把异常放任不管直接打印到浏览器可能会让用户感觉莫名其妙,也有可能让某些用户找到搞定系统的方法。所以不要在页面上输出错误信息,使用log日志的方式处理异常并记录异常。就拿struts2+hibernate+spring项目说明:通常一个页面请求到后台以后,首先是到action(也就是所谓mvc的c

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

Struts2
拦截器实现
异常处理机制
在j2ee项目中,系统内部难免会出现一些异常,如果把异常放任不管直接打印到浏览器可能会让用户感觉莫名其妙,也有可能让某些用户找到搞定系统的方法。 所以不要在页面上输出错误信息,使用log日志的方式处理异常并记录异常。
就拿struts2+hibernate+spring项目说明:通常一个页面请求到后台以后,首先是到action(也就是所谓mvc的controller),在action层会调用业务逻辑service,servce层会调用持久层dao获取数据。最后执行结果会汇总到action,然后通过action控制转发到指定页面,执行流程如下图所示:


Struts2拦截器实现异常处理[通俗易懂]
而这三层其实都有可能发生异常,比如dao层可能会有SQLException,service可能会有NullPointException,action可能会有IOException,一但发生异常并且程序员未做处理,那么该层不会再往下执行,而是向调用自己的方法抛出异常,如果dao、service、action层都未处理异常的话,异常信息会抛到服务器,然后服务器会把异常直接打印到页面,结果就会如下图所示:


Struts2拦截器实现异常处理[通俗易懂]     


其实这种错误对于客户来说毫无意义,因为他们通常是看不懂这是什么意思的。
刚学java的时候,我们处理异常通常两种方法:
①   直接throws,放任不管;
②    写try…catch,在catch块中不作任何操作,或者仅仅printStackTrace()把异常打印到控制台。
第一种方法最后就造就了上图的结果(不符合操作);而第二种方法更不好:页面不报错,但是也不执行用户的请求,简单的说,其实这就是bug。
那么发生异常到底应该怎么办呢?我想在大家对java异常有一定了解以后,会知道:异常应该在action控制转发之前尽量处理,同时记录log日志,然后在页面以友好的错误提示告诉用户出错了,如。
Struts2拦截器实现异常处理[通俗易懂]


然后我们回到刚才处理异常的地方,如果大家积累了一些项目经验以后会发现使用上面那种处理异常的方式可能还不够灵活:
①因为spring把大多数非运行时异常都转换成运行时异常(RuntimeException)最后导致程序员根本不知道什么地方应该进行try…catch操作
②每个方法都重复写try…catch,而且catch块内的代码都很相似,这明显做了很多重复工作而且还很容易出错。
使用truts2拦截器定义异常拦截器用来解决上述问题,如下图所示:


Struts2拦截器实现异常处理[通俗易懂]   
首先我的action类、service类和dao类如果有必要捕获异常,我都会try…catch,catch块内不记录log,通常是抛出一个新异常,并且注明错误信息,有拦截器来抛出异常信息,并写入log日志文件:


  1. Java代码
  2. //action层执行数据添加操作   
  3. public String save(){   
  4.    try{   
  5.          //调用service的save方法   
  6.          service.save(obj);   
  7.    }catch(Exception e){    
  8.       throw new RuntimeException(“添加数据时发生错误!”,e);   
  9.   }   
  10.    return “success”;   
  11. }  

复制代码

Struts2自定义拦截器的操作:
在struts2的配置文件<package>下添加:


  1. <interceptors>
  2.                    <!– 声明拦截器 –>
  3.                    <interceptor name=”errorInterceptor” class=”cn.itcast.elec.util.ErrorInterceptor” />
  4.                    <!– 配置拦截器栈 –>
  5.                    <interceptor-stack name=”myErrorInterceptor”>
  6.                                <interceptor-ref name=”defaultStack” />
  7.                                <interceptor-ref name=”errorInterceptor” />
  8.                    </interceptor-stack>
  9. </interceptors>
  10. <!– 覆盖底层的拦截器栈 对包中的所有action都有效 –>
  11. <default-interceptor-ref name=”myErrorInterceptor”/>
  12.             
  13.             <global-results>
  14.                     <result name=”errorMsg”>/errorMsg.jsp</result>
  15.             </global-results>
  16.             <global-exception-mappings>
  17.                     <exception-mapping result=”errorMsg” exception=”java.lang.Exception”></exception-mapping>
  18.         </global-exception-mappings>

复制代码

然后在异常拦截器对异常进行处理,看下面的代码:


拦截器的Java代码
  1. public class ErrorInterceptor implements Interceptor {


  2.         public void init() {


  3.         }

  4.         public String intercept(ActionInvocation actioninvocation) {


  5.                 String result = null; // Action的返回值   
  6.                 try {

  7.                         // 运行被拦截的Action,期间如果发生异常会被catch住   
  8.                         result = actioninvocation.invoke();
  9.                         return result;
  10.                 } catch (Exception e) {

  11.                         /**  
  12.                          * 处理异常  
  13.                          */
  14.                         String errorMsg = “出现错误信息,请查看日志!”;
  15.                         //通过instanceof判断到底是什么异常类型   
  16.                         if (e instanceof RuntimeException) {

  17.                                 //未知的运行时异常   
  18.                                 RuntimeException re = (RuntimeException) e;
  19.                                 //re.printStackTrace();
  20.                                 errorMsg = re.getMessage().trim();
  21.                         }
  22.                         //把自定义错误信息   
  23.                         HttpServletRequest request = (HttpServletRequest) actioninvocation
  24.                                         .getInvocationContext().get(StrutsStatics.HTTP_REQUEST);
  25.                         /**  
  26.                          * 发送错误消息到页面  
  27.                          */
  28.                         request.setAttribute(“errorMsg”, errorMsg);

  29.                         /**  
  30.                          * log4j记录日志  
  31.                          */
  32.                         Log log = LogFactory
  33.                                         .getLog(actioninvocation.getAction().getClass());
  34.                         log.error(errorMsg, e);
  35.                         return “errorMsg”;
  36.                 }// …end of catch   
  37.         }

  38.         public void destroy() {


  39.         }
  40. }

复制代码

最后在errorMsg.JSP页面显示具体的错误消息即可:


   
  1. <body>   
  2. <s:if test=”%{#request.errorMsg==null}”>   
  3.     <p>对不起,系统发生了未知的错误,请查看日志</p>   
  4. </s:if>   
  5. <s:else>   
  6.     <p>${requestScope.errorMsg}</p>   
  7. </s:else>   
  8. </body>  

复制代码

以上方式可以拦截后台代码所有的异常,但如果出现数据库连接异常时不
能被捕获的,大家可以使用
struts2
的全局异常处理机制来处理:


Struts2
配置文件
代码
  1. <global-results>
  2.             <result name=”errorMsg”>/errorMsg.jsp</result>
  3. </global-results>
  4. <global-exception-mappings>
  5.                     <exception-mapping result=”errorMsg” exception=”java.lang.Exception”></exception-mapping>
  6. </global-exception-mappings>

复制代码

上面这是一个很简单的异常拦截器,大家可以使用自定义异常,那样会更灵活一些。

以上异常拦截器可以使用其它很多技术替换:比如spring aop,servlet filter等,根据项目实际情况处理。
辅助:
log4j.properties
文件的内容:
### direct log messages tostdout ###
log4j.appender.stdout=
org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=
System.out
log4j.appender.stdout.layout=
org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=
%d{ABSOLUTE}
 
%5p
 
%c
{1}
:
%L
 

 
%m%n
### direct messages to filehibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE}%5p %c{1}:%L – %m%n
### set log levels – for moreverbose logging change ‘info’ to ‘debug’ ###
log4j.rootLogger=
error,
 
stdout
#log4j.logger.org.hibernate=info
#log4j.logger.org.hibernate=debug
### log HQL query parseractivity
#log4j.logger.org.hibernate.hql.ast.AST=debug
### log just the SQL
#log4j.logger.org.hibernate.SQL=debug
### log JDBC bind parameters###
#log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug
### log schema export/update###
#log4j.logger.org.hibernate.tool.hbm2ddl=debug
### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug
### log cache activity ###
#log4j.logger.org.hibernate.cache=debug
### log transaction activity
#log4j.logger.org.hibernate.transaction=debug
### log JDBC resourceacquisition
#log4j.logger.org.hibernate.jdbc=debug
### enable the following lineif you want to track down connection ###
### leakages when usingDriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
log4j.rootLogger= 
error,
 
A1,
 
R
log4j.appender.A1=
org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=
org.apache.log4j.PatternLayout
# Print the date in ISO 8601format
#log4j.appender.A1.layout.ConversionPattern=%d[%t] %-5p %c – %m%n
#log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-ddHH:mm:ss,SSS} %m%n
log4j.appender.A1.layout.ConversionPattern=
%d{yyyy-MM-dd
 
HH
:
mm:ss,SSS}
 
%l
 
“#”
 
%m%n
log4j.appender.R=
org.apache.log4j.RollingFileAppender
log4j.appender.R.File=
/elec.log
log4j.appender.R.MaxFileSize=
1000KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=
10
log4j.appender.R.layout=
org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=
%p
 
%t
 
%c
 

 
%m%n
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/188570.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Fcoin交易所的危险游戏!韭菜请远离!

    币圈一天,人间一年!Fcoin再一次用币圈速度验证了上面这句话并非虚言。Fcoin上线半个月,平台交易量即雄霸全球数字货币榜首,远超币安、OKEx、火币等老牌交易所,成为宇宙第一数字货币交易所。与Fcoin交易量蹿升速度相当的,还有Fcoin的平台币FT,一个月上涨百倍!成为币圈人士口中争相传播的百倍币。一、并不新鲜的Fcoin“交易挖矿”Fcoin能在短时间崛起,主要依靠的是“交易挖矿”模…

    2022年4月16日
    41
  • docker容器和主机同网段_docker桥接模式下外网访问

    docker容器和主机同网段_docker桥接模式下外网访问首先我们需要了解的是:每个docker容器都是隔离的,所以它们之间是相互不同的!那么我们开始操作起来,让他们之间可以相互ping通网络。。。一、拉取镜像创建容器1.在这之前首先关闭防火墙;如果显示runinng则执行:sudosystemctlstopfirewalld2.在https://hub.docker.com里拉取镜像busybox(注:busybox相当于小型的c…

    2025年10月25日
    4
  • 怎样使用cookie登录自己的账号

    在这之前,不管是做测试还是挖漏洞总会遇到这种问题做测试的时候测试项里面有一个会话标识未更新,这种漏洞说白了就是在退出个人账户的时候没有及时的清除cookie,从而让别人利用你的cookie再次登录你的账户,然后测试的时候客户就让测试如何使用cookie登录在挖漏洞的时候一般xss都需要打cookie然后伪造别人的身份登录,其实也是使用打到的cookie登录在这之前我没深入的理解这块,现…

    2022年4月8日
    80
  • MyEclipse安装SVN插件详解

    MyEclipse安装SVN插件详解今天弄了一下svn插件,确实不太容易,花了一番功夫才搞定,所以,为了以后不为同样的工作花费时间去学重复的事情,我决定记录一下自己安装SVN插件到MyEclipse的过程。也为苦恼在这事上的朋友提供点资源。首先当然是准备工具咯,svn的插件下载地址:http://www.eclipse.org/subversive/downloads.php#latest_releasesvn-con…

    2022年7月20日
    16
  • STL空间配置器解析和实现

    1.一级空间配置器实现1.1接口1.2实现2.二级空间配置器实现2.1接口2.2实现3.配置器标准接口4.测试

    2021年12月28日
    53
  • UVA 11464 Even Parity(递归枚举)

    UVA 11464 Even Parity(递归枚举)

    2022年1月10日
    47

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号