我们前面的知识点使用spring boot开发了一个用户管理的demo,但是启动都使用的是spring-boot-web依赖导入的内置tomcat,这在正式的生产环境中一般是不提倡的,除非开发的系统在使用上要求不高,而且很多时候网络策略只给了少量的端口,因此你办不到模块都用不同的内置web软件并占用不同的端口,所以单凭内置的tomcat是无法满足我们的开发需求的,这时通常的开发手段就是部署到外置的tomcat上。现在我们一起看一下如何部署。
第一步:首先我们需要在maven的pom中直接修改打包方式为war
<packaging>war</packaging>
第二步:既然使用外部tomcat那就必须保证没有任何的内置web插件,我们前面的知识点教大家使用了undertow
内置web插件,同理我们只需要删掉它的依赖,并保持内置tomcat是禁用的
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
第三步:我们需要在项目中准备一个配置类,这个类如果有SSM基础的朋友,应该知道spring容器有一种手动写启动类的方式,作为兄弟的spring-boot当然也有,只是这个类并不是让我们手动运行的,而是默许tomcat这类web链接软件去调用启动spring-boot的一个类
package com.wy.scjg.config;
import com.wy.scjg.ScjgApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* @创建人 wangyang
* @创建时间 2022/10/1
* @描述
*
* 外部web链接软件 配置类
* 必须重写configure方法并指定该项目的系统类
*/
public class MySpringBootServletIni extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(ScjgApplication.class);
}
}
第四步:在build
标签中添加一个包名,这个名字决定了当前项目打包后的包名,这个设置主要是因为正式开发中,包名打完之后带版本号的,而我们又不方便为了一个版本号而去每次打包后还要去手动改包名,所以在这里就可以设置一下
<finalName>scjg</finalName>
第五步:在打包之前,如果你的项目中使用了javax.servlet
包下的资源,你会发现项目中报错,是因为上面删除了内置web链接软件因此相关依赖没有了,我们单独导入一下即可
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
第六步:打包,但是打包之前,一定要点击下图这个图标,不让maven进行test不然会报错
打好包后将war包放在tomcat的webapps文件夹下,并运行bin目录下的startup.bat
启动的黑窗口不报错就可以了,但在这个时候要知道一个问题,用外部的web链接软件启动后,springboot项目中配置的web相关配置项以及启动类就都失效了,统一按照所使用的web链接软件的配置运行,例如此时的tomcat需要使用 “默认8080端口+项目名+请求路径” 进行访问
,但是对于springboot项目来说这其中就涉及到一个问题,见特别说明
,这里我写了一个toLogin
测试页面,首次访问我手写的全路所以可以展示出访问效果
特别说明
你要把一个本来是内置web软件的spring boot项目变成外置部署的方式,那么一定要检查你所使用的外部软件的配置,需要检查它的访问方式是否已改成不需要项目名的方式
,因为内置web软件时,你的所有请求路径是例如localhost:91:/login
的这种springboot内置访问方式,而你外置之后根据不同的外置web软件你需要注意请求路径发生的改变。如果你在项目中单独编辑了spring web环境,在请求前缀那里添加了等值的项目名,这种情况大家可以自己试一试,大概率也会失效,跟随整体统一使用外部web软件的配置。
就像上面截图中的http://localhost:8080/scjg/user/toLogin
一样,它在内置web时访问的路径应该是http://localhost:91/user/toLogin
,端口号不需要你担心,但是端口号和请求路径中间多了一个项目名,这个就会导致你首次手动输入的路径可以正常访问,但是之后的系统运行都是写好的代码,由于没有项目名导致全是404
,到此给大家附上修改tomcat不要项目名访问的配置方式
打开tomcat的server.xml配置文件
我们需要将配置中的HOST
修改一下,修改前是如下值
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
修改后如下,注意把你的项目名改好
<Host name="localhost" appBase="" unpackWARs="true" autoDeploy="true">
<Context docBase="webapps/你的项目名" path="" reloadable="true" source="org.eclipse.jst.jee.server:你的项目名"/>
这样你才可以正常的访问在外置tomcat上的springboot项目
这个时候或许有人会想到和SSM那样使用试图解析器
解决项目名的问题,但是根据本作者实操发现这个方法行不通,首先面临的第一个问题就是springboot前端页面开发方式中相对成体系的不再和SSM一样只有jsp了,这就导致不同的前端技术所用的配置视图解析方式是不同的
就比如,本系列知识点中介绍了模板引擎freemaker以及SSM时代所用的JSP,这两个技术的视图解析配置中freemarker用的是spring.freemarker.prefix和spring.freemarker.suffix
,而JSP用的是spring.mvc.view.prefix和spring.mvc.view.suffix
当然真理需要实践,通过具体实操发现,在使用视图解析器解决项目名问题时,tomcat运行后请求路径是没有错,但是前端所有的返回都是问号未知错误。
而且springboot是一个倾向于前后端分离、模块化开发方式的框架,同时正式开发中后端大多都是API接口而不是单纯的跳转。就算你人为干预开发成只跳转的项目,可是对后端控制解析器路径来说有多少个前端模块和前端模块的路径是什么,这些均是未知数。
需要注意的是,经过这样配置以后的tomcat它的默认访问项目就已经定死了,但是他不影响原来的访问方式。除了视图解析器,也不要去尝试在开发工具中设置spring boot自带的web环境中提供的前缀,因为上面也说了,一旦部署在外部,自带的web环境就失效了,在自带环境中设置的前缀有没有生效是一个画问号的事情?所以如果你要部署在外部,就使用上面的方式将项目设置为tomcat的默认访问项目,如果你有多个,就将这些项目融合成一个启动项目。不过一般正式开发中都是有很多服务器用来运行不同的子模块webAPP
的,不可能所有的web模块都放在一台机器上。
还要注意的是裸跑tomcat在Windows系统上默认的cmd窗口不是utf-8所以你需要在cmd中运行chcp 65001随后用命令行的方式选择tomcat的启动命令
在最后对tomcat和spring boot两个技术一起使用,需要给初学者一点说明,在日后的正式工作中,如果后端模块使用spring boot开发,那么只有很小的可能才会使用tomcat,这其中最主要的原因有那么几点。首先第一
是经历了上面的配置,不难明白spring boot在tomcat上运行需要占用tomcat的默认访问实例的,而tomcat自身除了默认的缺省名称访问实例,其他的tomcat实例都需要拥有实例名称来区别不同tomcat实例。当我们不配置的时候,例如上一代的SSM框架,我们直接把war包扔进去解析之后,它是以war包名作为实例名称,这在本质上是更改了controller控制器的访问路径,而上面的流程经过一遍之后,你就会发现spring boot是不兼容这样修改的,也就是说,如果不可避免的要使用,那么一个tomcat,只能以配置缺省项目名的方式运行一个springboot程序,这其中意味着,你不止要将多个程序合成一个启动程序,还意味着你要花出心思来维护tomcat的配置文件,这对于后期的部署维护是一个很占精力的事情,但是在国内来讲普遍都是小项目,基本不会出现像类似阿里百度那种特别庞大的项目需求,所以普遍会以jar包的方式去打包spring boot程序。这种情况下,除了必要多和一的程序,总体上不同的模块又是如何融合在一个域名站点的呢?这个时候就要说到web开发中一个重要的软件,叫做nginx
,它提供了两大重要的能力,负载均衡和转发,我们日常使用的网站,去访问域名下的站点时,你的web请求本质上并不是直接访问到了它运行后台程序的服务器上,而是访问到了一台运行nginx的服务器上,由nginx将你的程序转发在不同的模块上,此时,这些模块会分布在不同服务器,不同端口中,但是由于nginx的转发使得在效果上,你访问的永远是域名下的同一站点。第二个原因
是综合性能,我们并不是在一起使用时,tomcat的限制而导致很少用它,是因为考虑到综合性能,第一点原因中说了,我们在正式工作中遇到的项目很少会有特别庞大的项目,也就是在一般情况下,一个项目关注点通常是部署简单、占用资源少、灵活性高,而这三点打包成jar包直接运行通常是最优解。部署简单是指将应用打包成Jar包后,只需通过命令行或脚本启动即可,无需额外配置和安装其他服务器软件。资源占用低是指相比于常规的Web服务器,在同一台机器上运行独立的Jar包可以减少系统资源占用,因为它不需要维护额外的服务器进程。灵活性高是指独立的Jar包易于移植和部署,可以在不同的环境中运行。那什么时候就要考虑使用tomcat呢?如果要开发一个并发请求相当高并且对性能要求也很高的网站,比如12306买票程序这种,这个时候你就要用tomcat这种外部的web软件,来解决部署问题了,由于独立的Jar包不会使用多线程监听请求,因此它在处理并发请求时会有一些限制,而常规的Web服务器会更好地处理请求。