Spring MVC Exception handler (перехват исключений). Настройка логирования в Spring MVC с помощью Logback
Перехват исключений (Exception Handling) в Spring MVC. Настройка логирования в Spring MVC с помощью Logback.
Обзор приложения Spring MVC + AngularJS + Bootstrap + HTML5
Используемые технологии и библиотеки
- Spring MVC 4.2.4.Release
- Logback 1.0.13
- SLF4J 1.7.13
- Maven 3.2.5
- IntelliJ IDEA 15.0.2
1. Описание задачи
Рассмотрим как обрабатывать исключения в приложении Spring MVC. При этом добавим к нашему приложению логирование ошибок и действий в приложении с помощью библиотеки Logback.
2. Структура проекта
Для реализации задачи перехвата исключений и выполнения логирования в приложении были добавлены классы ExceptionController и ExceptionHandler. Контроллер служит для вызова метода, который будет выбрасывать исключение. Это исключение мы будем обрабатывать с помощью класса ExceptionHandler. Внутри обработчика исключений был добавлен класс Logger для записи необходимых событий в приложении (данные будут выводиться в консоль и записываться в файл на диске). При перехвате исключения пользователь будет перенаправлен на страницу exception.jsp.
3. Подключение зависимостей в pom.xml
Для перехвата и обработки исключений никаких дополнительных зависимостей относительно предыдущего раздела подключать не нужно. Всё уже находится в подключенных зависимостях Spring MVC. Для логирования будет использована современная библиотека Logback.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!-- Logging --> <!--logback - improved version of log4j--> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.13</slf4j.version> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> <scope>runtime</scope> </dependency> |
pom.xml целиком:
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 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>ru.javastudy</groupId> <artifactId>mvc_html5_angular</artifactId> <version>1.0</version> <properties> <!-- Generic properties --> <java.version>1.8</java.version> <!-- Web --> <jsp.version>2.2</jsp.version> <jstl.version>1.2</jstl.version> <servlet.version>3.1.0</servlet.version> <!-- Spring --> <spring-framework.version>4.2.4.RELEASE</spring-framework.version> <!-- JUnit test --> <junit.version>4.12</junit.version> <!-- Logging --> <!--logback - improved version of log4j--> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.13</slf4j.version> <!-- jackson json JSON Processing API --> <jackson.databind-version>2.2.3</jackson.databind-version> <!-- Hibernate / JPA --> <hibernate.version>5.0.1.Final</hibernate.version> <!-- I don't know why, but with 5.0.5 final app not working! --> <!-- Spring Data --> <spring-framework.data.version>1.9.1.RELEASE</spring-framework.data.version> </properties> <dependencyManagement> <!--all spring dependencies --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>${spring-framework.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!--bootstrap webjars.org--> <dependencies> <!-- Spring MVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <!-- Other Servlet Web dependencies --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <!--Servlet API--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <!-- Apache Commons File Upload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!-- Excel view --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.12</version> </dependency> <!-- PDF view --> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.5</version> </dependency> <!-- HSQLDB embedded database. Встроенная база данных--> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.3.3</version> </dependency> <!-- Spring JDBC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <!--JUnit Test--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- Test Artifacts with Spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <scope>test</scope> </dependency> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> <scope>runtime</scope> </dependency> <!--Contains org.springframework.mail.javamail--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Spring MVC Mail Related Dependency --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <!-- Spring REST jackson JSON Processing API --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.databind-version}</version> </dependency> <!--Hibernate ORM--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <!--Hibernate validator (contains @NotEmpty)--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.1.0.Final</version> </dependency> <!--Spring Data--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring-framework.data.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> <source>1.8</source> <target>1.8</target> <compilerArgument>-Xlint:all</compilerArgument> <showWarnings>true</showWarnings> <showDeprecation>true</showDeprecation> </configuration> </plugin> </plugins> <!--need to find configs in tests in package web-inf like @ContextConfiguration(locations = {"classpath:/config/application-context.xml" --> <testResources> <testResource> <directory>src/main/webapp/WEB-INF/config</directory> </testResource> </testResources> </build> </project> |
4. Настройка конфигурации spring mvc
Файлы конфигурации spring так же остались без изменений. Для класса обработчика исключений будет использована аннотация и реализация интерфейса. Поэтому приведу полные файлы под катом.
application-context.xml:
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 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd "> <!--find property file. See bean id='dataSource' for example ${jdbc.hsqldb.driverClass}--> <context:property-placeholder location="classpath:util.properties" /> <!-- XML Bean Definitions --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.hsqldb.driverClass}" /> <property name="url" value="${jdbc.hsqldb.url}" /> <property name="username" value="${jdbc.hsqldb.username}" /> <property name="password" value="${jdbc.hsqldb.password}" /> </bean> <!-- initialize Embedded DataSource. Встроенная база данных--> <jdbc:initialize-database data-source="dataSource"> <jdbc:script location="classpath:dbschema.sql"/> <jdbc:script location="classpath:test-data.sql"/> </jdbc:initialize-database> <!-- Java Mail Configuration --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="username" value="${java.mail.username}"/> <property name="password" value="${java.mail.password}"/> <property name="port" value="465"/> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">true</prop> <prop key="mail.smtp.starttls.enable">true</prop> <prop key="mail.smtp.starttls.required">true</prop> <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> <prop key="mail.smtp.host">${java.mail.host}</prop> </props> </property> </bean> <!-- Velocity Email Template Config Bean --> <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean"> <property name="resourceLoaderPath" value="/WEB-INF/email-templates/"/> </bean> <!-- REST template configuration --> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/> <!--Do not forget activate @Transactional JPA annotation with <annotation-driven/>--> <!-- JPA Persistence Context and EntityManager configuration --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" > <!--packagesToScan - search Entity and mapping them --> <property name="packagesToScan" value="ru.javastudy.mvcHtml5Angular.mvc.bean" /> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" > <property name="generateDdl" value="true" /> <property name="showSql" value="true" /> </bean> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <!-- Automatic Transaction Participation--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <!--not uses but could autowired in JDBCExample bean--> <!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> --> </beans> |
mvc-config.xml:
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 |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- context:component-scan This tag will scan @Component, @Repository, @Service, @Controller and also resolves @Autowired and @Qualifier --> <context:component-scan base-package="ru.javastudy.mvcHtml5Angular.mvc" /> <!-- mvc:annotation-driven configures Spring MVC annotations Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath. HttpMessageConverter support for @RequestBody method parameters and @ResponseBody method return values from @RequestMapping or @ExceptionHandler methods. --> <mvc:annotation-driven/> <!-- activate @Transactional JPA annotation --> <tx:annotation-driven/> <!-- ViewResolver bean config for mapping strings to jsp views --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' --> <property name="order" value="1" /> <property name="prefix" value="/WEB-INF/view/" /> <property name="suffix" value=".jsp" /> </bean> <!-- File Upload bean config--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- set the maximum file size in bytes --> <property name="maxUploadSize" value="1000000"/> </bean> <!--Excel and PDF xml view configuration --> <!--disabling for jUnit test. --> <bean class="org.springframework.web.servlet.view.XmlViewResolver"> <property name="order" value="0" /> <property name="location" value="/WEB-INF/config/excel-pdf-config.xml"/> </bean> <mvc:view-controller path="/index.html" view-name="/index"/> <mvc:view-controller path="/about.html" view-name="/about/about"/> <mvc:view-controller path="/file.html" view-name="/file/file"/> <mvc:view-controller path="/jdbc.html" view-name="/jdbc/jdbc"/> <mvc:view-controller path="/email.html" view-name="/email/email"/> <mvc:view-controller path="/rest.html" view-name="/rest/rest"/> <mvc:view-controller path="/orm.html" view-name="/orm/orm"/> <!-- Static Resources Configuration (get access to static sources such as CSS and JavaScript files) --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- themes can be put in different folder such as <mvc:resources mapping="/resources/**" location="/resources/themeBlue" /> <mvc:resources mapping="/resources/**" location="/resources/themeGreen" /> --> </beans> |
5. web.xml
Дополнительно ничего добавлено не было.
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 |
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>mvc-html5-angularjs</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value> WEB-INF/config/application-context.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/mvc-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--Позволяет работать с русскими символами--> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>/WEB-INF/view/index.jsp</welcome-file> </welcome-file-list> <error-page> <error-code>404</error-code> <location>/WEB-INF/view/error/errorstatus.jsp</location> </error-page> </web-app> |
6. Java классы (контроллер и обработчик исключений)
Контроллер ну очень простой. При переходе по ссылке вида /runtimeException в методе будет искусственно выброшено RuntimeException исключение.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package ru.javastudy.mvcHtml5Angular.mvc.exception; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; /** * Created for JavaStudy.ru on 02.03.2016. */ @Controller public class ExceptionController { @RequestMapping(value = "/runtimeException", method = RequestMethod.GET) public void throwException( ) { throw new RuntimeException(); } } |
Это исключение мы будет обрабатывать в классе, который реализует интерфейс HandlerExceptionResolver. В Spring MVC достаточно реализовать этот интерфейс для перехвата исключений и их обработке по своему усмотрению:
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 |
package ru.javastudy.mvcHtml5Angular.mvc.exception; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Created for JavaStudy.ru on 02.03.2016. */ @Component public class ExceptionHandler implements HandlerExceptionResolver { private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class); @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { System.out.println("Spring MVC ExceptionHandler handling"); logger.error("ErrorLog: ", e); return new ModelAndView("error/exception", "exceptionMsg", "ExceptionHandler msg: " + e.toString()); } } |
При перехвате исключения мы можем запрограммировать любое поведение. Здесь мы просто логируем ошибку и передаем ViewResolver представление, на которое мы должны быть переброшены (в данном случае на страницу exception.jsp) и саму ошибку в переменной exceptionMsg.
Обратите внимание — оба класса отмечены аннотацией @Component и поэтому они оба будут находиться в контексте spring приложения и работать как нам нужно.
7. JSP Представление
На странице просто выводится сообщение, которое записано в объекте {exceptionMsg}, которое формируется на этапе выше.
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 |
<!DOCTYPE html> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> <%@ taglib prefix="page" tagdir="/WEB-INF/tags" %> <page:template> <jsp:body> <!-- Page Content --> <div class="container"> <div class="row"> <div class="col-lg-12"> <h1 class="page-header">Страница ошибки <small>exception handler</small> </h1> <ol class="breadcrumb"> <li><a href="index.html">Home</a> </li> <li class="active">Exception Handler</li> </ol> </div> </div> <!-- /.row --> <!-- Content Row --> <div class="row"> <div class="col-lg-12"> <p>This is message from ExceptionHandler:</p> <b>${exceptionMsg}</b> </div> </div> <!-- /.row --> <hr> </div> <!-- /.container --> </jsp:body> </page:template> |
8. Логирование
Как вы заметили в java классах использовался объект Logger. Для начала вам нужно создать файл logback.xml и поместить его в папку resources. В самом начале логер будет искать этот конфигурационный файл и будет с ним связан. Ниже приведены настройки для логирования.
logback.xml:
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 |
<?xml version="1.0" encoding="UTF-8"?> <!-- configuration file for LogBack (slf4J implementation) See here for more details: http://gordondickens.com/wordpress/2013/03/27/sawing-through-the-java-loggers/ --> <configuration scan="true" scanPeriod="30 seconds"> <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"> <resetJUL>true</resetJUL> </contextListener> <!-- To enable JMX Management --> <jmxConfigurator/> <!--Write logs in this file --> <property name="LOG_HOME" value="c:/springmvc-angularjs-html5/logs" /> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%-5level %logger{0} - %msg%n</pattern> </encoder> </appender> <!-- File Logging --> <appender name="file" class="ch.qos.logback.core.FileAppender"> <file>${LOG_HOME}/error.log</file> <encoder> <pattern>%-5level %logger{0} - %msg%n</pattern> </encoder> </appender> <!--<logger name="org.hibernate" level="debug"/> --> <!-- Uncomment and add your logger here: <logger name="org.springframework.samples.service.service" level="debug"/> --> <root level="error"> <!-- uncomment file--> <!--If you want to write to file - uncomment it--> <appender-ref ref="file"/> <appender-ref ref="console"/> </root> </configuration> |
Первое на что обратить внимание — строчка
1 |
<property name="LOG_HOME" value="c:/springmvc-angularjs-html5/logs" /> |
Здесь задается свойство, которое будет использовано как указание пути расположения файла с логами на диске. Далее идет указание к какому файлу будут прикрепляться логи (файл error.log) и какой будет для этого использован шаблон записи. Чуть ниже выставлен уровень debug. (Здесь так же закомментировано логирование для Hibernate, если хотите — можете раскоментить и посмотреть предыдущую тему по настройке ORM Hibernate).
В конце прописано куда будут записываться логи (если не хотите записи в файл или консоль, то закомментируйте\удалите соответствующую строчку, например для записи в файл — <appender-ref ref=»file»/> ).
9. Тестирование приложения
После перехода по ссылке Runtime Exception в меню сайта, мы получим в консоль следующую запись:
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 |
Spring MVC ExceptionHandler handling ERROR ExceptionHandler - ErrorLog: java.lang.RuntimeException: null at ru.javastudy.mvcHtml5Angular.mvc.exception.ExceptionController.throwException(ExceptionController.java:15) ~[ExceptionController.class:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_65] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_65] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_65] at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_65] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:618) [servlet-api.jar:na] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) [servlet-api.jar:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [catalina.jar:8.0.20] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.20] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.20] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.20] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.20] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.20] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.20] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.20] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.20] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [catalina.jar:8.0.20] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.20] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.20] at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) [catalina.jar:8.0.20] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.20] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516) [catalina.jar:8.0.20] at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086) [tomcat-coyote.jar:8.0.20] at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659) [tomcat-coyote.jar:8.0.20] at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:285) [tomcat-coyote.jar:8.0.20] at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2439) [tomcat-coyote.jar:8.0.20] at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2428) [tomcat-coyote.jar:8.0.20] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_65] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_65] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.20] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_65] |
Так же это будет записано на диск.
Ну и конечно вывод на странице сайта:
Исходные коды
MVC_AngularJS_Html5 full project — полный проект Spring MVC + AngularJS + Bootstrap + HTML5.
7. Exception and Logging — код для этой части
Обзор приложения Spring MVC + AngularJS + Bootstrap + HTML5
42 thoughts on “Spring MVC Exception handler (перехват исключений). Настройка логирования в Spring MVC с помощью Logback”
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.
При запуске приложения в консоль пишет все как и предполагается, но вот лог не создается и страничка с ошибкой не выходит. Где копать?
мы разве не должны были записать в mvc-config
ModelAndView(«error/exception», «exceptionMsg», «ExceptionHandler msg: « + e.toString());
Здесь перед error нужен слэш. И обращаться к контроллеру нужно по адресу localhost:8080/runtimeException. Тогда все заработает.