跳至主要內容

SpringBoot与WEB应用

wangdx大约 11 分钟

项目打包

SpringBoot 程序打包

  • SpringBoot 项目开发完成后一定需要进行打包上线的处理,虽然 SpringBoot 也是一种 WEB 开发技术,但是其从设计之初所强调的就是一种微服务的实现技术,所以可以直接将 SpringBoot 打包为一个可运行 JAR 文件,这样开发者就减少了 WEB 容器项目部署的繁琐操作。
1、
bootJar {  // 是由SpringBoot提供的任务名称
    // 如果开发者有需要也可以自定一些打包后的配置项,例如:后缀、版本号、执行类
    archiveClassifier = 'lee' // 打包文件追加一个后缀
    archiveBaseName = 'yootkboot' // 设置打包文件的名称
    archiveVersion = project_version // 使用项目版本作为打包版本
    mainClassName = 'com.yootk.StartSpringBootApplication' // 程序启动类
}

2、java -jar yootkboot-1.0.0-lee.jar

3、http://localhost:8080/dept/get

调整 JVM 运行参数

默认 JVM 参数

  • 所有的 SpringBoot 程序代码都运行在 JVM 之中,但是在默认情况下,每一个 JVM 进程都只会分配当前物理内存的四分之一,同时还会根据内存的占用情况动态的进行内存资源的动态分配

1、
package com.yootk.action;

import com.yootk.common.action.abs.AbstractBaseAction;
import com.yootk.vo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController // 直接基于Rest架构进行处理,省略了@ResponseBody注解
@RequestMapping("/jvm/*") // 添加父路径
public class MemoryAction extends AbstractBaseAction { // 控制层的实现类
    @RequestMapping("memory")
    public Object memory() {
        Runtime runtime = Runtime.getRuntime(); // 获取Runtime对象实例
        Map<String, Object> data = new HashMap<>();
        data.put("MaxMemory", runtime.maxMemory());
        data.put("TotalMemory", runtime.totalMemory());
        data.put("FreeMemory", runtime.freeMemory());
        return data;
    }
}

2、
gradle bootRun

3、
localhost:8080/jvm/memory

4、
{
  "TotalMemory": 83886080, 80M
  "MaxMemory": 10703863808,9.9g
  "FreeMemory": 31788536 30M
}

java -jar -Xms30g -Xss256k -Xlog:gc -XX:+UseG1GC -Xmx30g yootkboot-1.0.0-lee.jar

配置 WEB 环境

application.properties

  • 在进行 SpringBoot 开发项目时,虽然大部分的情况下都会通过“application.yml”进行配置,实际上也可以定义 application.properties 文件实现配置处理。
1、
server:
  port: 80 # 服务的运行端口


2、
http://localhost/jvm/memory

3、

server:
  port: 80 # 服务的运行端口
  servlet:
    context-path: /muyan # 上下文路径名称

4、
http://localhost/muyan/jvm/memory


5、
server.port=9090
server.servlet.context-path=/yootk

6、

http://localhost:9090/yootk/jvm/memory

profile 环境配置

profile 动态切换

  • 项目的开发、测试以及上线都会存在有不同的网络服务环境,所以在项目中就需要为不同的运行环境设置不同的 profile 文件,一般来讲会分为三种 profile 环境,分别是:开发环境、测试环境以及生产环境
1、
server:
  port: 8080
  servlet:
    context-path: /dev

2、
server:
  port: 8181
  servlet:
    context-path: /test

3、
server:
  port: 8282
  servlet:
    context-path: /product

4、
spring:
  profiles:
    active: dev # 指的就是后缀名称

5、
java -jar yootkboot-1.0.0-lee.jar

6、
java -jar yootkboot-1.0.0-lee.jar --spring.profiles.active=test

7、
spring:
  profiles:
    active: test # 指的就是后缀名称

---
spring:
  profiles: dev
server:
  port: 9090
  servlet:
    context-path: /dev

---
spring:
  profiles: test
server:
  port: 9191
  servlet:
    context-path: /test

---
spring:
  profiles: product
server:
  port: 9292
  servlet:
    context-path: /product


打包 war 文件

Tomcat 部署 war 文件

  • 在传统的 WEB 项目开发中,往往都是基于容器的方式进行项目部署的,这样就要求将所编写的程序代码打包为一个“*.war”文件,随后将其部署到 WEB 容器的指定目录中以实现发布
1、
plugins {
    id 'java'
    id 'war' // 当前的项目具备有打包为war文件的支持
}

2、
package com.yootk; // 父包,这个包中的所有子包的类会被自动扫描

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication // 一个注解解决所有的问题
public class StartSpringBootApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(StartSpringBootApplication.class,args); // 运行SpringBoot程序
    }
}


3、
http://localhost/microboot-web-1.0.0/jvm/memory

localhost:9191/test/jvm/memory

整合 Jetty 容器

Jetty 是什么?

  • Tomcat 和 Jetty 都支持标准的 Servlet 规范以及 JakartaEE 规范,相比较而言,Jetty 的实现架构要比 Tomcat 更加简单。Tomcat 架构是基于容器设计的,基于 Service 实现处理每一个 Service 由一个 Container 和多个 Connector 所组成,形成一个个独立且完整的处理单元
  • Jetty 的核心是 Server,里面包含有多个 Handler 及-个 Connector,Jetty 的实现架构要比 Tomcat 更加简单,所有的扩展功能都可以基于 Handler 来实现
1、
gradle dependencies

2、
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jetty
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty', version: '2.4.3'

3、
project('microboot-web') { // 子模块
    dependencies { // 配置子模块依赖
        compile(project(':microboot-common')) // 引入其他子模块
        compile(libraries.'itextpdf') // 引入PDF相关依赖
        compile(libraries.'easypoi-spring-boot-starter') // 引入EasyPOI组件
    }
}
project('microboot-common') { // 子模块
    dependencies { // 配置子模块依赖
        compile('org.springframework.boot:spring-boot-starter-web') { // 引入SpringBoot依赖
            exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
        }
        compile('org.springframework.boot:spring-boot-starter-jetty')
    }
}

3、https://www.eclipse.org/jetty/

整合 Undertow 容器

Undertow

  • Undertow 是由红帽公司开发的一款基于 NIO 的高性能处理的 WEB 嵌入式服务器,在使用时不需要提供容器,只需要提供其内部的构建 API 即可快速搭建 WEB 服务,同时 Undertow 的生命周期完全由嵌入的应用程序进行进行控制,在 SpringBoot 依赖库中可以直接通过依赖管理实现 Undertow 的整合
1、
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-undertow
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-undertow', version: '2.4.3'
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-undertow
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-undertow', version: '3.2.3'



2、
project('microboot-common') { // 子模块
    dependencies { // 配置子模块依赖
        compile('org.springframework.boot:spring-boot-starter-web') { // 引入SpringBoot依赖
            exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
        }
        compile('org.springframework.boot:spring-boot-starter-undertow')
    }
}

获取 WEB 内置对象

SpringBoot 获取内置对象

  • 在 JavaWEB 开发中,内置对象的获取与应用是程序的核心机制,在 SpringBoot 中可以直接使用 SpringMVC 所提供的 ServletRequestAttributes 类获取 HttpServletRequest 以及 HttpServletResponse 接实例
1、
package com.yootk.action;

import com.yootk.common.action.abs.AbstractBaseAction;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController // 直接基于Rest架构进行处理,省略了@ResponseBody注解
@RequestMapping("/object/*") // 添加父路径
public class ObjectAction extends AbstractBaseAction { // 控制层的实现类
    @RequestMapping("first") // 子路径
    public Object firstShow(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>();
        result.put("【request】contextPath", request.getContextPath());
        result.put("【request】messageParam", request.getParameter("message"));
        result.put("【request】method", request.getMethod());
        result.put("【session】sessionId", request.getSession().getId());
        result.put("【application】VirtualServerName", request.getServletContext().getVirtualServerName());
        result.put("【application】InitParameter", request.getServletContext().getInitParameter("teacher"));
        return result;
    }
}

2、
server:
  port: 80
  servlet:
    context-parameters:
      teacher: 李兴华(爆可爱的小李老师)

3、
localhost/object/first

4、
package com.yootk.action;

import com.yootk.common.action.abs.AbstractBaseAction;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

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

@RestController // 直接基于Rest架构进行处理,省略了@ResponseBody注解
@RequestMapping("/object/*") // 添加父路径
public class ObjectAction extends AbstractBaseAction { // 控制层的实现类
    @RequestMapping("first") // 子路径
    public Object firstShow(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>();
        result.put("【request】contextPath", request.getContextPath());
        result.put("【request】messageParam", request.getParameter("message"));
        result.put("【request】method", request.getMethod());
        result.put("【session】sessionId", request.getSession().getId());
        result.put("【application】VirtualServerName", request.getServletContext().getVirtualServerName());
        result.put("【application】InitParameter", request.getServletContext().getInitParameter("teacher"));
        return result;
    }
    @RequestMapping("second") // 子路径
    public Object secondShow() {
        ServletRequestAttributes attributes =  (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        Map<String, Object> result = new HashMap<>();
        result.put("【request】contextPath", request.getContextPath());
        result.put("【request】messageParam", request.getParameter("message"));
        result.put("【request】method", request.getMethod());
        result.put("【session】sessionId", request.getSession().getId());
        result.put("【application】VirtualServerName", request.getServletContext().getVirtualServerName());
        result.put("【application】InitParameter", request.getServletContext().getInitParameter("teacher"));
        return result;
    }
}

localhost/object/second

读取资源文件

资源管理

  • 在进行项目开发中为了可以方便实现显示数据的维护处理操作,可以采用资源文件的方式实现文字内容的统一管理,同时利用资源文件并结合 Locale 类的对象实例也可以方便的实现文本国际化的处理操作,在 SpringBoot 中可以利用 application.yml 实现资源的引入,同时使用 MessageSource 接口实例根据指定的 key 获取对应的数据信息
1、
yootk.message=沐言科技
yootk.url=www.yootk.com

2、
yootk.message=沐言科技(MuYan Technology)
yootk.url=沐言优拓:www.yootk.com

3、
yootk.message=MuYan Technology
yootk.url=yootk : www.yootk.com

4、
spring:
  messages:
    basename: i18n/Message # 定义资源的BaseName

5、
package com.yootk.action;

import com.yootk.common.action.abs.AbstractBaseAction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@RestController // 直接基于Rest架构进行处理,省略了@ResponseBody注解
@RequestMapping("/i18n/*") // 添加父路径
public class I18NAction extends AbstractBaseAction { // 控制层的实现类
    @Autowired // 容器启动的时候会自动的提供此Bean实例
    private MessageSource messageSource; // 消息资源
    @RequestMapping("base") // 子路径
    public Object showBase() { // 进行请求参数的接收以及请求内容的回应
        Map<String, String> map = new HashMap<>(); // 定义Map集合
        map.put("message", this.messageSource.getMessage("yootk.message", null, Locale.getDefault()));
        map.put("url", this.messageSource.getMessage("yootk.url", null, Locale.getDefault()));
        return map;
    }
}

6、
localhost/i18n/base


7、
package com.yootk.action;

import com.yootk.common.action.abs.AbstractBaseAction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@RestController // 直接基于Rest架构进行处理,省略了@ResponseBody注解
@RequestMapping("/i18n/*") // 添加父路径
public class I18NAction extends AbstractBaseAction { // 控制层的实现类
    @Autowired // 容器启动的时候会自动的提供此Bean实例
    private MessageSource messageSource; // 消息资源
    @RequestMapping("base") // 子路径
    public Object showBase() { // 进行请求参数的接收以及请求内容的回应
        Map<String, String> map = new HashMap<>(); // 定义Map集合
        map.put("message", this.messageSource.getMessage("yootk.message", null, Locale.getDefault()));
        map.put("url", this.messageSource.getMessage("yootk.url", null, Locale.getDefault()));
        return map;
    }
    @RequestMapping("locale") // 子路径
    public Object showLocale(Locale loc) { // 进行请求参数的接收以及请求内容的回应
        Map<String, String> map = new HashMap<>(); // 定义Map集合
        map.put("message", this.messageSource.getMessage("yootk.message", null, loc));
        map.put("url", this.messageSource.getMessage("yootk.url", null, loc));
        return map;
    }
}


8、
package com.yootk.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
@Configuration // 配置Bean
public class DefaultLocaleResolver implements LocaleResolver {  // 配置转换器
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        // 此时接收的参数名称肯定是loc,而传递的loc参数的内容一般是“zh_CN”
        String loc = request.getParameter("loc"); // 接收请求参数
        if (!StringUtils.hasLength(loc)) {   // 现在有内容
            return Locale.getDefault(); // 使用默认的Locale实例
        } else {    // 现在有请求数据
            String [] split = loc.split("_"); // 数据拆分
            return new Locale(split[0], split[1]); // 手工实例化Locale对象
        }
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {}
    @Bean
    public LocaleResolver localeResolver() { // 定义转换处理的Bean
        return new DefaultLocaleResolver(); // 返回LocaleResolver实例
    }
}

9、
localhost/i18n/locale?loc=zh_CN
localhost/i18n/locale?loc=en_US


文件上传

1、
server:
  port: 80
spring:
  servlet:
    multipart: # 实现文件上传的相关配置
      enabled: true # 启用文件上传支持(默认就是启用状态)
      max-file-size: 10MB # 支持单个文件上传最大长度
      max-request-size: 20MB # 每次请求允许上传的总长度
      file-size-threshold: 512KB # 每当达到512KB的时候进行磁盘写入
      location: / # 临时存储目录


2、
package com.yootk.action;

import com.yootk.common.action.abs.AbstractBaseAction;
import com.yootk.vo.Message;
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 java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/form/*")
public class UploadAction extends AbstractBaseAction {
    @PostMapping("upload")
    public Object uploadHandler(Message message, MultipartFile photo) {
        Map<String, Object> result = new HashMap<>(); // 保存最终的上传结果
        result.put("message", message); // 普通对象
        result.put("photoName", photo.getName());
        result.put("photoOriginalFilename",photo.getOriginalFilename());
        result.put("photoContentType", photo.getContentType());
        result.put("photoSize", photo.getSize());
        return result;
    }
}


3、
curl -X POST -F "photo=@h:\muyan_yootk.png" -F "title=MuyanYootk" -F "content=www.yootk.com" -F "pubdate=2016-12-26" http://localhost/form/upload


整合 WEB 过滤器

过滤器

  • 在 WEB 中提供的过滤器组件,可以针对用户配置请求路径实现自动过滤处理,例如:session 登录判断或者是访问授权检测,在 SpringBoot 中可以像传统的 WEB 开发一样通过“@WebFilter”注解实现过滤器的定义
1、
package com.yootk.filter;

import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/*") // 过滤处理路径
public class MessageFilter extends HttpFilter { // 过滤器定义

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        if ("/message/echo".equals(request.getRequestURI())) {  // 判断当前的路径
            String title = request.getParameter("title"); // 接收title参数
            if (StringUtils.hasLength(title)) { // 存在有数据
                System.err.println("【MessageFilter】title参数内容为:" + title);
            }
        }
        chain.doFilter(request, response);
    }
}

2、

package com.yootk; // 父包,这个包中的所有子包的类会被自动扫描

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

@SpringBootApplication // 一个注解解决所有的问题
@ServletComponentScan // Servlet组件扫描
public class StartSpringBootApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(StartSpringBootApplication.class,args); // 运行SpringBoot程序
    }
}


3、
localhost/message/message?title=沐言科技&content=www.yootk.com&pubdate=1998-09-19

4、
package com.yootk.filter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MuyanFilter extends HttpFilter {
    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("【MuyanFilter】*************************************");
        chain.doFilter(request, response);
    }
}

5、
package com.yootk.filter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class YootkFilter extends HttpFilter {
    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("【YootkFilter】*************************************");
        chain.doFilter(request, response);
    }
}

6、
package com.yootk.filter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class EduFilter extends HttpFilter {
    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("【EduFilter】*************************************");
        chain.doFilter(request, response);
    }
}

7、
package com.yootk.config;

import com.yootk.filter.EduFilter;
import com.yootk.filter.MuyanFilter;
import com.yootk.filter.YootkFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import javax.servlet.Filter;

@Configuration
@Order(-10) // 这个配置无法在过滤器上使用
public class WebFilterConfig { // 定义WEB过滤器
    @Bean
    public FilterRegistrationBean getMuyanFilterRegistration() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(this.getMuyanFilter());
        filterRegistrationBean.setName("MFilter");
        filterRegistrationBean.addUrlPatterns("/orders/*");
        filterRegistrationBean.setOrder(5); // 设置过滤器的执行顺序
        return filterRegistrationBean;
    }
    @Bean
    public FilterRegistrationBean getYootkFilterRegistration() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(this.getYootkFilter());
        filterRegistrationBean.setName("AFilter");
        filterRegistrationBean.addUrlPatterns("/orders/*");
        filterRegistrationBean.setOrder(2); // 设置过滤器的执行顺序
        return filterRegistrationBean;
    }
    @Bean
    public FilterRegistrationBean getEduFilterRegistration() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(this.getEduFilter());
        filterRegistrationBean.setName("ZFilter");
        filterRegistrationBean.addUrlPatterns("/orders/*");
        filterRegistrationBean.setOrder(-100); // 设置过滤器的执行顺序
        return filterRegistrationBean;
    }
    @Bean
    public Filter getMuyanFilter() {
        return new MuyanFilter(); // 手工实例化Filter对象
    }
    @Bean
    public Filter getYootkFilter() {
        return new YootkFilter(); // 手工实例化Filter对象
    }
    @Bean
    public Filter getEduFilter() {
        return new EduFilter(); // 手工实例化Filter对象
    }
}

8、
localhost/orders/free

demo


上次编辑于: