我是靠谱客的博主 能干灯泡,这篇文章主要介绍struts2之json请求的异常处理方案,现在分享给大家,希望可以做个参考。

大家都知道,使用struts2的异常处理机制,只要几行配置,就可以在发生异常时,跳转到我们指定的页面,并显示出相应的异常信息,具体的使用操作过程如下:

1)struts.xml

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<struts> <include file="struts-default.xml"></include>     <constant name="struts.devMode" value="true" /><!-- 实现国际化资源文件和struts配置文件自动重新加载,不需要重启服务器 -->     <constant name="struts.ui.theme" value="simple" />     <constant name="struts.action.extension" value="," /><!-- 不要后缀 -->     <constant name="struts.enable.SlashesInActionNames" value="true" /><!-- 使用"/"的方式 -->     <package name="hatch" namespace="" extends="json-default"><!-- json支持 --> ... <!-- 定义全局视图 -->     <global-results> <result name="login" type="redirectAction">login</result> <result name="404">/WEB-INF/view/404.jsp</result> <result name="500">/WEB-INF/view/500.jsp</result>     </global-results>     <!-- 定义全局异常-->     <global-exception-mappings> <exception-mapping result="500" exception="java.lang.Exception"/><!-- 出现异常时,将页面转到500这个错误页面 -->     </global-exception-mappings> ... </struts>

2)500.jsp

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>程序异常</title> <%@include file="/WEB-INF/view/common/common.jspf" %> <style type="text/css"> *{margin:0;padding:0;} .errTitle{min-width:300px;width:90%;height:50px;line-height:50px;border:1px solid #999999;border-radius:5px;background:#0169B2;text-align:center;word-spacing:10px;font-family:'黑体';font-size:24px;margin:10px 70px;padding: 4px 4px 4px 6px;position:relative;} .showErrWrap{font-size:10px;position:absolute;right:10px;bottom:-5px;} .showErrWrap a:link,.showErrWrap a:visited{text-decoration:none;color:black;} .showErrWrap a:hover{text-decoration:underline;color:yellow;} .showErrWrap span{margin:0 4px;color:black;} .errStack{min-width:300px;width:90%;font-family:"Courier New", Courier, monospace;border:0 none;margin:10px 70px;overflow:auto;padding:4px;} </style> <script type="text/javascript"> $(function(){ $('#showErrBtn').toggle(function(){ $('#showErrBtn').text('关闭详情'); $('.errStack').slideDown('normal'); },function(){ $('.errStack').slideUp('normal'); $('#showErrBtn').text('查看详情'); }); }); if (window.parent != window) { window.parent.location.href = window.location.href; } </script> </head> <body> <div class="errTitle">程 序 出 现 异 常!<span class="showErrWrap"><a href="javascript:void(0);" id="showErrBtn">查看详情</a><span>|</span><a href="javascript:void(0);" οnclick="javascript:history.go(-1);">返回上一页</a></span></div> <div class="errStack" style="display:none;"><pre> <s:property value="exceptionStack"/><!-- 异常信息 --> </pre> </div> </body> </html>

假设在UserAction.java中有一个跳转到列表页面的方法,如下:

复制代码
1
2
3
4
5
/* 用户列表视图 */ public String list() { int i = 10/0; return "list"; }

这样,在出现异常时,就能到这个页面了,效果大约是下面的样子:


但现在我很多请求处理,使用的都是ajax提交请求并获取数据的方式,这种情况下,默认的异常处理就力不从心了。跑个题儿先,稍微介绍下struts2中ajax请求的配置方式,以下以用户列表为例:

1)添加jar包支持:struts2-json-plugin-2.3.4.jar

2)在自己的struts.xml中,package继承json-default

3)返回类型为json

4)Action中添加设置返回的数据的值

如下是配置:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<struts> <constant name="struts.devMode" value="true" /><!-- 实现国际化资源文件和struts配置文件自动重新加载,不需要重启服务器 --> <constant name="struts.ui.theme" value="simple" /> <constant name="struts.action.extension" value="," /><!-- 不要后缀 --> <constant name="struts.enable.SlashesInActionNames" value="true" /><!-- 使用"/"的方式 --> <package name="hatch" namespace="" extends="json-default"> <!-- json支持 --> ... <action name="user/*" class="userAction" method="{1}">             <result name="list">/WEB-INF/view/sys/user/list.jsp</result>             <result name="saveOrUpdate">/WEB-INF/view/sys/user/saveOrUpdate.jsp</result>             <result name="assginRole">/WEB-INF/view/sys/user/assginRole.jsp</result>             <result type="json">                 <param name="root">dataMap</param>                 <param name="excludeProperties">rows[d+].department.parent,rows[d+].department.users,rows[d+].department.children,rows[d+].roles</param>             </result><!-- ajax请求的返回视图 -->         </action>
如下是页面:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <%@include file="/WEB-INF/view/common/common.jspf"%> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>用户列表</title> <script type="text/javascript"> $(function(){ //用户列表初始化 $('#dg').datagrid({ striped : true, rownumbers : true, singleSelect : false, pagination : true, pageSize : 10, fitColumn : true, dataType : 'json', animate : true, loadMsg : '请稍候...', url:'${ctx }/sys/user/doList', columns:[[ {field:'ck',checkbox:true,align:'center'}, {title:'序号',field:'id',align:'center'}, {title:'登录名',field:'username',align:'center'}, {title:'名称',field:'name',align:'center'}, {title:'性别',field:'gender',align:'center',formatter:function(v){ return v==1?'男':'女' }}, {title:'手机',field:'phoneNumber',align:'center'}, {title:'email',field:'email',align:'center'}, {title:'所属部门',field:'department',align:'center',formatter:function(v){if(v)return v['name'];}}, {title:'操作',field:'Operation',align:'center',formatter: operationFormate} ]], });//easyui的列表请求,返回数据为json //添加操作列 function operationFormate(value,node){ var str='<a style="color:green;text-decoration:none;margin-right:4px;" href="javascript:void(0);" οnclick="update('+node.id+')">修改</a>' +'<a style="color:red;text-decoration:none;margin-right:4px;" href="javascript:void(0);" οnclick="del('+node.id+')">删除</a>' +'<a style="color:green;text-decoration:none;margin-right:4px;" href="javascript:void(0);" οnclick="assignrole('+node.id+')">角色分配</a>' +'<a style="color:red;text-decoration:none;" href="javascript:void(0);" οnclick="resetPwd('+node.id+')">密码重置</a>'; return str; } //查询用户 $('#queryBtn').click(function(){ var queryParams = $('#dg').datagrid('options').queryParams; var name = $.trim($('#queryForm').find('input[name=name]').val()); var gender = $.trim($('#queryForm').find('select[name=gender]').val()); queryParams.name = name; queryParams.gender = gender; $('#dg').datagrid('options').queryParams=queryParams; $('#dg').datagrid('reload'); }); //添加用户 $('#addBtn').click(function(){ window.location.href="${ctx}/sys/user/save"; }); //删除用户 $('#delBtn').click(function(){ var ss = new Array(); var rows = $('#dg').datagrid('getSelections'); for(var i=0; i<rows.length; i++){ var row = rows[i]; ss.push(row.id); } del(ss.join(',')); }); }); //修改用户 function update(id){ window.location.href="${ctx}/sys/user/update?id="+id; } //删除用户 function del(ids){ $.messager.confirm('确认框', '确认要删除吗?此操作是不可恢复的', function(r){ if (r){ var url = '${ctx }/sys/user/del'; $.post(url, { ids:ids }, function(data){ if(data.result==0){ $('#dg').datagrid('reload'); }else{ $.messager.alert('error','失败'); } alert(data.result); },'json'); } }); } //分配角色 function assignrole(id){ window.location.href="${ctx}/sys/user/assginRole?id="+id; } //密码重置 function resetPwd(id){ var url = '${ctx }/sys/user/doResetPwd1'; $.post(url, { id:id }, function(data){ if(data.result==0){ $.messager.alert('信息提示','修改成功,密码重置为111111!','info'); }else{ var msg = data.msg; $.messager.alert('错误提示','操作失败!','error'); window.location = "${ctx}/jsonHandlerAction"; } },'json'); } </script> </head> <body> <div class="ptitle">系统管理>>用户列表</div> <div class="content-wrap"> <div class="pcontent"> <div class="easyui-panel toolbar"> <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-add" plain="true" id="addBtn">新建</a> <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-remove" plain="true" id="delBtn">删除</a> <s:form action="/user/doList" namespace="/" method="post" id="queryForm"> 名称:<s:textfield name="name"/> 性别:<s:select list="#{null:'全部',1:'男',2:'女'}" name="gender"/> <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-search" id="queryBtn">Search</a> </s:form> </div> <!-- 列表 --> <table id="dg" title=""></table> </div> </div> </body>
如下是Action

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
/* 用户 列表数据 */ public String doList(){ HttpServletRequest re = ServletActionContext.getRequest(); dataMap = new HashMap<String, Object>(); Map<String, Object> cond = MapBeanUtil.transBean2Map(user); Page<User> p = new Page<User>(); cond.put("page", Integer.parseInt(re.getParameter("page"))); cond.put("rows", Integer.parseInt(re.getParameter("rows"))); p = userService.findUserForPage(cond); dataMap.put("total", p.getTotal()); dataMap.put("rows", p.getRows()); return SUCCESS; }
效果如下:



以上是json开发的简单介绍,更详细的可以下载相关文档。

返回正题,假如正在我在Action中出现异常,可怕的事情:框架将错误页面的html代码以html的形式返回来了,以下是用firefox看到的结果:


分析思考:

struts2的异常处理,是基于拦截器的,出现目前的错误,就是因为拦截器的异常处理,没有考虑到ajax异步请求,那么是哪个拦截器处理异常呢?打开struts核心包struts2-core-2.3.4.jar中的struts-default.xml中,查看下面的信息:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
<interceptors> <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" /> <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" /> <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> 。。。
发现异常是这个类com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor来处理的,因此,一个最简单的办法,就是将该类覆写,加上json请求的支持。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
/* * Copyright 2002-2006,2009 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.opensymphony.xwork2.interceptor; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsStatics; import com.hatch.common.JsonHandlerException; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.util.logging.Logger; import com.opensymphony.xwork2.util.logging.LoggerFactory; /** * <!-- START SNIPPET: description --> * * This interceptor forms the core functionality of the exception handling * feature. Exception handling allows you to map an exception to a result code, * just as if the action returned a result code instead of throwing an * unexpected exception. When an exception is encountered, it is wrapped with an * {@link ExceptionHolder} and pushed on the stack, providing easy access to the * exception from within your result. * * <b>Note:</b> While you can configure exception mapping in your configuration * file at any point, the configuration will not have any effect if this * interceptor is not in the interceptor stack for your actions. It is * recommended that you make this interceptor the first interceptor on the * stack, ensuring that it has full access to catch any exception, even those * caused by other interceptors. * * <!-- END SNIPPET: description --> * * <p/> * <u>Interceptor parameters:</u> * * <!-- START SNIPPET: parameters --> * * <ul> * * <li>logEnabled (optional) - Should exceptions also be logged? (boolean * true|false)</li> * * <li>logLevel (optional) - what log level should we use ( * <code>trace, debug, info, warn, error, fatal</code>)? - defaut is * <code>debug</code></li> * * <li>logCategory (optional) - If provided we would use this category (eg. * <code>com.mycompany.app</code>). Default is to use * <code>com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor</code>. * </li> * * </ul> * * The parameters above enables us to log all thrown exceptions with stacktace * in our own logfile, and present a friendly webpage (with no stacktrace) to * the end user. * * <!-- END SNIPPET: parameters --> * * <p/> * <u>Extending the interceptor:</u> * * <p/> * * <!-- START SNIPPET: extending --> * * If you want to add custom handling for publishing the Exception, you may * override * {@link #publishException(com.opensymphony.xwork2.ActionInvocation, ExceptionHolder)} * . The default implementation pushes the given ExceptionHolder on value stack. * A custom implementation could add additional logging etc. * * <!-- END SNIPPET: extending --> * * <p/> * <u>Example code:</u> * * <pre> * <!-- START SNIPPET: example --> * <xwork> * <package name="default" extends="xwork-default"> * <global-results> * <result name="error" type="freemarker">error.ftl</result> * </global-results> * * <global-exception-mappings> * <exception-mapping exception="java.lang.Exception" result="error"/> * </global-exception-mappings> * * <action name="test"> * <interceptor-ref name="exception"/> * <interceptor-ref name="basicStack"/> * <exception-mapping exception="com.acme.CustomException" result="custom_error"/> * <result name="custom_error">custom_error.ftl</result> * <result name="success" type="freemarker">test.ftl</result> * </action> * </package> * </xwork> * <!-- END SNIPPET: example --> * </pre> * * <p/> * This second example will also log the exceptions using our own category * <code>com.mycompany.app.unhandled<code> at WARN level. * * <pre> * <!-- START SNIPPET: example2 --> * <xwork> * <package name="something" extends="xwork-default"> * <interceptors> * <interceptor-stack name="exceptionmappingStack"> * <interceptor-ref name="exception"> * <param name="logEnabled">true</param> * <param name="logCategory">com.mycompany.app.unhandled</param> * <param name="logLevel">WARN</param> * </interceptor-ref> * <interceptor-ref name="i18n"/> * <interceptor-ref name="staticParams"/> * <interceptor-ref name="params"/> * <interceptor-ref name="validation"> * <param name="excludeMethods">input,back,cancel,browse</param> * </interceptor-ref> * </interceptor-stack> * </interceptors> * * <default-interceptor-ref name="exceptionmappingStack"/> * * <global-results> * <result name="unhandledException">/unhandled-exception.jsp</result> * </global-results> * * <global-exception-mappings> * <exception-mapping exception="java.lang.Exception" result="unhandledException"/> * </global-exception-mappings> * * <action name="exceptionDemo" class="org.apache.struts2.showcase.exceptionmapping.ExceptionMappingAction"> * <exception-mapping exception="org.apache.struts2.showcase.exceptionmapping.ExceptionMappingException" * result="damm"/> * <result name="input">index.jsp</result> * <result name="success">success.jsp</result> * <result name="damm">damm.jsp</result> * </action> * * </package> * </xwork> * <!-- END SNIPPET: example2 --> * </pre> * * @author Matthew E. Porter (matthew dot porter at metissian dot com) * @author Claus Ibsen */ public class ExceptionMappingInterceptor1 extends AbstractInterceptor { protected static final Logger LOG = LoggerFactory .getLogger(ExceptionMappingInterceptor.class); protected Logger categoryLogger; protected boolean logEnabled = false; protected String logCategory; protected String logLevel; public boolean isLogEnabled() { return logEnabled; } public void setLogEnabled(boolean logEnabled) { this.logEnabled = logEnabled; } public String getLogCategory() { return logCategory; } public void setLogCategory(String logCatgory) { this.logCategory = logCatgory; } public String getLogLevel() { return logLevel; } public void setLogLevel(String logLevel) { this.logLevel = logLevel; } @Override public String intercept(ActionInvocation invocation) throws Exception { String result; try { result = invocation.invoke(); } catch (Exception e) { ActionContext actionContext = invocation.getInvocationContext(); HttpServletRequest request = (HttpServletRequest) actionContext .get(StrutsStatics.HTTP_REQUEST); if (isAjaxRequest(request)) {//如果是ajax请求方式 ValueStack stack = invocation.getStack(); List<ExceptionMappingConfig> exceptionMappings = invocation .getProxy().getConfig().getExceptionMappings(); JsonHandlerException je = new JsonHandlerException(e); String mappedResult = this.findResultFromExceptions( exceptionMappings, je); result = mappedResult; Map<String, Object> dataMap = new HashMap<String, Object>(); stack.set("dataMap", dataMap); dataMap.put("result", "500"); StringBuffer msg = new StringBuffer(e.toString()+"n"); StackTraceElement[] trace = e.getStackTrace(); for (int i=0; i < trace.length; i++) msg.append("tat " + trace[i]+"n"); ServletActionContext.getRequest().getSession().setAttribute("errMsg", msg); }else{// 默认处理方式 if (isLogEnabled()) { handleLogging(e); } List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings(); String mappedResult = this.findResultFromExceptions(exceptionMappings, e); if (mappedResult != null) { result = mappedResult; publishException(invocation, new ExceptionHolder(e)); } else { throw e; } invocation.getStack(); invocation.getInvocationContext().get(Action.ERROR); // invocation.getStack().findString("exceptionStack"); invocation.getInvocationContext().get(Action.ERROR); } } return result; } private boolean isAjaxRequest(HttpServletRequest request) { String header = request.getHeader("X-Requested-With"); if (header != null && "XMLHttpRequest".equals(header)) return true; else return false; } /** * Handles the logging of the exception. * * @param e * the exception to log. */ protected void handleLogging(Exception e) { if (logCategory != null) { if (categoryLogger == null) { // init category logger categoryLogger = LoggerFactory.getLogger(logCategory); } doLog(categoryLogger, e); } else { doLog(LOG, e); } } /** * Performs the actual logging. * * @param logger * the provided logger to use. * @param e * the exception to log. */ protected void doLog(Logger logger, Exception e) { if (logLevel == null) { logger.debug(e.getMessage(), e); return; } if ("trace".equalsIgnoreCase(logLevel)) { logger.trace(e.getMessage(), e); } else if ("debug".equalsIgnoreCase(logLevel)) { logger.debug(e.getMessage(), e); } else if ("info".equalsIgnoreCase(logLevel)) { logger.info(e.getMessage(), e); } else if ("warn".equalsIgnoreCase(logLevel)) { logger.warn(e.getMessage(), e); } else if ("error".equalsIgnoreCase(logLevel)) { logger.error(e.getMessage(), e); } else if ("fatal".equalsIgnoreCase(logLevel)) { logger.fatal(e.getMessage(), e); } else { throw new IllegalArgumentException("LogLevel [" + logLevel + "] is not supported"); } } protected String findResultFromExceptions( List<ExceptionMappingConfig> exceptionMappings, Throwable t) { String result = null; // Check for specific exception mappings. if (exceptionMappings != null) { int deepest = Integer.MAX_VALUE; for (Object exceptionMapping : exceptionMappings) { ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) exceptionMapping; int depth = getDepth(exceptionMappingConfig .getExceptionClassName(), t); if (depth >= 0 && depth < deepest) { deepest = depth; result = exceptionMappingConfig.getResult(); } } } return result; } /** * Return the depth to the superclass matching. 0 means ex matches exactly. * Returns -1 if there's no match. Otherwise, returns depth. Lowest depth * wins. * * @param exceptionMapping * the mapping classname * @param t * the cause * @return the depth, if not found -1 is returned. */ public int getDepth(String exceptionMapping, Throwable t) { return getDepth(exceptionMapping, t.getClass(), 0); } private int getDepth(String exceptionMapping, Class exceptionClass, int depth) { if (exceptionClass.getName().contains(exceptionMapping)) { // Found it! return depth; } // If we've gone as far as we can go and haven't found it... if (exceptionClass.equals(Throwable.class)) { return -1; } return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1); } /** * Default implementation to handle ExceptionHolder publishing. Pushes given * ExceptionHolder on the stack. Subclasses may override this to customize * publishing. * * @param invocation * The invocation to publish Exception for. * @param exceptionHolder * The exceptionHolder wrapping the Exception to publish. */ protected void publishException(ActionInvocation invocation, ExceptionHolder exceptionHolder) { invocation.getStack().push(exceptionHolder); } }
这里说明下,如果是出现异常,而且是ajax请求的话,就找JsonHandlerException这个异常所对应的视图:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 定义全局视图 --> <global-results> <result name="login" type="redirectAction">login</result> <result name="404">/WEB-INF/view/404.jsp</result> <result name="500">/WEB-INF/view/500.jsp</result> <result name="json_500" type="json"><param name="root">dataMap</param></result> <result type="json"><param name="root">dataMap</param></result><!-- ajax请求的返回视图 --> </global-results> <!-- 定义全局异常--> <global-exception-mappings> <exception-mapping result="500" exception="java.lang.Exception"/> <exception-mapping result="json_500" exception="com.hatch.common.JsonHandlerException"/> </global-exception-mappings> ...

下面是自定义Json异常类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.hatch.common; public class JsonHandlerException extends Exception { /** * */ private static final long serialVersionUID = -4788951533205831941L; public JsonHandlerException() { super(); } public JsonHandlerException(String message) { super(message); } public JsonHandlerException(String message, Throwable cause) { super(message, cause); } public JsonHandlerException(Throwable cause) { super(cause); } }
这样在页面一端,就可以正确的获取异常数据了。

对于普通的$.post请求,这个异常数据很容易可以人性化的提示给用户,这里用的easyui,可以在数据表格加载时,验证下有没有返回数据:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$('#dg').datagrid({ striped : true, rownumbers : true, singleSelect : false, pagination : true, pageSize : 10, fitColumn : true, dataType : 'json', animate : true, loadMsg : '请稍候...', url:'${ctx }/sys/user/doList', loadFilter:function(data){ if(!data.rows||!data.total){ if(data.msg){ $.messager.alert('错误提示','操作失败!错误原因:<hr/>'+data.msg,'error'); }else{ $.messager.alert('错误提示','操作失败!','error'); } return {total:0,rows:[]}; } }, columns:[[ {field:'ck',checkbox:true,align:'center'}, {title:'序号',field:'id',align:'center'}, {title:'登录名',field:'username',align:'center'}, {title:'名称',field:'name',align:'center'}, {title:'性别',field:'gender',align:'center',formatter:function(v){ return v==1?'男':'女' }}, {title:'手机',field:'phoneNumber',align:'center'}, {title:'email',field:'email',align:'center'}, {title:'所属部门',field:'department',align:'center',formatter:function(v){if(v)return v['name'];}}, {title:'操作',field:'Operation',align:'center',formatter: operationFormate} ]], });

以上红色字体表示数据加载异常时,提示给用户错误信息,效果如下:

当然,如果想做一致的处理,像默认的拦截器那样定位到一个错误页面,可以在这里加跳转信息:

复制代码
1
2
3
4
5
6
7
8
9
10
11
loadFilter:function(data){ if(!data.rows||!data.total){ if(data.msg){ $.messager.alert('错误提示','操作失败!错误原因:<hr/>'+data.msg,'error'); }else{ $.messager.alert('错误提示','操作失败!','error'); } window.location = '${ctx}/jsonHandlerAction' return {total:0,rows:[]}; } },
这样,又能跳转到我们默认的错误页面了:

这个错误信息,用了一个很笨的方法传递到错误页面,即在拦截器捕获到这个ajax操作的异常时 ,将这个异常信息加入到会话中,然后在js跳转后,在错误页面中取出错误信息。

至此,该方案介绍完毕,有更好方法的童鞋可以赐教!


最后

以上就是能干灯泡最近收集整理的关于struts2之json请求的异常处理方案的全部内容,更多相关struts2之json请求内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(73)

评论列表共有 0 条评论

立即
投稿
返回
顶部