这一节我们主要学习如何整合 Web 相关技术:

  • Servlet
  • Filter
  • Listener
  • 访问静态资源
  • 文件上传
  • 文件下载

  Web三大基本组件分别是:Servlet,Listener,Filter。正常来说一旦我们用了框架,这三个基本就用不上了,Servlet 被 Controller 代替,Filter 被拦截器代替。但是可能在一些特殊的场景下不得不使用这三个基本组件时,Spring Boot 中要如何去引用呢?下面我们来一起学习一下。

  Spring Boot 集成了 Servlet 容器,当我们在 pom.xml 中增加 spring-boot-starter-web 组件依赖时,不做任何 web 相关的配置便能提供 web 服务,这还得归功于 Spring Boot 自动配置的功能,帮我们创建了一堆默认的配置,以前在 web.xml 中的配置,现在都可以通过 Spring Bean 的方式或者注解方式进行配置,由 Spring 来进行生命周期的管理,大多数情况下,我们需要自定义这些配置,如:修改服务的启动端口,ContextPath,Filter,Listener,Servlet,Session超时时间等等。

  Spring Boot 提供了 ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean@WebServlet@WebFilter@WebListener 三种类型分别配置应用的 Servlet,Filter,Listener。

  创建 jar 项目,编写 pom.xml

<?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>com.springboot</groupId>
    <artifactId>springboot-hello</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>springboot-hello</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <!-- 引入springboot父类依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencies>
        <!-- springboot-web 组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

整合Servlet

  Servlet 是 Java Servlet 的简称,称为小服务程序或服务连接器,用 Java 编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。

  Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet 可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

方法一

  通过注解扫描完成 Servlet 组件的注册

  编写FirstServlet.java

package com.springboot.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;

/*
    配置文件的写法:
    <servlet>
        <servlet-name>FirstServlet</servlet-name>
        <servlet-class>com.springboot.servlet.FirstServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FirstServlet</servlet-name>
        <url-pattern>/first</url-pattern>
    </servlet-mapping>
 */
@WebServlet(name = "FirstServlet", urlPatterns = {"/first"})
public class FirstServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("FirstServlet");
    }

}

  启动类App.java

package com.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
// 在 SpringBoot 启动时会扫描 @WebServlet,并将该类实例化
@ServletComponentScan
public class App {

    // 项目中不需要有多个 main 方法只需要有一个入口就可以了
    public static void main(String[] args) {
        // 主函数运行 springboot 项目
        SpringApplication.run(App.class, args);
    }

}

方法二

  通过方法完成 Servlet 组件的注册

  编写SecondServlet.java

package com.springboot.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 = "SecondServlet", urlPatterns = {"/second"})
public class SecondServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("FirstServlet");
    }

}

  启动类App.java

package com.springboot;

import com.springboot.servlet.SecondServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class App {

    // 项目中不需要有多个 main 方法只需要有一个入口就可以了
    public static void main(String[] args) {
        // 主函数运行 springboot 项目
        SpringApplication.run(App.class, args);
    }

    // 通过方法完成 Servlet 组件的注册
    @Bean
    public ServletRegistrationBean getServletRegistrationBean() {
        ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet());
        bean.addUrlMappings("/second");
        return bean;
    }

}

整合Filter

  过滤器:Filter 是 Servlet 技术中最实用的技术,Web开发人员通过 Filter 技术,对 web 服务器管理的所有 web 资源,例如:Jsp,Servlet,图片,HTML,CSS,JS等文件进行拦截,从而实现一些特殊的功能。例如实现 URL 级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。它主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行后处理。

  使用 Filter 的完整流程:Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成响应,最后 Filter 再对服务器响应进行后处理。

方法一

  通过注解扫描完成 Filter 组件的注册

  编写FirstFilter.java

package com.springboot.filter;

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

/*
    配置文件写法:
    <filter>
        <filter-name>FirstFilter</filter-name>
        <filter-class>com.springboot.filter.FirstFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FirstFilter</filter-name>
        <url-pattern>/first</url-pattern>
    </filter-mapping>
 */
@WebFilter(filterName = "FirstFilter", urlPatterns = {"/first"})
public class FirstFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("FirstFilter Begin");
        filterChain.doFilter(req, resp);
        System.out.println("FirstFilter End");
    }

    @Override
    public void destroy() {

    }

}

  启动类App.java

package com.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class App {

    // 项目中不需要有多个 main 方法只需要有一个入口就可以了
    public static void main(String[] args) {
        // 主函数运行 springboot 项目
        SpringApplication.run(App.class, args);
    }

}

方法二

  通过方法完成 Filter 组件的注册

  编写SecondFilter.java

package com.springboot.filter;

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

@WebFilter(filterName = "SecondFilter", urlPatterns = {"/second"})
public class SecondFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("SecondFilter Begin");
        filterChain.doFilter(req, resp);
        System.out.println("SecondFilter End");
    }

    @Override
    public void destroy() {

    }

}

  启动类App.java

package com.springboot;

import com.springboot.filter.SecondFilter;
import com.springboot.servlet.SecondServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class App {

    // 项目中不需要有多个 main 方法只需要有一个入口就可以了
    public static void main(String[] args) {
        // 主函数运行 springboot 项目
        SpringApplication.run(App.class, args);
    }

    // 通过方法完成 Servlet 组件的注册
    @Bean
    public ServletRegistrationBean getServletRegistrationBean() {
        ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet());
        bean.addUrlMappings("/second");
        return bean;
    }

    // 通过方法完成 Filter 组件的注册
    @Bean
    public FilterRegistrationBean getFilterRegistrationBean() {
        FilterRegistrationBean bean = new FilterRegistrationBean(new SecondFilter());
        bean.addUrlPatterns("/second");
        return bean;
    }

}

整合Listener

  Servlet 的监听器 Listener 实现了 javax.servlet.ServletContextListener 接口的服务器端程序,它随 web应用的启动而启动,只初始化一次,随 web 应用的停止而销毁。主要作用是: 做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等。

方法一

  通过注解扫描完成 Listener 组件的注册

  编写FirstListener.java

package com.springboot.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/*
    配置文件写法:
    <listener>
        <listener-class>com.springboot.listener.FirstListener</listener-class>
    </listener>
 */
@WebListener
public class FirstListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("FirstListener Init");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }

}

​ 启动类App.java

package com.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan
public class App {

    // 项目中不需要有多个 main 方法只需要有一个入口就可以了
    public static void main(String[] args) {
        // 主函数运行 springboot 项目
        SpringApplication.run(App.class, args);
    }

}

方法二

  通过方法完成 Listener 组件注册

  编写SecondListener.java

package com.springboot.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class SecondListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("SecondListener Init");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }

}

  启动类App.java

package com.springboot;

import com.springboot.listener.SecondListener;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class App {

    // 项目中不需要有多个 main 方法只需要有一个入口就可以了
    public static void main(String[] args) {
        // 主函数运行 springboot 项目
        SpringApplication.run(App.class, args);
    }

    // 通过方法完成 Listener 组件注册
    @Bean
    public ServletListenerRegistrationBean<SecondListener> getServletListenerRegistrationBean() {
        return new ServletListenerRegistrationBean(new SecondListener());
    }

}

访问静态资源

static目录

  在我们开发web应用的时候,需要引用大量的js、css、图片等静态资源。

  Spring Boot 默认提供静态资源目录位置需要置于 classpath 下,目录名需符合如下规则:

   /static

   /public

   /resources

   /META-INF/resources

  比如:

   启动项目后,位于 static 下的资源直接访问,路径里无需添加 /static

   如果 /static下还有文件夹需要添加对应路径访问

  访问:http://localhost:8080/spring-boot.svg

  demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>资源访问</title>
</head>
<body>
    <p>资源访问</p>
    <img src="images/java.jpg">
</body>
</html>

  访问:http://localhost:8080/demo.html

ServletContext目录

  在 src/main/webapp 下,目录名称必须是 webapp

  demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>资源访问</title>
</head>
<body>
    <p>资源访问</p>
    <img src="../images/spring-boot.svg">
</body>
</html>

  访问:http://localhost:8080/html/demo.html

文件上传

  Spring MVC 通过 MultipartResolver(多部件解析器)对象实现对文件上传的支持。

  MultipartResolver 是一个接口对象,需要通过它的实现类 CommonsMultipartResolver 来完成文件的上传工作。在 Spring Boot 中又是如何来完成的,我们一起学习一下。

  FileController.java

package com.springboot.controller;

import org.springframework.web.bind.annotation.PostMapping;
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;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/file")
public class FileController {

    /**
     * 文件上传
     *
     * @param fileName
     * @param request
     * @return
     */
    @PostMapping("/upload")
    public Map<String, Object> fileUpload(MultipartFile fileName,
                                          HttpServletRequest request) {
        try {
            // 获取文件名
            System.out.println("文件名:" + fileName.getOriginalFilename());
            // 将文件保存至当前项目 src/main/upload 文件夹
            String baseDir = System.getProperty("user.dir") + "/src/main/upload/";
            fileName.transferTo(new File(baseDir + fileName.getOriginalFilename()));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Map<String, Object> map = new HashMap<>();
        map.put("message", "success");
        return map;
    }

}

  resources/static/fileUpload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
    <form action="file/upload" method="post" enctype="multipart/form-data">
        文件上传:<input type="file" name="fileName"/>
        <input type="submit" value="上传"/>
    </form>
</body>
</html>

  启动类App.java

package com.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    // 项目中不需要有多个 main 方法只需要有一个入口就可以了
    public static void main(String[] args) {
        // 主函数运行 springboot 项目
        SpringApplication.run(App.class, args);
    }

}

  演示效果:

设置上传文件大小的默认值

  Spring 限制了文件上传的大小值,默认是10MB,需要通过配置文件设置,

  在 resources 根目录下添加一个 Spring Boot 的配置文件 application.properties。

  resources/application.properties

# 设置单个上传文件的大小
spring.http.multipart.max-file-size=200MB
# 设置一次请求上传文件的总容量
spring.http.multipart.max-request-size=200MB

文件下载

  本文基于简单的功能实现,编写 Get 请求方法,将刚才上传的文件进行下载。

  FileController.java

package com.springboot.controller;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/file")
public class FileController {

    /**
     * 文件上传
     *
     * @param fileName
     * @param request
     * @return
     */
    @PostMapping("/upload")
    public Map<String, Object> fileUpload(MultipartFile fileName,
                                          HttpServletRequest request) {
        ...
    }

    /**
     * 文件下载
     *
     * @param fileName
     * @param request
     * @param response
     */
    @GetMapping("/download")
    public void fileDownload(String fileName,
                             HttpServletRequest request,
                             HttpServletResponse response) {
        // 获取文件存储路径
        String baseDir = System.getProperty("user.dir") + "/src/main/upload/";
        // 读取文件,声明输出流
        try (InputStream is = new FileInputStream(new File(baseDir, fileName));
             OutputStream os = response.getOutputStream()) {
            // 设置响应数据类型
            response.setContentType("application/x-download");
            response.addHeader("Content-Disposition", "attchment;filename=" + fileName);
            // 复制写出文件
            IOUtils.copy(is, os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

  演示效果:

  ✍️本章节到这里就结束了,喜欢的话就点赞

Spring Boot 整合 Web 开发的更多相关文章

  1. 【Spring Boot】web开发

    ​ springboot在开发web项目的时候具备天然的优势,现在的很多企业级开发都是依托于springboot的. ​ 使用springboot的步骤: ​ 1.创建一个SpringBoot应用,选 ...

  2. Spring Boot的web开发

    web开发的自动配置类:org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration 自动配置的ViewResolver 视图的 ...

  3. 跟我学Spring Boot(三)Spring Boot 的web开发

    1.Web开发中至关重要的一部分,Web开发的核心内容主要包括内嵌Servlet容器和SpringMVC spring boot  提供了spring-boot-starter-web 为web开发提 ...

  4. Spring Boot的web开发&静态资源配置方式

    Web开发的自动配置类:org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration 1.1. 自动配置的ViewResolve ...

  5. Spring Boot 整合Web 层技术(整合Servlet)

    1 整合Servlet 方式一1.1通过注解扫描完成Servlet 组件的注册      1.1.1创建Servlet /*** 整合Servlet 方式一*/@WebServlet(name = & ...

  6. Spring boot 整合JSP开发步骤

    1. 新建Springboot项目,war <dependency> <groupId>org.springframework.boot</groupId> < ...

  7. Spring boot 整合CXF webservice 遇到的问题及解决

    将WebService的WSDL生成的代码的命令: wsimport -p com -s . com http://localhost:8080/service/user?wsdl Spring bo ...

  8. Spring Boot 整合JDBC 实现后端项目开发

    一.前言 二.新建Spring Boot 项目 三.Spring Boot 整合JDBC 与MySQL 交互 3.1 新建数据表skr_user 3.2 Jdbcproject 项目结构如下 3.3 ...

  9. Spring Boot集成MyBatis开发Web项目

    1.Maven构建Spring Boot 创建Maven Web工程,引入spring-boot-starter-parent依赖 <project xmlns="http://mav ...

随机推荐

  1. Codeforces 697D

    题意略. 思路: 对于随机产生的一个数列,对于某个儿子,其兄弟在其前面的概率为 1 / 2. 所以这个兄弟对期望的贡献为son[v] / 2,所有兄弟加起来即为(tot - 1) / 2. 详见代码: ...

  2. 《Java 编写基于 Netty 的 RPC 框架》

    一 简单概念 RPC: ( Remote Procedure Call),远程调用过程,是通过网络调用远程计算机的进程中某个方法,从而获取到想要的数据,过程如同调用本地的方法一样. 阻塞IO :当阻塞 ...

  3. 最近学习了限流与RateLimiter

    前言 分布式环境下应对高并发保证服务稳定几招,按照个人理解,优先级从高到低分别为缓存.限流.降级.熔断,每招都有它的作用,本文重点就讲讲限流这部分. 坦白讲,其实上面的说法也不准确,因为服务降级.熔断 ...

  4. 【数据结构】10.java源码关于LinkedHashMap

    目录 1.LinkedHashMap的内部结构 2.LinkedHashMap构造函数 3.元素新增策略 4.元素删除 5.元素修改和查找 6.特殊操作 7.扩容 8.总结 1.LinkedHashM ...

  5. 学会spss就能找到数据分析工作吗

     大学课堂上学习了spss,老师也讲了很多知识,但是现在准备毕业了,我做的实习工作就是用业内的数据进行最新的行业研究.现在真正需要用到spss进行分析了,我却看不懂老板给的数据和分析要求,难道这就是理 ...

  6. Codeforces 919D Substring (拓扑排序+树形dp)

    题目:Substring 题意:给你一个有向图, 一共有n个节点 , m条变, 一条路上的价值为这个路上出现过的某个字符最多出现次数, 现求这个最大价值, 如果价值可以无限大就输出-1. 题解:当这个 ...

  7. JOBDU 1199 找位置

    题目1199:找位置 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2645 解决:1286 题目描述: 对给定的一个字符串,找出有重复的字符,并给出其位置,如:abcaaAB12ab12 ...

  8. Kubernetes集群部署核心步骤

    目录 前言 一.所有节点安装docker 二.所有节点安装kubeadm 三.安装master节点 四.部署网络插件 五.安装node节点 六.运行一个demo 前言 这里使用环境:Ubuntu 18 ...

  9. 深入理解 Java 中 SPI 机制

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/vpy5DJ-hhn0iOyp747oL5A作者:姜柱 SPI(Service Provider ...

  10. d3.js 制作简单的贪吃蛇

    d3.js是一个不错的可视化框架,同时对于操作dom也是十分方便的.今天我们使用d3.js配合es6的类来制作一个童年小游戏–贪吃蛇.话不多说先上图片. 1. js snaker类 class Sna ...