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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • python字符串中某个字符修改_Python实现字符串中某个字母的替代功能

    python字符串中某个字符修改_Python实现字符串中某个字母的替代功能今晚想实现这样一个功能:将输入字符串中的字母“i”变成字母“p”。当时想的很简单,直接用for循环遍历,然后替代,出问题的代码如下:name=input(‘随便输入一堆字符吧…’)#name=list(name)name=””.join(name)j=0foriinrange(len(name)):ifname[i]==’i’:name[i]=’p’j=…

  • dex字符串解密_DEX文件混淆加密

    dex字符串解密_DEX文件混淆加密现在部分app出于安全性(比如加密算法)或者用户体验(热补丁修复bug)会考虑将部分模块采用热加载的形式Load。所以针对这部分的dex进行加密是有必要的,如果dex是修复的加密算法,你总不想被人一下就反编译出来吧。当然也可以直接用一个加密算法对dex进行加密,Load前进行解密就可以了,但是最好的加密就是让人分不清你是否加密了。一般逆向过程中拿到一个可以直接反编译成java…

  • PhpStorm 2021.5.2 x64 激活码(最新序列号破解)「建议收藏」

    PhpStorm 2021.5.2 x64 激活码(最新序列号破解),https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • 定制CentOS5.6系统

    定制CentOS5.6系统

  • 启动mysql报错10038_解决navicat远程连接mysql报错10038的问题

    navicat远程连接mysql报错10038一般由以下两个原因:一:本地防火墙问题在本地安装了mysql、navicat并打开了mysql服务的情况下,来设置防火墙。首先右击或者点击入站规则,找到新建规则,点击。点击端口。在特定本地端口中填入3306.一直点击下一步。这里可以给一个好分别的名称即可。之前再尝试连接即可,若仍然不可以,可能是服务器方面的问题。二:服务器3306端口未打开首先需要在安…

  • activexobject java_ActiveXObject[通俗易懂]

    activexobject java_ActiveXObject[通俗易懂]只有IE浏览器才支持这个构造函数,可以用这个来判断,当前是否为IE浏览器varisIE=!!window.ActiveXObject;在IE的不同版本下,要创建XHR对象,也需要通过这个构造函数来创建(构造时的参数不一样)。因为ActiveXObject的使用容易存在安全问题,如IE11中报错Automation服务器不能创建对象解决办法:Internet选项-安全-自定义安全级别-启用“对未…

    2022年10月15日

发表回复

您的电子邮箱地址不会被公开。

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