前端vue+后端spring boot,第一次采用这种分离形式进行开发,最近项目要上线了,需要部署到服务器上,因为自己还是刚刚接触学习这种分离开发的模式,部署的时候遇到了很多问题,最近几天搞这个上线的事情被虐得心态差点崩溃,刚从一个坑里出来立马又被拖进另一个坑,深刻体会到——学海无涯苦作舟,特此记录小结一下,也算是小白踩坑的一个小小纪念吧。
下图展示了前端项目和后端项目的基本结构,接下来就是如何编译、打包、最终成功部署到服务器上去。
#-> 关于前后端分类项目的部署方式,一般有两种
(1)前后端一起部署,前端打包成静态文件,复制到后端项目中,然后部署后端项目
(2)前后端分离部署,前端使用nginx部署,后端直接运行jar
参考资料:
https://www.bilibili.com/video/BV1bJ41157W7
https://www.bilibili.com/video/BV1uK411p7Bp
本次部署采用的是第1种方式,前端打包成静态文件丢给后端一起打包部署
#1-> 前端打包成静态文件
npm run build
在项目根目录下会自动生成一个dist文件,把这个文件夹下的内容复制到后端项目的resources/static/文件夹下
直接运行@SpringBootApplication的函数主入口,由于在pom.xml文件中添加了security依赖,页面会自动跳转到如下登录界面
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
但是这里希望localhost打开访问的是index.html页面,在SecurityConfig.java里添加如下代码,禁止该功能即可
package com.example.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
http.csrf().disable();
}
}
#2-> 后端使用maven进行package打包
打包之前需要修改一下项目启动类WebApplication.java
- 改造前 -
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
- 改造后 -
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.WebApplicationInitializer;
@SpringBootApplication
public class WebApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder){
return applicationBuilder.sources(WebApplication.class);
}
}
打包可以直接点击maven窗口里Lifecycle里的package,也可以通过命令行执行 mvn package,需要注意的是每次最好先clean一下
pom.xml文件指定打包方式war,默认是jar
<packaging>war</packaging>
项目根目录下会生成一个target文件夹,圈出来的两个文件任意丢到服务器上发布都可以
#3-> 部署到weblogic服务器
由于本地是tomcat,本地测试都没有问题,第一次发布到weblogic就遇上2个bug
1. package生成的web-0.0.1-SNAPSHOT文件夹/web-0.0.1-SNAPSHOT.war weblogic都无法自动识别
查找了一些资料,weblogic部署spring boot项目时还需要额外配置weblogic.xml
手动新建一个weblogic.xml,然后放到webapp/WEB-INF/下
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app
xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd
http://xmlns.oracle.com/weblogic/weblogic-web-app
http://xmlns.oracle.com/weblogic/weblogic-web-app/1.4/weblogic-web-app.xsd">
<!--设置weblogic上的访问路径,默认是localhost:8080/-->
<wls:context-root>/hdzs</wls:context-root>
<wls:container-descriptor>
<wls:prefer-application-packages>
<wls:package-name>org.slf4j</wls:package-name>
</wls:prefer-application-packages>
</wls:container-descriptor>
</wls:weblogic-web-app>
需要注意下,如果这里指定了context-root,访问的时候就要加上这个地址,例如现在正确的访问地址是:http://xx.xx.xx.xx(服务器ip):8080/hdzs,同时前端页面访问的后端接口地址的baseURL也变成了http://xx.xx.xx.xx(服务器ip):8080/hdzs
2. 发布报错,无法访问所选应用程序
仔细查看报错原因,发现报错的是一个叫 [tomcat-embed-websocket-9.0.37.jar],本地开发是Tomcat服务器,服务器是weblogic,maven在package的时候自动把内嵌的tomact的jar包也放进来了,导致不兼容报错。
查看\iamb\target\web-0.0.1-SNAPSHOT\WEB-INF\lib
解决办法是在pom.xml里排除掉tomcat即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
现在重新mvn package发现lib文件夹下就没有tomcat的依赖包了,重新部署发布到weblogic成功
#4-> 测试发布
运行 http://xx.xx.xx.xx(服务器ip):8080/hdzs 报错,找不到静态资源文件,第一次碰到这个问题的时候很懵逼,因为本地测试是没有这个问题的,本地加载静态资源是正常的,发布到服务器就出问题了。
本地测试:http://localhost:8080/
发布测试:http://xx.xx.xx.xx(服务器ip):8080/hdzs
两者唯一的不同就是发布地址由于指定了context-root后多了一个hdzs,我尝试在原静态资源文件的请求地址加上了/hdzs,发现资源可以请求的到,如下图所示
解决的思路就很清晰了,修改静态资源的默认加载地址即可
回到前端项目,在项目根目录下新建一个vue.config.js,配置publicPath
module.exports = {
publicPath: './'
}
其他路径方式可参考:https://www.jb51.net/article/184694.htm
#5-> index.html显示中文乱码
用记事本打开index.html然后另存为UTF-8的格式即可解决
[写在最后]
折腾了好几天,总算是把前后端整合到一起,成功发布到weblogic上了,心累。每次遇到问题的时候,总是有些焦躁,想尽快找到一种最好的解决办法,但很多时间都浪费在各种纠结上面了,最简单最有效的办法其实就是大胆去尝试各种可能性,有些问题其实很多人之前肯定都遇到过,所以不用焦躁不用担心,总会解决的。网上的资料大多数也是copy来copy去,虽然有时候确实能解决问题,但是仅仅也只是停留在了解决了当前问题的层面,而为什么这么做可以解决这个问题却不是很明白,比如我还是不太懂为嘛要改造 spring boot的启动类才能发布,这可能就牵涉到spring boot底层的相关配置等问题,前方的路还很遥远哪,要继续往前走呀。前后端分离的项目部署有两种方式,这里只采用了第一种方式,还有一种分开部署的方式还有待研究,貌似这种使用上更方便一些,大概率要入nginx的坑了。
参考资料
http://www.10qianwan.com/articledetail/605070.html
https://www.cnblogs.com/luwenlong/p/9469746.html
-----20210223-----问题记录更新
javax.faces.facesexception:Unable to find CDI BeanManager
解决方式:pom.xml添加,同时删除web.xml文件
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>