继续编写用户服务;增添基础信息服务;增强异常管理,美化相关界面;
This commit is contained in:
parent
a74da9805e
commit
d64a4aca62
@ -34,8 +34,11 @@ public class DataModelRepositorySearcher {
|
||||
}
|
||||
|
||||
public <T> T getDataModelRepositoryInstance() {
|
||||
// 确保可以引用
|
||||
if(isPresent()) {
|
||||
return (T) springUtil.getBean(repositoryClass);
|
||||
@SuppressWarnings("unchecked")
|
||||
T repository = (T) springUtil.getBean(repositoryClass);
|
||||
return repository;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 查找特定的Model以创建相应的操作表单(多例模式)
|
||||
* 根据子系统及名称查找特定的Data Model
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
|
@ -13,6 +13,7 @@ import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@ -30,13 +31,12 @@ public class ASEErrorController implements ErrorController {
|
||||
model.addAttribute("exception_name", exception.getClass().getName());
|
||||
model.addAttribute("exception_message", exception.getMessage());
|
||||
List<String> stack_infos = new ArrayList<>();
|
||||
|
||||
for(StackTraceElement element : exception.getStackTrace()){
|
||||
String s = element.toString();
|
||||
stack_infos.add(s);
|
||||
}
|
||||
model.addAttribute("error_stack", stack_infos);
|
||||
|
||||
model.addAttribute("exception_date",new Date());
|
||||
return "error";
|
||||
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ public class DataManagerController {
|
||||
if(!dataModelRepositorySearcher.isPresent()){
|
||||
throw new RuntimeException("Data Model Repository Not Found");
|
||||
}
|
||||
|
||||
Map<String, Object> data;
|
||||
return "query";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.codesdream.ase.exception;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class UserInformationIllegalException extends RuntimeException {
|
||||
|
||||
String username;
|
||||
|
||||
public UserInformationIllegalException(String username){
|
||||
super();
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.codesdream.ase.exception;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class UserNotFoundException extends RuntimeException {
|
||||
Integer id;
|
||||
String username;
|
||||
|
||||
public UserNotFoundException(Integer id, String username){
|
||||
super();
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.codesdream.ase.exception;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class UsernameAlreadyExistException extends RuntimeException {
|
||||
|
||||
String username;
|
||||
|
||||
public UsernameAlreadyExistException(String username){
|
||||
super();
|
||||
this.username = username;
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import lombok.Data;
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* 考生类别
|
||||
* 考生类别基本信息
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
|
@ -4,6 +4,9 @@ import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* 民族基本信息
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "base_ethnic")
|
||||
|
@ -4,6 +4,9 @@ import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* 专业基本信息
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "base_major")
|
||||
|
@ -5,7 +5,7 @@ import lombok.Data;
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* 政治面貌
|
||||
* 政治面貌基本信息
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.codesdream.ase.model.permission;
|
||||
|
||||
import com.codesdream.ase.model.information.BaseAdministrativeDivision;
|
||||
import com.codesdream.ase.model.information.BaseCollege;
|
||||
import com.codesdream.ase.model.information.BaseMajor;
|
||||
import com.codesdream.ase.model.information.*;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
@ -19,20 +17,28 @@ public class UserDetail {
|
||||
private int id;
|
||||
|
||||
// 所属地区
|
||||
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@OneToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||
private BaseAdministrativeDivision baseAdministrativeDivision;
|
||||
|
||||
// 所属学院
|
||||
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@OneToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||
private BaseCollege baseCollege;
|
||||
|
||||
// 所属专业
|
||||
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@OneToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||
private BaseMajor baseMajor;
|
||||
|
||||
// 民族
|
||||
@OneToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||
private BaseEthnic baseEthnic;
|
||||
|
||||
// 政治面貌
|
||||
@OneToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
|
||||
private BasePoliticalStatus basePoliticalStatus;
|
||||
|
||||
// 真实姓名
|
||||
private String realName;
|
||||
private String realName = "";
|
||||
|
||||
// 在校状态
|
||||
private boolean atSchool;
|
||||
private boolean atSchool = false;
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.codesdream.ase.repository.information;
|
||||
|
||||
import com.codesdream.ase.model.information.BaseAdministrativeDivision;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface BaseAdministrativeDivisionRepository extends CrudRepository<BaseAdministrativeDivision, Integer> {
|
||||
Optional<BaseAdministrativeDivision> findByName(String name);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.codesdream.ase.repository.information;
|
||||
|
||||
import com.codesdream.ase.model.information.BaseCandidateCategory;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface BaseCandidateCategoryRepository extends CrudRepository<BaseCandidateCategory, Integer> {
|
||||
Optional<BaseCandidateCategory> findByName(String name);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.codesdream.ase.repository.information;
|
||||
|
||||
import com.codesdream.ase.model.information.BaseCollege;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface BaseCollegeRepository extends CrudRepository<BaseCollege, Integer> {
|
||||
Optional<BaseCollege> findByName(String name);
|
||||
Optional<BaseCollege> findByNumber(Integer number);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.codesdream.ase.repository.information;
|
||||
|
||||
import com.codesdream.ase.model.information.BaseEthnic;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface BaseEthnicRepository extends CrudRepository<BaseEthnic, Integer> {
|
||||
Optional<BaseEthnic> findByName(String name);
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.codesdream.ase.repository.information;
|
||||
|
||||
import com.codesdream.ase.model.information.BaseMajor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface BaseMajorRepository extends CrudRepository<BaseMajor, Integer> {
|
||||
Optional<BaseMajor> findByName(String name);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.codesdream.ase.repository.information;
|
||||
|
||||
import com.codesdream.ase.model.information.BasePoliticalStatus;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface BasePoliticalStatusRepository extends CrudRepository<BasePoliticalStatus, Integer> {
|
||||
Optional<BasePoliticalStatus> findByName(String name);
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.codesdream.ase.service;
|
||||
|
||||
public interface IBaseInformationService {
|
||||
boolean checkAdministrativeDivision(String name);
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.codesdream.ase.service;
|
||||
|
||||
import com.codesdream.ase.model.permission.User;
|
||||
import javafx.util.Pair;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -16,20 +17,28 @@ public interface IUserService {
|
||||
List<User> findAll();
|
||||
|
||||
Optional<User> findUserById(int id);
|
||||
|
||||
User findUserByUsername(String username);
|
||||
|
||||
public Pair<Boolean, User> checkIfUserExists(String username);
|
||||
|
||||
// 获得用户所有的权限角色
|
||||
Collection<? extends GrantedAuthority> getUserAuthorities(User user);
|
||||
|
||||
// 更新用户的密码
|
||||
void updatePassword(User user, String password);
|
||||
|
||||
// 生成随机用户名
|
||||
// 根据学号生成随机用户名
|
||||
void generateRandomUsernameByStudentID(User user, String id);
|
||||
|
||||
// 注册用户
|
||||
User save(User user);
|
||||
|
||||
// 更新用户信息
|
||||
User update(User user);
|
||||
|
||||
// 删除用户
|
||||
void delete(User user);
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,8 +3,12 @@ package com.codesdream.ase.service;
|
||||
import com.codesdream.ase.component.permission.ASEPasswordEncoder;
|
||||
import com.codesdream.ase.component.permission.ASEUsernameEncoder;
|
||||
import com.codesdream.ase.component.permission.UserRolesListGenerator;
|
||||
import com.codesdream.ase.exception.UserInformationIllegalException;
|
||||
import com.codesdream.ase.exception.UserNotFoundException;
|
||||
import com.codesdream.ase.exception.UsernameAlreadyExistException;
|
||||
import com.codesdream.ase.model.permission.User;
|
||||
import com.codesdream.ase.repository.permission.UserRepository;
|
||||
import javafx.util.Pair;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -41,10 +45,16 @@ public class UserService implements IUserService {
|
||||
@Override
|
||||
public User findUserByUsername(String username) {
|
||||
Optional<User> user = userRepository.findByUsername(username);
|
||||
if(!user.isPresent()) throw new UsernameNotFoundException("User Not Found");
|
||||
if(!user.isPresent()) throw new UsernameNotFoundException(username);
|
||||
return user.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Boolean, User> checkIfUserExists(String username){
|
||||
Optional<User> user = userRepository.findByUsername(username);
|
||||
return user.map(value -> new Pair<>(true, value)).orElseGet(() -> new Pair<>(false, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getUserAuthorities(User user) {
|
||||
return userRolesListGenerator.generateRoles(user);
|
||||
@ -66,23 +76,43 @@ public class UserService implements IUserService {
|
||||
public User save(User user) {
|
||||
// 查找用户名是否已经被注册
|
||||
if(userRepository.findByUsername(user.getUsername()).isPresent())
|
||||
throw new RuntimeException("Username Already Exists");
|
||||
throw new UsernameAlreadyExistException(user.getUsername());
|
||||
|
||||
// 用户信息一般性规范检查
|
||||
if(user.getUserAuth().getUserAnswer().length() > 255
|
||||
|| user.getUserAuth().getUserQuestion().length() > 255
|
||||
|| user.getUserAuth().getStudentID().length() > 24
|
||||
|| user.getUserAuth().getMail().length() > 64
|
||||
|| user.getUserDetail().getRealName().length() > 12)
|
||||
throw new UserInformationIllegalException(user.getUsername());
|
||||
|
||||
// 强制以哈希值(sha256)保存密码
|
||||
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User update(User user) {
|
||||
if(!userRepository.findByUsername(user.getUsername()).isPresent())
|
||||
throw new RuntimeException("Username Already Exists");
|
||||
// 执行前检查
|
||||
if(!userRepository.findById(user.getId()).isPresent())
|
||||
throw new UserNotFoundException(user.getId(), user.getUsername());
|
||||
return userRepository.save(user);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(User user) {
|
||||
// 执行前检查
|
||||
if(!userRepository.findById(user.getId()).isPresent())
|
||||
throw new UserNotFoundException(user.getId(), user.getUsername());
|
||||
userRepository.delete(user);
|
||||
}
|
||||
|
||||
// 获得一个默认初始化的用户对象
|
||||
@Override
|
||||
public User getDefaultUser() {
|
||||
return new User();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,74 +1,71 @@
|
||||
package com.codesdream.ase.test;
|
||||
|
||||
import com.codesdream.ase.model.permission.FunctionalPermissionContainer;
|
||||
import com.codesdream.ase.model.permission.Tag;
|
||||
import com.codesdream.ase.model.permission.User;
|
||||
import com.codesdream.ase.repository.permission.UserRepository;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import com.codesdream.ase.service.UserService;
|
||||
import com.sun.org.apache.xpath.internal.operations.Bool;
|
||||
import javafx.util.Pair;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.HashSet;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 用户基本表单元测试
|
||||
* 用于测试数据库与DAO层交互是否通畅
|
||||
*/
|
||||
@DataJpaTest
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class UserTest {
|
||||
|
||||
@Autowired
|
||||
private TestEntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
/**
|
||||
* 基本存储与查询测试
|
||||
*/
|
||||
@Test
|
||||
public void UserBaseTest_1(){
|
||||
User user = new User("Tim", "123456");
|
||||
userRepository.save(user);
|
||||
assertTrue(userRepository.findByUsername("Tim").isPresent());
|
||||
assertFalse(userRepository.findByUsername("Tom").isPresent());
|
||||
user = userRepository.findByUsername("Tim").get();
|
||||
// 查找数据库中是否有重复项
|
||||
Pair<Boolean, User> checker = userService.checkIfUserExists("Tim");
|
||||
if(checker.getKey()){
|
||||
userService.delete(checker.getValue());
|
||||
}
|
||||
|
||||
User user = userService.getDefaultUser();
|
||||
user.setUsername("Tim");
|
||||
user.setPassword("123456");
|
||||
user.getUserAuth().setStudentID("2018303026");
|
||||
user.getUserAuth().setMail("937447984@qq.com");
|
||||
user.getUserAuth().setUserQuestion("Your favourite animal?");
|
||||
user.getUserAuth().setUserAnswer("Cat");
|
||||
user.getUserDetail().setAtSchool(true);
|
||||
userService.save(user);
|
||||
|
||||
user = userService.findUserByUsername("Tim");
|
||||
|
||||
assertEquals(user.getUsername(), "Tim");
|
||||
assertEquals(user.getPassword(), "123456");
|
||||
assertEquals(user.getPassword(),
|
||||
"8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92");
|
||||
// 检查账号状态
|
||||
assertTrue(user.isEnabled());
|
||||
assertFalse(user.isDeleted());
|
||||
assertTrue(user.isAccountNonExpired());
|
||||
assertTrue(user.isAccountNonLocked());
|
||||
assertTrue(user.isCredentialsNonExpired());
|
||||
assertEquals(user.getUserAuth().getStudentID(), "2018303026");
|
||||
assertEquals(user.getUserAuth().getMail(), "937447984@qq.com");
|
||||
assertEquals(user.getUserAuth().getUserQuestion(), "Your favourite animal?");
|
||||
assertEquals(user.getUserAuth().getUserAnswer(), "Cat");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void UserBaseTest_2(){
|
||||
// 用户
|
||||
User user = new User("Pat", "123456");
|
||||
// 标签
|
||||
Tag tag = new Tag("学生","普通学生");
|
||||
// 功能性权限容器
|
||||
FunctionalPermissionContainer functionalPermissionContainer =
|
||||
new FunctionalPermissionContainer("基本用户权限", "基本的用户权限");
|
||||
|
||||
// 添加为标签功能性权限容器
|
||||
HashSet<FunctionalPermissionContainer> functionalPermissionContainers = new HashSet<>();
|
||||
functionalPermissionContainers.add(functionalPermissionContainer);
|
||||
// 等待添加
|
||||
|
||||
// 为用户添加标签
|
||||
HashSet<Tag> tags = new HashSet<>();
|
||||
tags.add(tag);
|
||||
user.setTags(tags);
|
||||
|
||||
userRepository.save(user);
|
||||
|
||||
User user = userService.findUserByUsername("Tim");
|
||||
|
||||
|
||||
|
||||
|
@ -8,83 +8,89 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="logo-header" data-background-color="blue" style="width:100%">
|
||||
<h1><font color="#FFFFFF">Error</font></h1>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
<h2>
|
||||
检测到异常发生
|
||||
</h2>
|
||||
<p>
|
||||
<strong><strong>当服务器端程序内部某个模块抛出异常时,该界面就会被显示。此次异常的简要信息已被异常管理子系统收集并概括如下表:</strong></strong>
|
||||
</p>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
编号
|
||||
</th>
|
||||
<th>
|
||||
信息项
|
||||
</th>
|
||||
<th>
|
||||
值
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
0
|
||||
</td>
|
||||
<td>
|
||||
服务器返回HTTP状态
|
||||
</td>
|
||||
<td th:text="${http_status}">
|
||||
<div class="wrapper">
|
||||
<div class="main-header">
|
||||
<nav class="navbar navbar-header navbar-expand-lg" data-background-color="blue2">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
1
|
||||
</td>
|
||||
<td>
|
||||
抛出的异常类型
|
||||
</td>
|
||||
<td th:text="${exception_name}">
|
||||
<div class="container-fluid">
|
||||
<h1 style="color: white">Error Occurred</h1>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="main-panel">
|
||||
<div class="content">
|
||||
<div class="page-inner">
|
||||
<div class="page-header">
|
||||
<h4 class="page-title"><div class="fa fa-surprise"></div> 异常被抛出 (Exception Thrown)</h4>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<h4 class="card-title"><div class="fa fa-cogs"></div> 概要信息</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-sub">
|
||||
此次异常的简要信息已被异常管理子系统收集并概括如下表
|
||||
</div>
|
||||
<table class="table table-bordered table-head-bg-info table-bordered-bd-info mt-8">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">信息项</th>
|
||||
<th scope="col">值</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0 </td>
|
||||
<td>HTTP状态</td>
|
||||
<td class="text-primary" th:text="${http_status}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>异常类型</td>
|
||||
<td class="text-primary" th:text="${exception_name}"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
2
|
||||
</td>
|
||||
<td>
|
||||
异常附带消息
|
||||
</td>
|
||||
<td th:text="${exception_message}">
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>附带消息</td>
|
||||
<td class="text-primary" th:text="${exception_message}"></td>
|
||||
</tr>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>附带消息</td>
|
||||
<td class="text-primary" th:text="${#dates.format(exception_date, 'yyyy-MM-dd HH:mm:ss')}"></td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>
|
||||
运行栈相关信息补充
|
||||
</h3>
|
||||
<p th:each="line : ${error_stack}">
|
||||
<span th:text="${line}"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h1 class="card-title"><div class="fa fa-bug"></div> 运行栈相关信息</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol class="activity-feed">
|
||||
<li class="feed-item" th:each="line : ${error_stack}">
|
||||
<span class="text" th:text="${line}"></span>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -8,10 +8,23 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="logo-header" data-background-color="blue" style="width:100%">
|
||||
<h1><font color="#FFFFFF">404 Not Found</font></h1>
|
||||
<div class="wrapper">
|
||||
<div class="main-header">
|
||||
<nav class="navbar navbar-header navbar-expand-lg" data-background-color="blue2">
|
||||
<div class="container-fluid">
|
||||
<h1 style="color: white">Page Not Found</h1>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="main-panel">
|
||||
<div class="content">
|
||||
<div class="col-md-8">
|
||||
<div class="card"><img th:src="@{/assets/img/404.jpg}" /></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user