一、SpringBoot Web项目

新建项目时

dispatcherServlet配置 springboot_java

 

 Developer Tools 开发者工具

如果用的是 Developer Tools 直接加载maven依赖就可以了

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

dispatcherServlet配置 springboot_java_02

 

 如果是用的JRebel,要做些额外的配置

当开始开发web项目的时候,需要频繁的修改web页面,此时如果频繁的重启变得很麻烦,因此,可以在idea中集成JRebel插件,改动代码之后不需要重新启动应用程序。

1、安装JRebel

(1)在IDEA中一次点击 File->Settings->Plugins->Brows Repositories

(2)在搜索框中输入JRebel进行搜索

(3)找到JRebel for intellij

(4)install

(5)安装好之后需要restart IDEA

2、激活JRebel

JRebel并非是免费的插件,需要激活之后才可以使用

(1)生成一个GUID:https://www.guidgen.com/

(2)根据反向代理服务器地址拼接激活地址: https://jrebel.qekang.com/{GUID}

(3)打开JRebel激活面板,选择Connect to online licensing service.

(4)点击work offline

可以看官网

http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/

28、开发Web应用程序

二、SpringBoot整合Servlet

新建一个项目springboot_web

新建包controller, 新建MyController文件

dispatcherServlet配置 springboot_java_03

 

 MyController.java

package xyz.kxq.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {
    @RequestMapping("hello")
    public String hello(){
        return "hello, springboot";
    }
}

运行程序,浏览器访问:

dispatcherServlet配置 springboot_java_04

 

 

这就是我们之前搭建web项目最简单的一种方式, 可以集成servlet

1、Servlet、Filter与Listener

可以看文档中

28.4、内嵌Servlet容器支持

 Spring Boot 包含了对内嵌 TomcatJetty 和 Undertow 服务器的支持

使用servlet可以配置Servlet、Filter、Listener

  • Servlet业务逻辑类
  • Filter 过滤器
  • Listener 监听器

使用内嵌 servlet 容器时,您可以使用 Spring bean 或者扫描方式来注册 Servlet 规范中的 Servlet、Filter 和所有监听器(比如 HttpSessionListener)。

任何 ServletFilter 或 *Listener 的 Spring bean 实例都将被注册到内嵌容器中。如果您想引用 application.properties 中的某个值,这可能会特别方便。

默认情况下,如果上下文只包含单个 Servlet,它将映射到 /。在多个 Servlet bean 的情况下,bean 的名称将用作路径的前缀。Filter 将映射到 /*

如果基于约定配置的映射不够灵活,您可以使用 ServletRegistrationBeanFilterRegistrationBean 和 ServletListenerRegistrationBean 类来完全控制

Spring Boot 附带了许多可以定义 Filter bean 的自动配置。以下是部分过滤器及其执行顺序的(顺序值越低,优先级越高):

Servlet Filter

顺序

OrderedCharacterEncodingFilter

Ordered.HIGHEST_PRECEDENCE

WebMvcMetricsFilter

Ordered.HIGHEST_PRECEDENCE + 1

ErrorPageFilter

Ordered.HIGHEST_PRECEDENCE + 1

HttpTraceFilter

Ordered.LOWEST_PRECEDENCE - 10

 

 

 

 

 

 

 

通常 Filter bean 无序放置也是安全的。

如果需要指定顺序,则应避免在 Ordered.HIGHEST_PRECEDENCE 顺序点配置读取请求体的过滤器,因为它的字符编码可能与应用程序的字符编码配置不一致。

如果一个 Servlet 过滤器包装了请求,则应使用小于或等于 OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER的顺序点对其进行配置。

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(name = "myServlet",urlPatterns = "/srv")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("111");
        super.doGet(req, resp);
    }

}

 

2、Servlet上下文初始化

我们一般刚接触web开发的时候第一个接触的都是servlet, 下面我们来使用springboot来整合servlet

  1. 编写servlet类
  1. 新建包servlet
  2. 新建MyServlet文件
package xyz.kxq.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(name = "myServlet", urlPatterns = "/srv")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("111");
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
    
}
  1. 在启动类上添加如下配置
@ServletComponentScan, @SpringBootApplication点进去会有一个@ComponentScan
  1.     会有一个自动扫描的过程
  2.     需要把Servlet注册为当前SpringBoot容器里面的一个bean
import com.mashibing.filter.MyHttpSessionListener;
import com.mashibing.servlet.MyServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ServletComponentScan
public class SpringbootWebApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebApplication.class, args);
    }

    //将自定义的servlet添加到springboot容器中,当配置了urlmappings之后,servlet自己的配置就不会生效
    @Bean
    public ServletRegistrationBean<MyServlet> getServletRegistrationBean(){
        ServletRegistrationBean<MyServlet> bean = new ServletRegistrationBean<>(new MyServlet(),"/s2");
        bean.setLoadOnStartup(1);
        return bean;
    }
}
getServletRegistrationBean: 获取servlet注册的一个Bean对象,可以加路由(/s2),当配置了urlmappings之后,servlet自己的配置就不会生效了
bean.setLoadOnStartup: 设置servlet什么时候启动,配置当前类,设置为1了
  1. 启动服务
  2. 访问 http://localhost:8080/s2/
  1. 打印结果为
111
111
  1. 所以说可以自己写一个servlet类,然后把servlet类注入到springboot里面就ok了。

 二、过滤器

包下新建filter目录,新建MyFilter文件

import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "MyFilter", urlPatterns = "/filter")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("filter");
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {
        System.out.println("destory");
    }
}

重启服务会发现init执行了

/*
2021-10-21 15:41:40.665  INFO 118196 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 725 ms
2021-10-21 15:41:40.700  INFO 118196 --- [           main] o.s.boot.web.servlet.RegistrationBean    : Servlet myServlet was not registered (possibly already registered?)
init
2021-10-21 15:41:40.929  INFO 118196 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-10-21 15:41:40.936  INFO 118196 --- [           main] xyz.kxq.SpringbootWebApplication         : Started SpringbootWebApplication in 1.34 seconds (JVM running for 2.217)
*/

当访问http://localhost:8080/filter, 发现filter执行了

/*
2021-10-21 15:44:47.008  INFO 118196 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-10-21 15:44:47.008  INFO 118196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-10-21 15:44:47.009  INFO 118196 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
filter
*/

如果所有的请求都需要过滤,urlPatterns="/*"

 

如果用FilterRegistratronBran设置对应注册的类,类似于上面servlet,向里面 new 对象就可以

官网

http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-embedded-container-servlets-filters-listeners

28.4.1.1、将 Servlet、Filter 和 Listener 注册为 Spring Bean

 

三、监听器

listener是servlet规范定义的一种特殊类,用于监听servletContext,HttpSession和ServletRequest等域对象的创建和销毁事件。监听域对象的属性发生修改的事件,

用于在事件发生前、发生后做一些必要的处理。可用于以下方面

/*
1、统计在线人数和在线用户
2、系统启动时加载初始化信息
3、统计网站访问量
4、记录用户访问路径
*/

 新建listener目录,新建MyHttpSessionListener文件

package xyz.kxq.listener;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyHttpSessionListener implements HttpSessionListener {
    public static int online = 0;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("创建session");
        online++;
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("销毁session");
    }
}

需要创建session对象,代码中也没有注解,此时可以在SpringbootWebApplication文件加入Bean

import com.mashibing.filter.MyHttpSessionListener;
import com.mashibing.servlet.MyServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ServletComponentScan
public class SpringbootWebApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebApplication.class, args);
    }

    @Bean
    public ServletListenerRegistrationBean listenerRegist(){
        ServletListenerRegistrationBean srb = new ServletListenerRegistrationBean();
        srb.setListener(new MyHttpSessionListener());
        System.out.println("listener");
        return srb;
    }
}

重新运行,会看到打印listener

/*
2021-10-22 10:26:49.921  INFO 151208 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-10-22 10:26:49.921  INFO 151208 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 747 ms
listener
*/

添加控制层代码

MyController

package xyz.kxq.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xyz.kxq.listener.MyHttpSessionListener;

@RestController
public class MyController {
    @RequestMapping("hello")
    public String hello(){
        return "hello, springboot";
    }

    @RequestMapping("online")
    public String online(){
        return "当前在线人数: " + MyHttpSessionListener.online + "人";
    }
}

浏览器访问

dispatcherServlet配置 springboot_spring_05

 

 刷新一直是0;

原因:

监听器中创建session对象后才online++

发送的请求没有任何session对象的请求,所以不会++

在MyController

package xyz.kxq.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xyz.kxq.listener.MyHttpSessionListener;

import javax.servlet.http.HttpSession;

@RestController
public class MyController {
    @RequestMapping("hello")
    public String hello(HttpSession session){
        session.setAttribute("aa", "aa");
        return "hello, springboot";
    }

    @RequestMapping("online")
    public String online(){
        return "当前在线人数: " + MyHttpSessionListener.online + "人";
    }
}

在浏览器访问

dispatcherServlet配置 springboot_java_06

 

 

dispatcherServlet配置 springboot_java_07

四、静态资源的配置

默认情况下,Spring Boot 将在 classpath 或者 ServletContext 根目录下从名为 /static

(/public、/resources 或 /META-INF/resources)目录中服务静态内容。

它使用了 Spring MVC 的 ResourceHttpRequestHandler,

因此您可以通过添加自己的 WebMvcConfigurerAdapter 并重写 addResourceHandlers 方法来修改此行为。

dispatcherServlet配置 springboot_ide_08

我们可能会有很多.html、 .js、 .css、 .image文件

原来我们新建web项目后会有一个WEB-INF,但是现在没有这个了

我们只能把它们加载到静态资源目录里面

dispatcherServlet配置 springboot_ide_09

有时resources会建 /static /public /resources等,那它是怎么找到的?

WebMvcAutoConfiguration

dispatcherServlet配置 springboot_java_10

dispatcherServlet配置 springboot_ide_11

 

 

 

dispatcherServlet配置 springboot_spring_12

public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
                CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
                if (!registry.hasMappingForPattern("/webjars/**")) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

                String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

            }
        }

1、!this.resourceProperties.isAddMappings()

/*
首先看是否修改了对应的资源目录
点进去resourceProperties -> ResourceProperties
@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {

有很多属性,像这些属性值我们可以自己在配置文件定义
application.properties文件可以定义
spring:
    mvc:
*/

2、!registry.hasMappingForPattern("/webjars/**")

写前端时可能会导入很多web框架

dispatcherServlet配置 springboot_spring_13

 

 

 添加到pom.xml文件中

<dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.4.1</version>
        </dependency>

dispatcherServlet配置 springboot_java_14

 

 

 意味着可以直接访问了

http://localhost:8080/webjars/jquery/3.4.1/jquery.js

dispatcherServlet配置 springboot_spring_15

 

 3、!registry.hasMappingForPattern(staticPathPattern)

静态资源匹配

String staticPathPattern = this.mvcProperties.getStaticPathPattern();

dispatcherServlet配置 springboot_java_16

 

 

dispatcherServlet配置 springboot_java_17

 

 ResourceProperties.class

dispatcherServlet配置 springboot_spring_18

 

 对应的加载顺序 resources -> static -> public

4、欢迎页面 

Spring Boot 支持静态和模板化的欢迎页面。它首先在配置的静态内容位置中查找 index.html 文件。如果找不到,则查找 index 模板。

如果找到其中任何一个,它将自动用作应用程序的欢迎页面。

dispatcherServlet配置 springboot_spring_19

 

 

dispatcherServlet配置 springboot_java_20

 

 

dispatcherServlet配置 springboot_java_21

 

 

dispatcherServlet配置 springboot_ide_22