Tomcat底层启动分析+Spring容器初始化+Tomcat关联Spring容器
(1)创建一个Maven项目,修改pom.xml文件:我们需要自己创建Tomcat对象,因此在引入的场景启动器中排除SpringBoot内嵌的Tomcat,并引入tomcat依赖库
<!--导入SpringBoot父工程-规定写法-->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.5.3</version>
</parent>
<dependencies>
<!--导入web项目场景启动器:会自动导入和web开发相关的所有依赖[jar包]-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--因为我们要自己创建Tomcat对象,并启动,因为我们要先排除内嵌的spring-boot-starter-tomcat-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--指定Tomcat版本,引入tomcat依赖库
1.指定版本为8.5.75
2.如果我们引入了自己指定的tomcat,一定要记住把前面的spring-boot-starter-tomcat排除
3.否则会出现GenericServletNotFound错误-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.75</version>
</dependency>
</dependencies>
(2)创建LiSpringApplication.java
package com.li.lispringboot;
import org.apache.catalina.startup.Tomcat;
/**
* @author 李
* @version 1.0
*/
public class LiSpringApplication {
//创建tomcat对象,并关联spring容器,然后启动tomcat
public static void run() {
try {
//创建tomcat对象
Tomcat tomcat = new Tomcat();
//设置默认端口-9090
tomcat.setPort(9090);
//启动,就会在指定端口监听
tomcat.start();
//等待请求接入
System.out.println("======9090端口等待请求接入======");
tomcat.getServer().await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(3)LiMainApp
package com.li.lispringboot;
/**
* @author 李
* @version 1.0
*/
public class LiMainApp {
public static void main(String[] args) {
//启动LiSpringBoot项目/程序
LiSpringApplication.run();
}
}
(4)测试启动main方法,后台输出如下:
打开浏览器,访问9090端口,页面一片空白,因为这时候还没有接入其他组件。
(1)创建Monster.java,做一个测试bean
package com.li.lispringboot.bean;
/**
* @author 李
* @version 1.0
*/
public class Monster {
}
(2)创建HelloController.java,做一个测试Controller
package com.li.lispringboot.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 李
* @version 1.0
*/
@RestController
public class HelloController {
@RequestMapping("/hello")
public String Hello() {
return "Hello,I'm HelloController!";
}
}
(3)创建LiConfig.java,作为Spring的配置文件
package com.li.lispringboot.config;
import com.li.lispringboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author 李
* @version 1.0
* 配置类-作为Spring的配置文件
* 这里有一个问题,容器怎么知道要扫描哪些包?
*/
@Configuration
@ComponentScan("com.li.lispringboot")//指定要配置类扫描哪些包
public class LiConfig {
//注入Bean-Monster对象到Spring容器
@Bean
public Monster monster() {
return new Monster();
}
}
(4)LiWebApplicationInitializer.java
package com.li.lispringboot;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
/**
* @author 李
* @version 1.0
* LiWebApplicationInitializer容器初始化类的任务:
* 1.创建spring容器
* 2.加载/关联spring容器的配置-按照注解方式
* 3.完成spring容器配置的bean的创建,依赖注入
* 4.创建前端控制器(DispatcherServlet),让其持有spring容器
* 5.这的onStartup()方法是tomcat来调用,并把ServletContext对象传入
*/
public class LiWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println("onStartup ...");
//加载-Spring Web Application Configuration
AnnotationConfigWebApplicationContext ac =
new AnnotationConfigWebApplicationContext();
//在ac中注册配置类LiConfig
ac.register(LiConfig.class);
ac.refresh();//完成bean的创建和配置
/*
创建注册非常重要的前端控制器-DispatchServlet
让 DispatchServlet持有spring容器-ac
这样就可以进行映射分发
*/
DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
//返回ServletRegistration.Dynamic对象
ServletRegistration.Dynamic registration
= servletContext.addServlet("app", dispatcherServlet);
//设置前端控制器的加载顺序(这里设置为当tomcat启动时,就加载)
registration.setLoadOnStartup(1);
//设置前端控制器拦截所有请求,并进行分发处理
registration.addMapping("/");
}
}
(1)修改LiSpringApplication,将tomcat和Spring容器关联
package com.li.lispringboot;
import org.apache.catalina.startup.Tomcat;
/**
* @author 李
* @version 1.0
*/
public class LiSpringApplication {
//创建tomcat对象,并关联spring容器,然后启动tomcat
public static void run() {
try {
//创建tomcat对象
Tomcat tomcat = new Tomcat();
/*
1.让tomcat能够将请求转发到SpringWeb容器,因此需要关联
2."/liboot" 就是我们的项目的 application context,即原来配置tomcat时的项目名称
3."D:\\IDEA-workspace\\li-springboot" 指定项目的路径
*/
tomcat.addWebapp("/liboot", "D:\\IDEA-workspace\\li-springboot");
//设置默认端口-9090
tomcat.setPort(9090);
//启动,就会在指定端口监听
tomcat.start();
//等待请求接入
System.out.println("======9090端口等待请求接入======");
tomcat.getServer().await();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2)在LiMainApp.java中重新启动项目,在浏览器中访问测试Controller,访问成功:
如果启动时报异常,如下:
严重: Servlet [jsp] in web application [/liboot] threw load() exception java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet
解决方案是:引入对应版本的 Jasper包即可。
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>8.5.75</version>
</dependency>
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复
在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定
我试图在Ubuntu14.04中使用Curl安装RVM。我运行了以下命令:\curl-sSLhttps://get.rvm.io|bash-sstable出现如下错误:curl:(7)Failedtoconnecttoget.rvm.ioport80:Networkisunreachable非常感谢解决此问题的任何帮助。谢谢 最佳答案 在执行curl之前尝试这个:echoipv4>>~/.curlrc 关于ruby-在Ubuntu14.04中使用Curl安装RVM时出错,我们在Stack
我目前有一个reddit克隆类型的网站。我正在尝试根据我的用户之前喜欢的帖子推荐帖子。看起来K最近邻或k均值是执行此操作的最佳方法。我似乎无法理解如何实际实现它。我看过一些数学公式(例如k表示维基百科页面),但它们对我来说并没有真正意义。有人可以推荐一些伪代码,或者可以查看的地方,以便我更好地了解如何执行此操作吗? 最佳答案 K最近邻(又名KNN)是一种分类算法。基本上,您采用包含N个项目的训练组并对它们进行分类。如何对它们进行分类完全取决于您的数据,以及您认为该数据的重要分类特征是什么。在您的示例中,这可能是帖子类别、谁发布了该项