#1 -- Add custom error page

This commit is contained in:
Anton Romanov 2021-03-16 13:50:29 +04:00
parent e669750575
commit de2125d251
8 changed files with 222 additions and 72 deletions

View File

@ -39,8 +39,6 @@ repositories {
configurations { configurations {
compile.exclude module: "spring-boot-starter-tomcat" compile.exclude module: "spring-boot-starter-tomcat"
compile.exclude module: "jquery"
compile.exclude module: "popper.js"
compile.exclude module: "follow-redirects" compile.exclude module: "follow-redirects"
compile.exclude module: "is-buffer" compile.exclude module: "is-buffer"
} }
@ -49,6 +47,7 @@ dependencies {
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web' compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-jetty' compile group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf' compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
compile group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect'
compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-afterburner' compile group: 'com.fasterxml.jackson.module', name: 'jackson-module-afterburner'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate5' compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate5'
@ -57,6 +56,12 @@ dependencies {
compile group: 'com.ibm.icu', name: 'icu4j', version: '63.1' compile group: 'com.ibm.icu', name: 'icu4j', version: '63.1'
compile group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '5.9.0.202009080501-r' compile group: 'org.eclipse.jgit', name: 'org.eclipse.jgit', version: '5.9.0.202009080501-r'
compile group: 'org.webjars', name: 'jquery', version: '3.6.0'
compile group: 'org.webjars', name: 'bootstrap', version: '4.6.0'
compile group: 'org.webjars', name: 'bootstrap-select', version: '1.13.8'
compile group: 'org.webjars', name: 'font-awesome', version: '4.7.0'
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test' testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
} }

View File

@ -0,0 +1,40 @@
package ru.ulstu.extractor.mvc;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice
class GlobalDefaultExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) {
// If the exception is annotated with @ResponseStatus rethrow it and let
// the framework handle it - like the OrderNotFoundException example
// at the start of this post.
// AnnotationUtils is a Spring Framework utility class.
/*if (AnnotationUtils.findAnnotation (e.getClass(), ResponseStatus.class) != null) {
throw e;
}
*/
// Otherwise setup and send the user to a default error-view.
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public String handle(NoHandlerFoundException ex) {
return "DEFAULT_ERROR_VIEW";
}
}

View File

@ -0,0 +1,23 @@
package ru.ulstu.extractor.mvc;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/{articlename:\\w+}");
registry.addRedirectViewController("/", "/index");
registry.addRedirectViewController("/default", "/home");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("/webjars/");
}
}

View File

@ -0,0 +1,19 @@
package ru.ulstu.extractor.mvc;
import nz.net.ultraq.thymeleaf.LayoutDialect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ITemplateResolver;
@Configuration
public class TemplateConfiguration {
@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(templateResolver);
templateEngine.addDialect(new LayoutDialect());
return templateEngine;
}
}

View File

@ -2,4 +2,6 @@ spring.main.banner-mode=off
server.port=8080 server.port=8080
# Available levels are: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF # Available levels are: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
logging.level.ru.ulstu=DEBUG logging.level.ru.ulstu=DEBUG
extractor.custom-projects-dir= extractor.custom-projects-dir=
# Thymeleaf Settings
spring.thymeleaf.cache=false

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html lang="ru"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8"/>
<title>GitExtractor</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<script type="text/javascript" src="/webjars/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript" src="/webjars/bootstrap/4.6.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/webjars/bootstrap-select/1.13.8/js/bootstrap-select.min.js"></script>
<link rel="stylesheet" href="/webjars/bootstrap/4.6.0/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/webjars/bootstrap-select/1.13.8/css/bootstrap-select.min.css"/>
<link rel="stylesheet" href="/webjars/font-awesome/4.7.0/css/font-awesome.min.css"/>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light" layout:fragment="navbar">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
Dropdown
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
</div>
</nav>
<div class="wrapper">
<div id="sidebar" class="collapse navbar-collapse sidebar-mobile">
<ul id="menu" class="list-unstyled">
</ul>
</div>
<div id="content">
<div id="breadcrumbs" class="container-fluid">
</div>
<div class="container-fluid">
<ul id="messages" class="feedback-panel">
</ul>
</div>
<div layout:fragment="content">
</div>
</div>
</div>
</body>
</html>

View File

@ -1,53 +1,45 @@
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd"> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"> xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<!--<head th:substituteby="header :: copy"></head>--> <!--<head th:substituteby="header :: copy"></head>-->
<body> <div class="container" layout:fragment="content">
<h1>Support Friendly Error Page</h1> <h1>Ошибка</h1>
<!-- As we are using Thymeleaf, you might consider using <!-- As we are using Thymeleaf, you might consider using
${#httpServletRequest.requestURL}. But that returns the path ${#httpServletRequest.requestURL}. But that returns the path
to this error page. Hence we explicitly add the url to the to this error page. Hence we explicitly add the url to the
Model in some of the example code. --> Model in some of the example code. -->
<p th:if="${url}"> <p th:if="${url}">
<b>Page:</b> <span th:text="${url}">Page URL</span> <b>Страница:</b> <span th:text="${url}">Page URL</span>
</p> </p>
<p th:if="${timestamp}" id='created'> <p th:if="${timestamp}" id='created'>
<b>Occurred:</b> <span th:text="${timestamp}">Timestamp</span> <b>Время:</b> <span th:text="${timestamp}">Timestamp</span>
</p> </p>
<p th:if="${status}"> <p th:if="${status}">
<b>Response Status:</b> <span th:text="${status}">status-code</span> <span <b>Response Status:</b> <span th:text="${status}">status-code</span> <span
th:if="${error}" th:text="'('+${error}+')'">error ...</span> th:if="${error}" th:text="'('+${error}+')'">error ...</span>
</p> </p>
<p>
<p th:if="${exception}"> <a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false"
<b>Exception:</b> <span th:text="${exception}">exception</span> <span aria-controls="collapseExample">
</p> Показать stack trace
</a>
<p>Application has encountered an error. Please contact support on </p>
...</p> <div class="collapse" id="collapseExample">
<div class="card card-body">
<p>Support may ask you to right click to view page source.</p> <div th:utext="'Failed URL: ' + ${url}" th:remove="tag">${url}</div>
<div th:utext="'Exception: ' + ${exception.message}" th:remove="tag">${exception.message}</div>
<!-- <ul th:remove="tag">
// Hidden Exception Details - this is not a recommendation, but here is <li th:each="ste : ${exception.stackTrace}" th:remove="tag"><span
// how you could hide an exception in the page using Thymeleaf th:utext="${ste}" th:remove="tag">${ste}</span></li>
--> </ul>
<div th:utext="'&lt;!--'" th:remove="tag"></div> </div>
<div th:utext="'Failed URL: ' + ${url}" th:remove="tag">${url}</div> </div>
<div th:utext="'Exception: ' + ${exception.message}" th:remove="tag">${exception.message}</div> </div>
<ul th:remove="tag">
<li th:each="ste : ${exception.stackTrace}" th:remove="tag"><span
th:utext="${ste}" th:remove="tag">${ste}</span></li>
</ul>
<div th:utext="'--&gt;'" th:remove="tag"></div>
<div th:substituteby="footer :: copy"></div>
</body>
</html> </html>

View File

@ -1,30 +1,32 @@
<!DOCTYPE HTML> <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}">
<head> <head>
<title>Простая обработка формы на Spring MVC</title> <title>Простая обработка формы на Spring MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head> </head>
<body> <div class="container" layout:fragment="content">
<h1>Форма</h1> <h1>Форма</h1>
<form action="#" th:action="@{/sendEmail}" th:object="${emailForm}" method="post"> <form action="#" th:action="@{/sendEmail}" th:object="${emailForm}" method="post">
<p style="color:red" th:text="${error}"></p> <p style="color:red" th:text="${error}"></p>
<table> <table>
<tr> <tr>
<td>Тема:</td> <td>Тема:</td>
<td><input type="text" th:field="*{subject}"/></td> <td><input type="text" th:field="*{subject}"/></td>
</tr> </tr>
<tr> <tr>
<td>Кому:</td> <td>Кому:</td>
<td><input type="text" th:field="*{to}"/></td> <td><input type="text" th:field="*{to}"/></td>
</tr> </tr>
<tr> <tr>
<td>Сообщение:</td> <td>Сообщение:</td>
<td><textarea th:field="*{message}"/></td> <td><textarea th:field="*{message}"/></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><input type="submit" value="Отправить"/></td> <td colspan="2"><input type="submit" value="Отправить"/></td>
</tr> </tr>
</table> </table>
</form> </form>
</body> </div>
</html> </html>