Spring MVC exception Handling (internationalization of exception information, logging)

Source: Internet
Author: User
Tags getmessage

JAVA EE projects, whether it is the underlying data operations, business layer processing, or control layer processing, will inevitably encounter a variety of predictable (business exception unsolicited), unpredictable exceptions need to be handled. General DAO layer, service layer exception will be thrown directly, and finally by the Controller unified processing, each process is handled by the exception, and to take into account the exception information and front-end feedback, the code of high coupling, not uniform, post-maintenance work is also many.

It must also consider the exception module and log module, internationalization support.

Therefore, an exception handling mechanism is needed to decouple the anomaly understanding so as to ensure the function of the related processing process is single, decoupled from other modules of the system, and realizes the uniform processing and maintenance of the abnormal information.

The following is an example of the uniform processing of the spring MVC implementation exception in the actual work.

Analysis

First, look at the 3 ways that spring MVC handles exceptions, making comparisons and finally choosing a more appropriate way.

    1. Spring MVC provides a simple exception handler simplemappingexceptionresolver;
    2. Spring MVC exception Handling Interface Handlerexceptionresolver customize its own exception handler;
    3. @ExceptionHandler annotations for exception handling;
Simple Practice

For the first way, the use of simplemappingexceptionresolver can accurately display the defined exception handling page, exception handling, with simple integration, good extensibility, because it is based on the configuration of the existing code is not intrusive and other advantages. However, the method can only get exception information, which is not applicable for other data. The configuration method is as follows:

<bean class= "Org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" >          <!-- Defines the default exception handling page when the exception type is registered with-          <property name= "Defaulterrorview" value= "error" ></property>          <!--define the name of the variable that the exception handling page uses to get exception information, the default name is exception--and          <property name= "Exceptionattribute" value= "ex" ></ Property>          <!--define exceptions that require special handling, with the class name or full pathname as key, and the page name as the value--          <property name= "Exceptionmappings" >              <props>                  <prop key= "Cn.basttg.core.exception.BusinessException" >error-business</prop>                  <prop key= "cn.basttg.core.exception.ParameterException" >error-parameter</prop>                        <!-- You can also continue to extend the processing of different exception types-              </props>          </property>      </bean>  

For the second way, the exception handling using the implementation of the Handlerexceptionresolver interface has the advantages of simple integration, good extensibility, and no intrusion on existing code. At the same time, because of the custom implementation, we can deal with the exception when the additional processing (log records, the internationalization of exception information, etc.). The actual development of the project is also used in this integration scenario, configured as follows:


<bean id= "Exceptionresolver" class= "Com.***.**.common.exception.platformmappingexceptionresolver" >        <!--with custom exception resolver--        <property name= "exceptionmappings" ><props>      <prop key= "com.***.** . common.exception.BusinessException ">error/error</prop>      <prop key=" Java.lang.Exception "> Error/error</prop></props></property></bean>

For the third way, exception handling via @exceptionhandler annotations is also very flexible, but this approach needs to be annotated on each controller, and the solution is to add a Basecontroller class, Use @exceptionhandler annotations to declare exception handling, and all other controllers inherit him. Here's how it's implemented:

  public class Basecontroller {          /** based on @exceptionhandler exception handling          *          /@ExceptionHandler public String exp ( HttpServletRequest request, Exception ex) {                            request.setattribute ("Ex", Ex);                            Turn to different page              if (ex instanceof businessexception) {                  return "error-business" according to different errors;              } else if (ex instanceof parameterexception) {                  return "Error-parameter";              } else {                  return "error";              }          }      }  



This method is intrusive and does not get data beyond the exception when it is handled, and the exception information generated by the AJAX request cannot be fed back to the front end.


In a comprehensive consideration, the second method is used for the design of the Exception unified processing scheme.

Program Design

First, we analyze the needs that the scheme should meet.

Demand
    1. Error page jump: for example 404 pages. Based on spring MVC, the front-end access to a page to jump controller when an exception occurs, jump to the error page.
    2. Ajax exception Feedback: The front end through the Ajax way to access the controller to get JSON data anomalies, you need to feed the exception to the front end.
    3. Logging of exception information: The log module is used to implement the logging of the Exception Log.
    4. Internationalization of anomalous information: international design to achieve the internationalization of abnormal information.
Design

1. First, customize the exception parser, the code listing is as follows:

Package Com.cisdi.ecis.common.exception;import Java.io.printwriter;import Java.io.stringwriter;import Javax.servlet.http.httpservletrequest;import Javax.servlet.http.httpservletresponse;import Org.slf4j.Logger; Import Org.slf4j.loggerfactory;import Org.springframework.web.servlet.modelandview;import Org.springframework.web.servlet.handler.simplemappingexceptionresolver;import com.cisdi.ecis.common.utils.exceptioni18message;/** * * @author lcore * * Platform exception information jump, parsing * */public class Platformmappinge Xceptionresolver extendssimplemappingexceptionresolver {static Logger Logger = Loggerfactory.getlogger ( Platformmappingexceptionresolver.class); @Overrideprotected Modelandview doresolveexception (httpservletrequest Request,httpservletresponse response, Object handler, Exception ex) {String viewName = Determineviewname (ex, request);// The VM Way returns if (viewName! = null) {if (! (Request.getheader) ("accept"). IndexOf ("Application/json") >-1 | | (Request.getheader ("X-requested-with")! = null && requEst.getheader ("X-requested-with"). IndexOf ("XMLHttpRequest") >-1)) {//non-asynchronously returns integer StatusCode = Determinestatuscode (Request, ViewName), if (statusCode! = null) {applystatuscodeifpossible (Request, Response, StatusCode);} Jump to the prompt page return Getmodelandview (ViewName, ex, request);} else {//asynchronously returns the try {printwriter writer = Response.getwriter (); Writer.write (Exceptioni18message.getlocalemessage (        Ex.getmessage ())); Response.setstatus (404, Exceptioni18message.getlocalemessage (Ex.getmessage ())); Logs the exception stack information to the log logger.error (Gettrace (ex)); Writer.flush ();} catch (Exception e) {e.printstacktrace ();} Do not make page jump return null;}} else {return null;}}        public static String Gettrace (Throwable t) {StringWriter stringwriter= new StringWriter ();        PrintWriter writer= New PrintWriter (StringWriter);        T.printstacktrace (writer);        StringBuffer buffer= Stringwriter.getbuffer ();    return buffer.tostring (); }}


2. Then configure the Exception resolver mapping path in the spring MVC configuration file.

<!--Configure exception mapping path, AJAX hint--><bean id= "exceptionresolver"        class= " Com.cisdi.ecis.common.exception.PlatformMappingExceptionResolver "><property name=" Exceptionmappings "> <props><prop key= "Com.cisdi.ecis.common.exception.BusinessException" >error/error</prop>< Prop key= "Java.lang.Exception" >error/error</prop></props></property></bean>

3. Internationalization of abnormal information


In fact, the above configuration has satisfied most of the requirements of the solution, and there is only one requirement: the internationalization of abnormal information. The code above has a section of code:

Exceptioni18message.getlocalemessage (Ex.getmessage ()

Exceptioni18message is based on the current language environment to get exception information, the implementation details are as follows:

Package Com.cisdi.ecis.common.utils;import Javax.servlet.http.httpservletrequest;import Org.springframework.web.context.request.requestcontextholder;import Org.springframework.web.context.request.servletrequestattributes;import Org.springframework.web.servlet.support.requestcontext;public class exceptioni18message{public       static String Getlocalemessage (String key) {    HttpServletRequest request =  ((servletrequestattributes) Requestcontextholder.getrequestattributes ()). Getrequest ();    RequestContext RequestContext = new RequestContext (request);    return Requestcontext.getmessage (key);}    }

About Internationalization: http://1.liangtao.sinaapp.com/?p=756


The backend programmer can throw a business exception directly while coding, but the pressed message should be the "key" in the Internationalized file, and the value of the key that is written in multiple sets of languages in the internationalization file itself. For example:

# #Exceptionpbs. exception.copynode=the exceptioninfo i18n

The exception information that we press in after this is Pbs.exception.copyNode:


throw new Exception ("Pbs.exception.copyNode");

Test

So far, the scheme has been designed, the simple test is to meet our needs, the exception for the page jump is not tested here, mainly in front-end Ajax request controller throws a business exception when the front end can receive feedback.

Front-End Code:

$.ajax ({                URL: "${basepath}/doc/adddocmaterials",                type: "Post",                DataType: "JSON",                Data:obj,                Complete:function (XHR) {                    console.log (XHR);                    if (Xhr.status = = && Xhr.responsetext! = null) {} else {                        $.messager.alert (' #springMessage ("Message.tip") ', xhr.responsetext);                        Displayload ();}}                );

When the backend proactively throws a business exception, the feedback from the front end is as follows: (Here we take the code that throws the exception above).


To this end, the unified processing scheme for Spring MVC Exceptions (internationalization, Ajax feedback) ends.



Spring MVC exception Handling (internationalization of exception information, logging)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.