spring-boot 官方文档:https://docs.spring.io/spring-boot/docs/2.2.0.BUILD-SNAPSHOT/reference/html/#boot-documentation
spring-io 官方文档:https://docs.spring.io/platform/docs/Cairo-SR7/reference/htmlsingle/#platform-documentation
github 地址:https://github.com/simba1949/springboot-learn
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.0.BUILD-SNAPSHOTversion>
parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.2.0.BUILD-SNAPSHOTversion>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<parent>
<groupId>io.spring.platformgroupId>
<artifactId>platform-bomartifactId>
<version>Cairo-SR7version>
<relativePath/>
parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platformgroupId>
<artifactId>platform-bomartifactId>
<version>Cairo-SR7version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
pom.xml
<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.0modelVersion>
<groupId>top.simba1949groupId>
<artifactId>spring-boot-get-startartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.5.RELEASEversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<target>1.8target>
<source>1.8source>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
<configuration>
<encoding>UTF-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
configuration>
plugin>
plugins>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*include>
includes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*include>
includes>
resource>
resources>
build>
project>
启动程序
package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author SIMBA1949
* @date 2019/7/7 13:23
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication 是 SpringBoot 的核心注解,是一个组合注解,源码如下
/*
* Copyright 2012-2019 the original author or authors.
*
* 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
*
* https://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 org.springframework.boot.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
/**
* Indicates a {@link Configuration configuration} class that declares one or more
* {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
* auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
* annotation that is equivalent to declaring {@code @Configuration},
* {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
*
* @author Phillip Webb
* @author Stephane Nicoll
* @since 1.2.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
*
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
关闭特定的自动配置应该使用@SpringBootApplication注解的exclude参数
例:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
在 SpringBoot 启动的时候会有一个默认的启动图案
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.5.RELEASE)
在src/main/resources下新建一个banner.txt,通过http://patorjk.com/software/taag网站生成字符,如敲入simba1949,将网站生成的字符复制在banner.txt中,即可定制
_ _ __ _____ ___ _____
(_) | | / | | _ | / || _ |
___ _ _ __ ___ | |__ __ _`| | | |_| | / /| || |_| |
/ __| | '_ ` _ \| '_ \ / _` || | \____ |/ /_| |\____ |
\__ \ | | | | | | |_) | (_| || |_.___/ /\___ |.___/ /
|___/_|_| |_| |_|_.__/ \__,_\___/\____/ |_/\____/
<----------------Spring Boot Learn Note--------------->
可以在 banner.txt 文件中使用 ${}
Variable | Description |
---|---|
${application.version} |
The version number of your application, as declared in MANIFEST.MF . For example,Implementation-Version: 1.0 is printed as 1.0 . |
${application.formatted-version} |
The version number of your application, as declared in MANIFEST.MF and formatted for display (surrounded with brackets and prefixed with v ). For example (v1.0) . |
${spring-boot.version} |
The Spring Boot version that you are using. For example 2.2.0.BUILD-SNAPSHOT . |
${spring-boot.formatted-version} |
The Spring Boot version that you are using, formatted for display (surrounded with brackets and prefixed with v ). For example (v2.2.0.BUILD-SNAPSHOT) . |
${Ansi.NAME} (or ${AnsiColor.NAME} , ${AnsiBackground.NAME} , ${AnsiStyle.NAME} ) |
Where NAME is the name of an ANSI escape code. See [AnsiPropertySource ] for details. |
${application.title} |
The title of your application, as declared in MANIFEST.MF . For exampleImplementation-Title: MyApp is printed as MyApp . |
添加打包插件
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
命令运行:mvn clean compile package
会得到如下jar包
[INFO] Building jar: T:\IDE\IDEA\Workspace-Learn\springboot-learn\spring-boot-get-start\target\spring-boot-get-start-1.0-SNAPSHOT.jar
在命令窗口输入下面命令即可运行:
# linux 环境下,前台运行
java -jar spring-boot-get-start-1.0-SNAPSHOT.jar
# linux 环境下,后台运行
java -jar spring-boot-get-start-1.0-SNAPSHOT.jar &
1.5.1 配置随机数
my:
secret: ${random.value}
number: ${random.int}
bigNumber: ${random.long}
uuid: ${random.uuid}
number.less.than.ten: ${random.int(10)}
number.in.range: ${random.int[1024,65536]}
1.5.2 读取 properties & yaml 配置文件信息
properties 配置文件
server.port=8080
#配置对应的属性
user.username=simba1949
user.say=hi,${user.username}!!!
yaml配置文件
server:
port: 8080
user:
username: jarvis
say: hi,${user.username}
设置配置信息类
package top.simba1949.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.io.Serializable;
/**
* 使用 @ConfigurationProperties(prefix = "user") 指定前缀,并提供 setter 方法
*
* @author SIMBA1949
* @date 2019/7/7 22:00
*/
@Configuration
@ConfigurationProperties(prefix = "user")
public class PropertiesConfigInfo implements Serializable {
private static final long serialVersionUID = -467150486910074559L;
private String username;
private String say;
// 省略 getter/setter、toString 方法
}
1.5.3 读取其他信息配置文件 properties & yaml
其他配置文件
properties
user.username=simba1949
user.age=18
# 日期类可以写成 年/月/日
user.birthday=1949/10/01
user.flag=true
yaml
user:
username: jarvis
age: 20
# 日期类可以写成 年/月/日
birthday: 1949/10/01
flag: true
读取配置文件代码
package top.simba1949.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import java.util.Date;
/**
* 使用 @PropertySource(value = "classpath:author.properties") 注解,并指定文件路径,使用 @Value 可以获取配置信息的数据
*
* @author SIMBA1949
* @date 2019/7/7 22:32
*/
@Configuration
@PropertySource(value = "classpath:author.properties")
public class OtherPropertiesConfig {
@Value("${user.username}")
private String username;
@Value("${user.age}")
private int age;
@Value("${user.birthday}")
private Date birthday;
@Value("${user.flag}")
private boolean flag;
// 省略 toString 方法
}
使用 xml 配置
@ImportResource({"classpath:ApplicationContext-tran.xml","classpath:ApplicationContext-dao.xml"})
1.5.4 Profile 配置
Porfile 是 Spring 用来针对不同的环境对不同的配置提供的支持,全局 Profile 配置使用 application-{profile}.yml 或者application-{profile}.properties,在 application.yml 或者 application.properties 中设置 spring.profiles.active=test 来指定活动的配置文件。
application.yml
spring:
profiles:
active: test
application-prod.yml
server:
port: 8080
spring:
application:
name: spring-boot-multi-profile-prod
application-dev.yml
server:
port: 8081
spring:
application:
name: spring-boot-multi-profile-dev
application-test.yml
server:
port: 8082
spring:
application:
name: spring-boot-multi-profile-test
添加 Maven 依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<optional>trueoptional>
dependency>
SpringBoot内置的自动配置功能:http的编码配置
在常规项目中配置http编码的时候在web.xml里配置一个filter
<filter>
<filter-name>encodingfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
自动配置要满足俩个条件
默认编码方式为 UTF-8,若修改可使用 spring.http.encoding.charset=编码;
设置 forceEncoding,默认为 true,若修改可使用 spring.http.encoding.force=false
#配置程序端口,默认为8080
server.port=
#用户会话session过期时间,以秒为单位
server.session.timeout=
#配置访问路径,默认为/
server.context-path=
#配置tomcat编码,默认为utf-8
server.tomcat.uri-encoding=
SpringBoot 默认开启,关闭 favicon 在 application.properties 中配置即可
spring.mvc.favicon.enabled=false
定制 Favicon
需要 spring.mvc.favicon.enabled 开启,不配置默认开启也可,将favicon.ico(文件名不能变动过)放置在src/main/resources/static 或者 src/main/resources 目录下即可,运行效果
**注意:**如果不显示,请清空浏览器缓存即可
# 日志配置
# 日志级别
logging.level.root=DEBUG
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=DEBUG
# 输出日志名字,默认为 myapp.log
logging.file=spring-boot-multi-profile.log
# 日志输出路径
logging.path=T:/IDE/IDEA/Workspace-Learn/springboot-learn/logs
# 指定日志文件路径
#logging.config=
SpringBoot 支持的日志框架的各个命名:
Logging System | Customization |
---|---|
Logback | logback-spring.xml , logback-spring.groovy , logback.xml , or logback.groovy |
Log4j2 | log4j2-spring.xml or log4j2.xml |
JDK (Java Util Logging) | logging.properties |
#默认支持文件上传.
spring.http.multipart.enabled=true
#支持文件写入磁盘.
spring.http.multipart.file-size-threshold=0
# 最大支持文件大小
spring.http.multipart.max-file-size=1Mb
# 最大支持请求大小
spring.http.multipart.max-request-size=10Mb
Java 代码读写
package top.simba1949.controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
/**
* @author SIMBA1949
* @date 2019/7/8 8:45
*/
@RestController
@RequestMapping("file")
public class FileOperatingController {
@PostMapping("upload")
public String upload(@RequestParam(value = "image")MultipartFile file, HttpServletRequest request){
try {
// 获取 upload 目录,不存在就在创建
// 获取当前项目的 classes 目录
String realPath = FileOperatingController.class.getClassLoader().getResource("").getPath();
// 获取服务器中当前WebRoot的物理路径
// String realPath = request.getSession().getServletContext().getRealPath("/");
File realPathFile = new File(realPath, "upload");
if (!realPathFile.exists()){
realPathFile.mkdirs();
}
// 文件上传
file.transferTo(new File(realPathFile,file.getOriginalFilename()));
return "http://localhost:8080/upload/" + file.getOriginalFilename();
} catch (IOException e) {
e.printStackTrace();
return e.getMessage();
}
}
}
SpringBoot 配置可访问文件
package top.simba1949.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author SIMBA1949
* @date 2019/7/8 9:15
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 添加静态资源文件,外部可以直接访问地址
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//需要配置1:----------- 需要告知系统,这是要被当成静态文件的!
//第一个方法设置访问路径前缀,第二个方法设置资源路径
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/");
registry.addResourceHandler("/upload/**").addResourceLocations("classpath:/upload/");
}
}
自定义拦截器
package top.simba1949.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义拦截器需要实现 HandlerInterceptor 接口,根据业务重写下面方法
*
* @author SIMBA1949
* @date 2019/7/8 9:26
*/
public class UserInterceptor implements HandlerInterceptor {
/**
* 在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle-------------------------------");
return true;
}
/**
* 在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle-------------------------------");
}
/**
* 在 DispatcherServlet 完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion-------------------------------");
}
}
注册拦截器
package top.simba1949.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import top.simba1949.interceptor.UserInterceptor;
/**
* @author SIMBA1949
* @date 2019/7/8 9:29
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器,配置拦截器需要拦截的 url
registry.addInterceptor(new UserInterceptor()).addPathPatterns("/hello/**");
}
}
定义过滤器类
package top.simba1949.filter;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @Order(2) 配置多个过滤器的执行顺序,数值越小的过滤器优先执行
* @WebFilter(urlPatterns = "/filter/*", filterName = "appFilter") 配置拦截 url
* urlPatterns 配置规则只能使用一个 * ,否则会失效
*
* @author SIMBA1949
* @date 2019/7/8 10:49
*/
@Order(2)
@WebFilter(urlPatterns = "/filter/*", filterName = "appFilter")
public class AppFilter implements Filter {
/**
* 过滤器逻辑
* @param request
* @param response
* @param chain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("AppFilter");
chain.doFilter(request, response);
}
}
需要在启动类上添加扫描器
package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
*
* @ServletComponentScan 需要扫描 servlet、 filter、 listener 三大组件
*
* @author SIMBA1949
* @date 2019/7/8 9:24
*/
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
自定义 Servlet 类
package top.simba1949.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*
* @WebServlet(urlPatterns = {"/my", "/diy"}, name = "diyServlet") urlPatterns 设置访问路径,name 设置 servlet 名称
*
* @author SIMBA1949
* @date 2019/7/9 6:34
*/
@WebServlet(urlPatterns = {"/my", "/diy"}, name = "diyServlet")
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = -6473768022688770593L;
/**
* 自定义 servlet 的 doGet 请求
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("接收到请求");
resp.setCharacterEncoding("utf-8");
resp.getWriter().append("君不见黄河之水天上来");
}
}
需要在启动类上添加扫描器
package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
*
* @ServletComponentScan 需要扫描 servlet、 filter、 listener 三大组件
*
* @author SIMBA1949
* @date 2019/7/8 9:24
*/
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
自定义 Listener 类
package top.simba1949.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* @author SIMBA1949
* @date 2019/7/9 7:47
*/
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("contextDestroyed");
}
}
需要在启动类上添加扫描器
package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
*
* @ServletComponentScan 需要扫描 servlet、 filter、 listener 三大组件
*
* @author SIMBA1949
* @date 2019/7/8 9:24
*/
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
自定义 Listener 类
package top.simba1949.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @author SIMBA1949
* @date 2019/7/9 7:51
*/
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("sessionCreated");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("sessionDestroyed");
}
}
需要在启动类上添加扫描器
package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
*
* @ServletComponentScan 需要扫描 servlet、 filter、 listener 三大组件
*
* @author SIMBA1949
* @date 2019/7/8 9:24
*/
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
自定义 Listener 类
package top.simba1949.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
/**
* @author SIMBA1949
* @date 2019/7/9 7:53
*/
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("requestInitialized");
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("requestDestroyed");
}
}
需要在启动类上添加扫描器
package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
/**
*
* @ServletComponentScan 需要扫描 servlet、 filter、 listener 三大组件
*
* @author SIMBA1949
* @date 2019/7/8 9:24
*/
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@ControllerAdvice
该注解是spring2.3以后新增的一个注解,主要是用来Controller的一些公共的需求的低侵入性增强提供辅助,作用于@RequestMapping标注的方法上。
@ExceptionHandler
该注解是配合@ControllerAdvice一起使用的注解,自定义错误处理器,可自己组装json字符串,并返回到页面。
异常统一处理类
package top.simba1949.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
/**
* @ControllerAdvice 全局异常统一处理类标识
*
* @author SIMBA1949
* @date 2019/7/8 10:22
*/
@ControllerAdvice
public class GlobalException {
/**
* @ExceptionHandler(value = IOException.class) 指定处理哪类异常
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(value = IOException.class)
public String ioExceptionDealWith(IOException e){
System.out.println(e.getMessage());
return e.getMessage();
}
@ResponseBody
@ExceptionHandler(value = Exception.class)
public String exceptionDealWith(Exception e){
System.out.println(e.getMessage());
return e.getMessage();
}
}
模拟异常类
package top.simba1949.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
* @author SIMBA1949
* @date 2019/7/8 10:32
*/
@RestController
@RequestMapping("e")
public class ExceptionController {
@GetMapping("")
public String exception() throws Exception {
System.out.println("Exception");
throw new Exception("Exception");
}
@GetMapping("io")
public String ioException() throws IOException {
System.out.println("IOException");
throw new IOException("IOException");
}
}
For example, to map 404
to a static HTML file, your folder structure would be as follows:
src/
+- main/
+- java/
| +
+- resources/
+- public/
+- error/
| +- 404.html
+-
To map all 5xx
errors by using a Mustache template, your folder structure would be as follows:
src/
+- main/
+- java/
| +
+- resources/
+- templates/
+- error/
| +- 5xx.mustache
+-
package top.simba1949;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
/**
* @RunWith(SpringRunner.class) 告诉JUnit使用Spring的测试支持
* @SpringBootTest 使用Spring Boot支持的引导,需要加载springboot的配置文件
* @author SIMBA1949
* @date 2018/11/28 22:05
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {
/**
* 伪造 MVC 环境
*/
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Before
public void setMockMvc(){
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void sayHelloTest() throws Exception {
ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders.get("/list")
.contentType(MediaType.APPLICATION_JSON_UTF8)
);
// $.length() jsonpath表达式
// jsonpath 表达式文档:https://github.com/json-path/JsonPath
resultActions
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(3));
}
}
2.12 Web 容器替换
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-tomcatartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jettyartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-undertowartifactId>
dependency>