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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • linux线程同步有几种方法_shell多线程执行命令

    linux线程同步有几种方法_shell多线程执行命令Linux中的线程同步机制(一)–Futex引子在编译2.6内核的时候,你会在编译选项中看到[*]Enablefutexsupport这一项,上网查,有的资料会告诉你”不选这个内核不一定能正确的运行使用glibc的程序”,那futex是什么?和glibc又有什么关系呢?1.什么是FutexFutex是FastUserspacemuTexes的缩写

    2022年9月17日
  • Js排序算法_js 排序算法

    Js排序算法_js 排序算法一、概念快速排序算法由C.A.R.Hoare在1960年提出。它的时间复杂度也是O(nlogn),但它在时间复杂度为O(nlogn)级的几种排序算法中,大多数情况下效率更高,所以快速排序的应用非常广泛。注意:快速排序不一定是最快的排序方法,这取决于需要排序的数据结构、数据量。不过,大多数情况下,面试官和工作场所用它的概率也是相对较高的,所以我们应该花时间把它学透彻。二、工作原理首先设定一个分界值,通过该分界值将数组分成左右两部分。将大于或等于分界值的数据集中到数组右边

    2022年9月1日
  • 盘点值得互联网创业者学习的十大做事风格

    盘点值得互联网创业者学习的十大做事风格中国互联网通过第19次互联网报告得出很多数据,综合成一句话就是:“发展速度惊人。”面对如此庞大的市场,国外网络巨头虎视眈眈,总想找机会跨进国门,却因为不了解中国互联网运营规范及网民的习惯,或是犹豫不决或是屡遭搁浅。  而与此同时,国内众多网站正在疯狂抢夺这块蛋糕。在这些网站的背后出谋划策的人都是大众较熟悉的,他们的思路以及做事风格,值得现在的互联网创业者学习、借荐,有相似者可对号入座。

    2022年8月20日
  • 常量指针,指针常量的区别是什么_指针常量与常量指针

    常量指针,指针常量的区别是什么_指针常量与常量指针**要有具备扎实指针知识……了解引用、指针的一些注意事项:引用并非对象引用必须初始化引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起类型要严格匹配一、常量指针定义:又叫常指针,可以理解为常量的指针,也即这个是指针,但指向的是个常量,这个常量是指针的值(地址),而不是地址指向的值。关键点:常量指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改;常量指针可以被赋值为变量的地址,之所以叫常量指针,是限制了通过这个指针修改变量的值;指针还可以指向别

    2022年10月7日
  • 四阶龙格库塔法的基本原理_隐式龙格库塔法

    四阶龙格库塔法的基本原理_隐式龙格库塔法龙格库塔法的基本原理该算法是构建在数学支持的基础之上的。对于一阶精度的拉格朗日中值定理有:对于微分方程:y’=f(x,y)y(i+1)=y(i)+h*K1K1=f(xi,yi)当用点xi处的斜率近似值K1与右端点xi+1处的斜率K2的算术平均值作为平均斜率K*的近似值,那么就会得到二阶精度的改进拉格朗日中值定理:y(i+1)=y(i)+[h*(K1+K2)/2]K1=f(xi,yi)K2=f(…

    2022年10月22日
  • NMAKE编译CTK[通俗易懂]

    NMAKE编译CTK[通俗易懂]NMAKE编译CTK启动编译环境从VC中启动命令行或通过VC提供的批处理启动命令行,以能运行编译环境。如果装了多个VC版本,注意使用想要的VC版本启动安装编译环境。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5YlX5Gta-1597631378020)(study/image-20200815174602043.png)]再启动cmaked:\soft\ProgramFiles(x86)\MicrosoftVisualtudio\2017\Commun

    2022年6月5日

发表回复

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

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