Java牛客项目课_仿牛客网讨论区_第八章

SpringBoot项目报错解决:“Error starting ApplicationContext. To display the conditions report re-run ...” SpringBoot项目报错:以下方案80%可以帮助您解决这些个‘可恶的’问题报错内容和截图如下: ( ( )___ | '_ | '| | ’ / ` | / )| |)| | | | | || (| | ) ) ) ) ’ || .__|| ||| |, | / / / / =========||==============|/=///_/ :: Spring Boot :: (v2.3.10.RELEASE) ——在看到这些个问题的时候,日志基本都会告诉你错误的地方,所以我们大部分 阅读详情

第八章、项目发布与总结

8.1、 单元测试

Spring Boot Testing

  • 依赖:spring-boot-starter-test
  • 包括:Junit、Spring Test、AssertJ、…

Test Case - 要求:保证测试方法的独立性。

  • 步骤:初始化数据、执行测试代码、验证测试结果、清理测试数据。

  • 常用注解:@BeforeClass、@AfterClass、@Before、@After。

    @BeforeClass:注解的方法在该类加载前运行
    @AfterClass:注解的方法在该类销毁后运行
    @Before:注解的方法在该类中的任何测试方法执行前运行
    @After:注解的方法在该类中的任何测试方法执行后运行

后两个注解,方便我们在没有条件时,创造条件来进行测试。比如测试数据库的增删改查,那么每个方法测试前,先在用@Before注解的方法里新建一条数据库中的数据,运行完测试方法后,再在用@After注解的方法里销毁测试的数据。

执行测试类时,会依次执行测试类的所有测试方法。

于是,在一个测试类中写好测试数据库中某张表的增删改查的方法后,可以直接执行这个测试类,用断言Assert比较测试结果和预期结果是否一致,一致就程序执行成功,不一致就会抛出异常。于是,只要执行这个测试类,就可以把数据库这张表的所有业务service方法测试完成,如果没有报错,就说明数据库这张表的所有业务service方法都正确,如果有某个测试方法抛异常,就说明该测试方法测试的方法有错误。
在这里插入图片描述

package com.nowcoder.community;

import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.service.DiscussPostService;
import org.junit.*;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class SpringBootTests {

    @Autowired
    private DiscussPostService discussPostService;

    private DiscussPost data;

    //@BeforeClass和@AfterClass修饰的方法都必须用static修饰
    @BeforeClass
    public static void beforeClass() {
        System.out.println("beforeClass");
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("afterClass");
    }

    @Before
    public void before() {
        System.out.println("before");

        // 初始化测试数据
        data = new DiscussPost();
        data.setUserId(111);
        data.setTitle("Test Title");
        data.setContent("Test Content");
        data.setCreateTime(new Date());
        discussPostService.addDiscussPost(data);
    }

    @After
    public void after() {
        System.out.println("after");

        // 删除测试数据
        discussPostService.updateStatus(data.getId(), 2);
    }

    @Test
    public void test1() {
        System.out.println("test1");
    }

    @Test
    public void test2() {
        System.out.println("test2");
    }

    @Test
    public void testFindById() {
        DiscussPost post = discussPostService.findDiscussPostById(data.getId());
        Assert.assertNotNull(post);
        Assert.assertEquals(data.getTitle(), post.getTitle());
        Assert.assertEquals(data.getContent(), post.getContent());
    }

    @Test
    public void testUpdateScore() {
        int rows = discussPostService.updateScore(data.getId(), 2000.00);
        Assert.assertEquals(1, rows);

        DiscussPost post = discussPostService.findDiscussPostById(data.getId());
        Assert.assertEquals(2000.00, post.getScore(), 2);
    }

}

8.2、项目监控

Spring Boot Actuator

  • Endpoints:监控应用的入口,Spring Boot内置了很多端点,也支持自定义端点。
  • 监控方式:HTTP 或 JMX。
  • 访问路径:例如“/actuator/health”。
  • 注意事项:按需配置暴露的端点,并对所有端点进行权限控制。

访问:http://localhost:8080/community/actuator/端点名字(如health、info、loggers,也可以是自定义端点的名字,如database)
返回:JSON字符串。

例子:

访问路径用处
http://localhost:8080/community/actuator/health当前服务的健康状况。返回:{“status”:“DOWN”}
http://localhost:8080/community/actuator/info返回服务端的一些相关信息。如果没有,返回:{}
http://localhost:8080/community/actuator/beans返回应用中所有的bean。返回的内容太多,建议写个程序来分析,或者安装和actuator有关的工具来分析。
http://localhost:8080/community/actuator/loggers所有日志

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

application.propertise

# actuator
management.endpoints.web.exposure.include=*	# 暴露哪些端点,'*'代表全部。
management.endpoints.web.exposure.exclude=info,caches	# 排除哪些端点,就是哪些端点不暴露。

DatabaseEndpoint.java

package com.nowcoder.community.actuator;

import com.nowcoder.community.util.CommunityUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

//这个自定义端点用来监控数据库的连接是否正常
@Component
@Endpoint(id = "database")//自定义端点的id为database,好通过id访问它。即访问路径:http://localhost:8080/community/actuator/database。
public class DatabaseEndpoint {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseEndpoint.class);

    @Autowired
    private DataSource dataSource;

    @ReadOperation  //@ReadOperation表明这个方法只能通过get请求来访问。@WriteOperation注释的方法只能通过post/put请求来访问
    public String checkConnection() {
        try (
                Connection conn = dataSource.getConnection();
        ) {
            return CommunityUtil.getJSONString(0, "获取连接成功!");
            // 返回:{"msg":"获取连接成功!","code":0}
        } catch (SQLException e) {
            logger.error("获取连接失败:" + e.getMessage());
            return CommunityUtil.getJSONString(1, "获取连接失败!");
        }
    }
}

8.3、项目部署

在这里插入图片描述

正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端。
反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端。
一句话总结:正向代理隐藏真实客户端,反向代理隐藏真实服务端。

老师想的压缩包安装部分。
在这里插入图片描述

宝塔面板、yum、rpm、压缩包 安装 unzip、Java1.8、Maven、MySQL、Redis、Kafka、ElasticSearch和ik分词器、wkhtmltopdf、xvfb、Tomcat、Nginx。

yum安装unzip

# 安装unzip,用于解压zip包
[root@wu1 /]# yum list unzip*		# yum list xx*,该命令在根目录"/"下才有效果
[root@wu1 /]# yum install -y unzip.x86_64

rpm安装Java1.8(狂神说)

视频课:【狂神说Java】Linux最通俗易懂的教程阿里云真实环境学习_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
视频课中的环境变量有错,按下面这个环境变量。

[root@wu1 apache-maven-3.8.1]# vim /etc/profile		# 环境变量,在最后追加
JAVA_HOME=/usr/java/jdk1.8.0_281-amd64
CLASSPATH=%JAVA_HOME%/lib:%JAVA_HOME%/jre/lib
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin
export PATH CLASSPATH JAVA_HOME

[root@wu1 apache-maven-3.8.1]# source /etc/profile	# 让配置文件/etc/profile生效
[root@wu1 /]# java -version	# 狂神说的Java
java version "1.8.0_281"
Java(TM) SE Runtime Environment (build 1.8.0_281-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)

yum安装Java环境(牛客项目课)

# 安装Java环境。这个安装完,Java在云服务器上就装了两个,一个是狂神说的,一个是牛客网项目课的,就下面这个。
[root@wu1 /]# yum list java*
[root@wu1 /]# yum install -y java-latest-openjdk.x86_64

# 此时,我用命令`java -version`还是显示"1.8.0_281",我也只需要一个Java环境,就把牛客项目课的openJDK删掉了。就是云服务器上只有狂神说的1.8的Java环境。
[root@wu1 community]# rpm -qa|grep java	# 查询服务器中是否有openJDK
java-latest-openjdk-16.0.0.0.36-1.rolling.el7.x86_64
python-javapackages-3.4.1-11.el7.noarch
javapackages-tools-3.4.1-11.el7.noarch
tzdata-java-2021a-1.el7.noarch
java-latest-openjdk-headless-16.0.0.0.36-1.rolling.el7.x86_64
[root@wu1 community]# rpm -ev java-latest-openjdk-16.0.0.0.36-1.rolling.el7.x86_64	# 删除openJDK
Preparing packages...
java-latest-openjdk-1:16.0.0.0.36-1.rolling.el7.x86_64
[root@wu1 community]# rpm -ev java-latest-openjdk-headless-16.0.0.0.36-1.rolling.el7.x86_64
Preparing packages...
java-latest-openjdk-headless-1:16.0.0.0.36-1.rolling.el7.x86_64

压缩包安装Maven

# 安装Maven
[root@wu1 ~]# ll
total 9356
-rw-r--r-- 1 root root 9536838 Apr 28 16:57 apache-maven-3.8.1-bin.tar.gz
-rw-r--r-- 1 root root      92 Apr 11 20:48 dump.rdb
-rw-r--r-- 1 root root      12 Apr 16 17:19 hi.html
-rw-r--r-- 1 root root   25386 Jan  9 12:00 install.sh
-rw-r--r-- 1 root root    2740 Aug 23  2020 update.sh
[root@wu1 ~]# tar -zxvf apache-maven-3.8.1-bin.tar.gz -C /opt
[root@wu1 ~]# cd /opt
[root@wu1 opt]# cd apache-maven-3.8.1/
[root@wu1 apache-maven-3.8.1]# pwd
/opt/apache-maven-3.8.1
[root@wu1 apache-maven-3.8.1]# vim /etc/profile		# 在最后追加一行
export PATH=$PATH:/opt/apache-maven-3.8.1/bin

[root@wu1 apache-maven-3.8.1]# source /etc/profile	# 让配置文件/etc/profile生效
[root@wu1 apache-maven-3.8.1]# echo $PATH		# 打印出环境变量看一下
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/java/jdk1.8.0_281-amd64/bin:/usr/java/jdk1.8.0_281-amd64/jre/bin:/usr/java/jdk1.8.0_281-amd64/bin:/usr/java/jdk1.8.0_281-amd64/jre/bin:/root/bin:/usr/java/jdk1.8.0_281-amd64/bin:/usr/java/jdk1.8.0_281-amd64/jre/bin:/opt/apache-maven-3.8.1:/usr/java/jdk1.8.0_281-amd64/bin:/usr/java/jdk1.8.0_281-amd64/jre/bin:/opt/apache-maven-3.8.1/bin
[root@wu1 apache-maven-3.8.1]# mvn -version	# 安装好maven了
Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)
Maven home: /opt/apache-maven-3.8.1
Java version: 1.8.0_281, vendor: Oracle Corporation, runtime: /usr/java/jdk1.8.0_281-amd64/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-1062.18.1.el7.x86_64", arch: "amd64", family: "unix"

# 配置Maven
[root@wu1 conf]# vim /opt/apache-maven-3.8.1/conf/settings.xml	# 下方复制到两个mirrors里

        <mirror>
   			 <id>alimaven</id>
  			  <name>aliyun maven</name>
    		  <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    		  <mirrorOf>central</mirrorOf>
        </mirror>

在这里插入图片描述

宝塔面板安装MySQL
MySQL :: Download MySQL Yum Repository
在这里插入图片描述

宝塔linux面板命令大全 - 宝塔面板

# 安装mysql
[root@wu1 ~]# yum install -y mysql80-community-release-el8-1.noarch.rpm
[root@wu1 ~]# cd /
[root@wu1 /]# yum list mysql*
[root@wu1 /]# yum install -y mysql-community-server.x86_64
或者
宝塔面板一键安装。我用的宝塔面板安装的mysql8

[root@wu1 /]# systemctl start mysqld
[root@wu1 /]# systemctl status mysqld
[root@wu1 ~]# cd /www/server/panel && python tools.py root a1b2c3	# 强制修改MySQL管理(root)密码,如要改成a1b2c3	
[root@wu1 panel]# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.23 Source distribution
。。。
mysql> create database community;
mysql> use community
mysql> source /root/init_sql/init_schema.sql
mysql> source /root/init_sql/init_data.sql
mysql> source /root/init_sql/tables_mysql_innodb.sql
mysql> show tables;
mysql> select id,username,header_url from user;
mysql> update user set header_url ='http://images.nowcoder.com/head/666t.png' where header_url like '%localhost%';
mysql> exit
Bye

yum安装Redis

# 安装redis。安装完这个redis,我电脑上总共安装了两个redis,一个是狂神说的redis,一个是按以下方法安装的redis。可以启动这个关闭那个,两个Redis里的数据是不一样的。
[root@wu1 panel]# cd /
[root@wu1 /]# yum list redis*
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * centos-sclo-rh: mirrors.aliyun.com
Available Packages
redis.x86_64                                            3.2.12-2.el7                                       epel
redis-trib.noarch                                       3.2.12-2.el7                                       epel
[root@wu1 /]# yum install -y redis.x86_64
[root@wu1 bin]# systemctl start redis
[root@wu1 bin]# systemctl status redis
[root@wu1 bin]# redis-cli
127.0.0.1:6379> exit

压缩包安装Kafka

# 安装Kafka
[root@wu1 ~]# tar -zvxf kafka_2.13-2.7.0.tgz -C /opt
[root@wu1 ~]# /opt/kafka_2.13-2.7.0/bin/zookeeper-server-start.sh -daemon /opt/kafka_2.13-2.7.0/config/zookeeper.properties 	# 后台启动zookeeper
[root@wu1 ~]# nohup /opt/kafka_2.13-2.7.0/bin/kafka-server-start.sh /opt/kafka_2.13-2.7.0/config/server.properties 1>/dev/null 2>&1 &	# 后台启动Kafka
[1] 4408
[root@wu1 ~]# /opt/kafka_2.13-2.7.0/bin/kafka-topics.sh --list --bootstrap-server localhost:9092	# 没报错就说明启动成功

压缩包安装ElasticSearch和ik分词器

# 安装elasticsearch和ik分词器
[root@wu1 ~]# tar -zvxf /root/elasticsearch-7.12.0-linux-x86_64.tar.gz -C /opt
[root@wu1 ~]# unzip -d /opt/elasticsearch-7.12.0/plugins/ik /root/elasticsearch-analysis-ik-7.12.0.zip 	
[root@wu1 ~]# vim /opt/elasticsearch-7.12.0/config/elasticsearch.yml 	# 取消下方内容的注释,修改以下内容
cluster.name: nowcoder
path.data: /tmp/elastic/data
path.logs: /tmp/elastic/logs

[root@wu1 ~]# vim /opt/elasticsearch-7.12.0/config/jvm.options	# 取消下方内容的注释,修改以下内容,这两个参数要顶格写。
-Xms256m
-Xmx512m

[root@wu1 ~]# groupadd nowcoder
[root@wu1 ~]# useradd nowcoder1 -p 123456 -g nowcoder
[root@wu1 ~]# cd /opt
[root@wu1 opt]# chown -R nowcoder1:nowcoder *
[root@wu1 opt]# cd /tmp
[root@wu1 tmp]# chown -R nowcoder1:nowcoder *
[root@wu1 tmp]# su - nowcoder1
[nowcoder1@wu1 ~]$ /opt/elasticsearch-7.12.0/bin/elasticsearch -d	# 后台启动es
[nowcoder1@wu1 ~]$ su -
Password: 
[root@wu1 ~]# curl -X GET "localhost:9200/_cat/health?v"	# 测试es是否成功启动
epoch      timestamp cluster  status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1619627359 16:29:19  nowcoder green           1         1      0   0    0    0        0             0                  -                100.0%

yum安装wkhtmltopdf

# yum安装wkhtmltopdf
[root@wu1 ~]# cd /
[root@wu1 /]# yum list wkhtmltopdf*
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * centos-sclo-rh: mirrors.aliyun.com
Available Packages
wkhtmltopdf.x86_64                                                0.12.4-1.el7                   
wkhtmltopdf-devel.x86_64                                          0.12.4-1.el7                   
[root@wu1 /]# yum install -y wkhtmltopdf.x86_64

yum安装xvfb,让Linux可视化。因为wkhtmltopdf会生成图片,图片是可视化的。

# yum安装xvfb,让Linux可视化。因为wkhtmltopdf会生成图片,图片是可视化的。
[root@wu1 /]# yum list *xvfb*
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * centos-sclo-rh: mirrors.aliyun.com
Available Packages
python-xvfbwrapper.noarch                         0.2.4-2.el7                            epel   
xorg-x11-server-Xvfb.x86_64                       1.20.4-15.el7_9                        updates
[root@wu1 /]# yum install -y xorg-x11-server-Xvfb.x86_64

测试用wkhtmltopdf生成图片

# 测试用wkhtmltopdf生成图片
[root@wu1 /]# cd /root/test
[root@wu1 test]# ll
total 0
[root@wu1 test]# xvfb-run --server-args="-screen 0, 1024x768x24" wkhtmltoimage https://www.baidu.com 1.png
Loading page (1/2)
Rendering (2/2)                                                    
Warning: Received createRequest signal on a disposed ResourceObject's NetworkAccessManager. This might be an indication of an iframe taking too long to load.
Done                                                               
[root@wu1 test]# ll
total 2952
-rw-r--r-- 1 root root 3019976 Apr 29 00:37 1.png
[root@wu1 test]# cd /opt
[root@wu1 opt]# vim wkhtmltoimage.sh		# /opt/wkhtmltoimage.sh文件里只有这一句话
xvfb-run --server-args="-screen 0, 1024x768x24" wkhtmltoimage "$@"
[root@wu1 opt]# ll
total 2412
drwxr-xr-x 6 nowcoder1 nowcoder    4096 Apr 28 17:01 apache-maven-3.8.1
drwx--x--x 4 nowcoder1 nowcoder    4096 Mar 19 11:15 containerd
drwxr-xr-x 9 nowcoder1 nowcoder    4096 Mar 18 14:21 elasticsearch-7.12.0
drwxr-xr-x 7 nowcoder1 nowcoder    4096 Apr 28 23:12 kafka_2.13-2.7.0
drwxrwxr-x 7 nowcoder1 nowcoder    4096 Mar  2 14:14 redis-6.2.1
-rw-r--r-- 1 nowcoder1 nowcoder 2438367 Mar 25 10:35 redis-6.2.1.tar.gz
drwxr-xr-x 3 nowcoder1 nowcoder    4096 Mar 13 11:11 rh
-rw-r--r-- 1 root      root          67 Apr 29 00:39 wkhtmltoimage.sh
[root@wu1 opt]# chmod +x wkhtmltoimage.sh 
[root@wu1 opt]# cd /root/test
[root@wu1 test]# /opt/wkhtmltoimage.sh https://www.baidu.com 2.png
Loading page (1/2)
Rendering (2/2)                                                    
Warning: Received createRequest signal on a disposed ResourceObject's NetworkAccessManager. This might be an indication of an iframe taking too long to load.
Done                                                               
[root@wu1 test]# ll
total 5904
-rw-r--r-- 1 root root 3019976 Apr 29 00:37 1.png
-rw-r--r-- 1 root root 3019976 Apr 29 00:40 2.png
[root@wu1 test]# 

宝塔面板安装Tomcat

# 宝塔面板安装tomcat
[root@wu1 test]# vim /etc/profile	# 最下方写一句这个
export PATH=$PATH:/www/server/tomcat/bin
[root@wu1 test]# source /etc/profile
[root@wu1 test]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/java/jdk1.8.0_281-amd64/bin:/usr/java/jdk1.8.0_281-amd64/jre/bin:/opt/apache-maven-3.8.1/bin:/www/server/tomcat/bin:/usr/java/jdk1.8.0_281-amd64/bin:/usr/java/jdk1.8.0_281-amd64/jre/bin:/opt/apache-maven-3.8.1/bin:/www/server/tomcat/bin:/root/bin:/usr/java/jdk1.8.0_281-amd64/bin:/usr/java/jdk1.8.0_281-amd64/jre/bin:/opt/apache-maven-3.8.1/bin:/www/server/tomcat/bin

压缩包安装Nginx

# 压缩包安装nginx(下方为yum安装nginx失败)
[root@wu1 ~]# cd /
[root@wu1 /]# yum list nginx*
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * centos-sclo-rh: mirrors.aliyun.com
Available Packages
nginx-all-modules.noarch                     1:1.16.1-3.el7            epel
nginx-filesystem.noarch                      1:1.16.1-3.el7            epel
nginx-mod-http-image-filter.x86_64           1:1.16.1-3.el7            epel
nginx-mod-http-perl.x86_64                   1:1.16.1-3.el7            epel
nginx-mod-http-xslt-filter.x86_64            1:1.16.1-3.el7            epel
nginx-mod-mail.x86_64                        1:1.16.1-3.el7            epel
nginx-mod-stream.x86_64                      1:1.16.1-3.el7            epel
[root@wu1 /]# yum install -y nginx.x86_64
。。。
No package nginx.x86_64 available.
Error: Nothing to do

# 压缩包安装nginx后
[root@wu1 ~]# vim /usr/local/nginx/conf/nginx.conf	# http的大括号里,去掉原先的server,加上下面这个
# http是80端口,https是443端口。默认是80端口,于是访问120.77.151.233会变为120.77.151.233:80,然后被服务器中的nginx映射到120.77.151.233:8080。
	upstream myserver{
		server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
	}
	server{
		listen 80;
		server_name 120.77.151.233;
		location / {
			proxy_pass http://myserver;
		}
	}

[root@wu1 ~]# /usr/local/nginx/sbin/nginx
nginx: [emerg] "upstream" directive is not allowed here in /usr/local/nginx/conf/nginx.conf:88
[root@wu1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@wu1 ~]# /usr/local/nginx/sbin/nginx
nginx: [emerg] "server" directive is not allowed here in /usr/local/nginx/conf/nginx.conf:93
[root@wu1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@wu1 ~]# /usr/local/nginx/sbin/nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
[root@wu1 ~]# killall -9 nginx
[root@wu1 ~]# /usr/local/nginx/sbin/nginx	# 没输出东西,nginx/logs目录下的error.log文件输出worker process 6610 exited on signal 11 ngx_http_fastdfs_process_init pid=6614,需要打开fastdfs的tracker
[root@wu1 ~]# fdfs_trackerd /etc/fdfs/tracker.conf start
[root@wu1 ~]# killall -9 nginx
[root@wu1 ~]# /usr/local/nginx/sbin/nginx	
如何访问到我们的项目:浏览器->Nginx->Tomcat。如何一个Tomcat部署多个项目。

在这里插入图片描述
如果访问1.1.1.1,会访问1.1.1.1:80,然后被服务器中的nginx映射到1.1.1.1:8080,即访问tomcat中的ROOT项目的首页。如果想访问tomcat下的其他项目,需要用1.1.1.1/community这种形式来访问,如果1.1.1.1有域名nowcoder.com,那么需要用nowcoder.com/community来访问我们自己的项目。

补充知识点:一个tomcat部署多个项目
~~
【狂神说Java】JavaWeb入门到实战_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili。这个视频课是关于tomcat的,讲了,直接把软件放在tomcat的webapp目录下,他默认是localhost:8080/会访问到webapp/ROOT项目;而localhost:8080/hello会访问到webapp/hello项目;而localhost:8080/hello2会访问到webapp/hello2项目。
~~
1.1.1.1默认为1.1.1.1:80,nginx把其映射到1.1.1.1:8080,然后我们可以在tomcat的webapp目录下部署两个war包,一个是ROOT,一个是scau-community。然后一启动tomcat,就会把这两个war包打开为两个文件夹,然后,可以用1.1.1.1访问ROOT,可以用1.1.1.1/scau-community访问scau-community
~~
1.1.1.1是假设的IP,改成你的服务器的IP。

在这里插入图片描述
通过删掉ROOT,然后把我们自己的项目打包成ROOT.war来解决,到时候访问1.1.1.1,会访问到我们自己的项目。

把能在Windows上运行的项目改为能在Linux服务器上运行。然后把项目丢到服务器上,用服务器上的Maven编译打包,再把ROOT.war丢到Tomcat的wabapp目录下,启动Tomcat。

接下来,1、去掉/community,2、访问"/“时要访问”/index"。

[root@wu1 ~]# shutdown.sh	# 关掉tomcat
Using CATALINA_BASE:   /www/server/tomcat
Using CATALINA_HOME:   /www/server/tomcat
Using CATALINA_TMPDIR: /www/server/tomcat/temp
Using JRE_HOME:        /usr/java/jdk1.8.0_281-amd64
Using CLASSPATH:       /www/server/tomcat/bin/bootstrap.jar:/www/server/tomcat/bin/tomcat-juli.jar

# 可以修改/www/server/tomcat/webapps/ROOT文件夹为ROOT_bak文件夹。
# 但建议直接删除原先的webapp目录下的所有文件。

IDEA项目8.3修改
1、去掉/community

# application.properties
server.servlet.context-path=

# global.js
var CONTEXT_PATH = "";

2、访问"/“时要访问”/index"

# HomeController.java加一个方法
    @RequestMapping(path = "/", method = RequestMethod.GET)
    public String root() {
        return "forward:/index";
    }

3、默认会打成jar包,要使得打包时打成war包

# pom.xml增加<packaging>和<finalName>两行
	<name>community</name>
	<description>nowcoder community</description>
	<packaging>war</packaging>

	<build>
		<finalName>ROOT</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

4、Windows上日志文件的存放地址和Linux服务器上的日志文件存放地址不一样,其他的一些路径也都不一样。又不方便测试时xx路径,上线时改为yy路径。于是SpringBoot允许一个项目有多套配置文件,开发时一套,上线时一套,也可以有其他的。然后通过一个开关,决定用哪套配置文件。
这里搞两套配置文件,开发一套,生产(上线)一套。

application.properties
application-develop.properties
application-produce.properties
logback-spring.xml
logback-spring-develop.xml
logback-spring-produce.xml

开关为application.properties,修改时只需要spring.profiles.active=produce/develop,即可。

# profile
spring.profiles.active=produce

# logback
logging.config=classpath:logback-spring-${spring.profiles.active}.xml

5、因为tomcat本身就有启动方法,而我们的项目也有启动的方法,于是需要一个两者间的桥梁,就是下面这个。继承一个类,用来实现该类的父接口的configure方法。
加一个类,CommunityServletInitializer.java

package com.nowcoder.community;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class CommunityServletInitializer extends SpringBootServletInitializer {

    //tomcat访问该方法作为入口来运行该项目
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(CommunityApplication.class); //这里指出该项目的main方法所在的类
    }
}

6、application-develop.properties和application-produce.properties相比,后者修改的地方。

# ServerProperties
server.servlet.context-path=

# ThymeleafProperties
spring.thymeleaf.cache=true

# DataSourceProperties	# 因为访问的是你自己电脑上的mysql->服务器的mysql,可能两个mysql你设置的用户名密码不一致。
spring.datasource.username=root
spring.datasource.password=a1b2c3

# community
community.path.domain=http://120.77.151.233		# 你的要部署的服务器的IP地址
community.path.upload=/tmp/uploads

# wk
wk.image.command=/opt/wkhtmltoimage.sh
wk.image.storage=/tmp/wk-images

7、logback-spring-produce.xml相对于logback-spring-develop.xml修改的地方

    <contextName>community</contextName>
    <property name="LOG_PATH" value="/tmp"/> <!--只改了这里"/tmp"-->
    <property name="APPDIR" value="community"/>

8、删除生成的target文件
在这里插入图片描述
删除target文件遇到的问题和解决方法:IDEA 踩坑之:maven 打包提示 [ERROR] The specified user settings file does not exist…_小白一个-优快云博客

9、把项目丢到服务器上,用服务器上的Maven编译打包,再把ROOT.war丢到Tomcat的wabapp目录下,启动Tomcat。

把项目打包为zip压缩包,然后上传到服务器的root目录下。

[root@wu1 ~]# unzip -d /root community.zip	# -d后面跟放到哪个目录下。
[root@wu1 ~]# cd community
[root@wu1 community]# mvn clean package -Dmaven.test.skip=true	# 用maven把项目编译并且打包,跳过测试,因为我们前面的测试类写的都不标准,最后单独讲的那个测试才是标准的测试。耗时较长。
[root@wu1 community]# cd target	# 来到/root/community/target目录
[root@wu1 target]# ll	# 看到ROOT.war文件
[root@wu1 target]# mv ROOT.war /www/server/tomcat/webapps/
[root@wu1 target]# startup.sh		# 启动tomcat。虽然立刻返回了信息,但实际上过了一会才启动
Using CATALINA_BASE:   /www/server/tomcat
Using CATALINA_HOME:   /www/server/tomcat
Using CATALINA_TMPDIR: /www/server/tomcat/temp
Using JRE_HOME:        /usr/java/jdk1.8.0_281-amd64
Using CLASSPATH:       /www/server/tomcat/bin/bootstrap.jar:/www/server/tomcat/bin/tomcat-juli.jar
Tomcat started.
[root@wu1 target]# vim /www/server/tomcat/logs/catalina.2021-05-16.log	# 查看tomcat的日志,是否启动成功。

tomcat启动日志/www/server/tomcat/logs/catalina.2021-05-16.log启动成功时提示:

。。。
18-May-2021 23:50:42.348 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 575 ms
18-May-2021 23:50:42.382 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service Catalina
18-May-2021 23:50:42.383 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/9.0.0.M18
18-May-2021 23:50:42.402 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive /www/server/tomcat/webapps/ROOT.war
18-May-2021 23:50:47.297 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
18-May-2021 23:50:58.085 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive /www/server/tomcat/webapps/ROOT.war has finished in 15,682 ms
18-May-2021 23:50:58.100 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [http-nio-8080]
18-May-2021 23:50:58.138 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [ajp-nio-8009]
18-May-2021 23:50:58.154 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 15806 ms

部署到服务器上以后,我们就没有办法用工具来调试了,一切都要看日志,所以要习惯于看日志。

为了部署到服务器,我在视频课项目外额外加的代码。

1、项目的启动初始化代码,使得服务器上的项目启动时,从数据库取到所有帖子数据,同步到ElasticSearch中。

加这段代码时,遇到的错:
ElasticSearch创建索引报错:ElasticsearchStatusException [type=resource_already_exists_exception, reason=index already exists]_夜中听雪的博客-优快云博客

package com.nowcoder.community.config;

import com.nowcoder.community.dao.DiscussPostMapper;
import com.nowcoder.community.dao.elasticsearch.DiscussPostRepository;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;

@Configuration
public class EsConfig {
    @Value("${elasticSearch.url}")
    private String esUrl;

    @Value("${elasticsearch.indices}")
    String esIndices;

    @Autowired
    private DiscussPostMapper discussMapper;

    @Autowired
    private DiscussPostRepository discussRepository;

    @Qualifier("client")
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    //localhost:9200 写在配置文件中就可以了
    @Bean
    RestHighLevelClient client() {
        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(esUrl)//elasticsearch地址
                .build();

        return RestClients.create(clientConfiguration).rest();
    }

    @PostConstruct
    public void init() throws Exception {
        client();

        //建立表
        if(!existsIndex(esIndices)){
            //createIndex(esIndices);
        }else{
            deleteIndex(esIndices);
        }

        //把所有帖子(List<DiscussPost>)存入es的discusspost索引(es的索引相当于数据库的表)
        //这个插入顺序是按"最新/热门"来插入都无所谓,因为搜索的时候,会在那里按照"热门"来搜索数据。
        discussRepository.saveAll(discussMapper.selectAllDiscussPosts());
    }

    @PreDestroy
    public void destroy() throws IOException {
        //删除表中数据,销毁表
        deleteIndex(esIndices);
    }
    ////////////////////////////////

    //判断索引是否存在
    public boolean existsIndex(String index) throws IOException {
        GetIndexRequest request = new GetIndexRequest(index);
        boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        return exists;
    }

    //创建索引
    public boolean createIndex(String index) throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(index);
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
        return createIndexResponse.isAcknowledged();
    }

    //删除索引
    public boolean deleteIndex(String index) throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);
        AcknowledgedResponse response = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }
}

2、在pom.xml文件中添加

		 <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
         </plugin>
遇到的错误和解决:
1、Maven编译打包项目报错:Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources

用命令mvn clean package -Dmaven.test.skip=true通过服务器上的maven把项目编译打包时报错:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources) on project community: Input length = 1 -> [Help 1]
解决:maven打包错误: Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources_夜中听雪的博客-优快云博客
即:在pom.xml文件中添加

		 <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
         </plugin>
2、Tomcat启动时的启动日志中的报错:Caused by: java.net.BindException: Address already in use

启动时tomcat的/www/server/tomcat/logs/catalina.2021-05-16.log产生很多日志,可能有多个SEVERE,从最下面的一条SEVERE开始解决,一条条往上解决。
即一直向下翻找到最后一个Caused by,解决了这个Caused by,再去解决上一个Caused by。为什么要找最后一个Caused by:,打个比方:拆线的时候,找到线头才好拆。
下方列出最下方的SEVERE先解决它:

16-May-2021 23:56:01.330 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[AJP/1.3-8009]]
 org.apache.catalina.LifecycleException: Protocol handler initialization failed
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:942)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
	at org.apache.catalina.core.StandardService.initInternal(StandardService.java:530)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
	at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:875)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:606)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:629)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:311)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:494)
Caused by: java.net.BindException: Address already in use
	at sun.nio.ch.Net.bind0(Native Method)
	at sun.nio.ch.Net.bind(Net.java:444)
	at sun.nio.ch.Net.bind(Net.java:436)
	at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:225)
	at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
	at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:206)
	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:952)
	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:550)
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:939)
	... 13 more

知识点:
netstat和lsof看端口的区别_lu123535884的专栏-优快云博客
每天一个linux命令(51):lsof命令 - peida - 博客园
每天一个linux命令(56):netstat命令 - peida - 博客园

[root@wu1 ~]# netstat -anonetstat -ano	# 查看端口使用情况
[root@wu1 ~]# netstat -ano|grep 8080	# 查看8080端口号是否已经被占用,如果结果为空则说明没有被使用,如果有值则说明已经被使用
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      off (0.00/0/0)
[root@wu1 ~]# lsof -i tcp:8080 
COMMAND  PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
jsvc    7922  www   50u  IPv4 5287264      0t0  TCP *:webcache (LISTEN)
[root@wu1 ~]# shutdown.sh
[root@wu1 ~]# kill 7922
[root@wu1 ~]# startup.sh
[root@wu1 ~]# lsof -i tcp:8080 
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
java    20064 root   51u  IPv4 57463225      0t0  TCP *:webcache (LISTEN)

然后退出,然后删除了/www/server/tomcat/webapps目录下除了ROOT.war以外的其他文件。

此时tomcat产生的日志:

# 退出:shutdown.sh

17-May-2021 09:16:06.752 INFO [main] org.apache.catalina.core.StandardServer.await A valid shutdown command was received via the shutdown port. Stopping the Server instance.
17-May-2021 09:16:06.752 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["http-nio-8080"]
17-May-2021 09:16:06.803 INFO [main] org.apache.coyote.AbstractProtocol.pause Pausing ProtocolHandler ["ajp-nio-8009"]
17-May-2021 09:16:06.854 INFO [main] org.apache.catalina.core.StandardService.stopInternal Stopping service Catalina
17-May-2021 09:16:07.067 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [mysql-cj-abandoned-connection-cleanup] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
 com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:85)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)
17-May-2021 09:16:07.083 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8080"]
17-May-2021 09:16:07.085 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8009"]
17-May-2021 09:16:07.087 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8080"]
17-May-2021 09:16:07.087 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8009"]
17-May-2021 09:16:08.014 INFO [mysql-cj-abandoned-connection-cleanup] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load []. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
 java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load []. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
	at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1295)
	at org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:976)
	at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.checkThreadContextClassLoader(AbandonedConnectionCleanupThread.java:117)
	at com.mysql.cj.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:84)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

# 启动:startup.sh

17-May-2021 09:19:32.309 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:        Apache Tomcat/9.0.0.M18
17-May-2021 09:19:32.336 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Mar 8 2017 15:20:57 UTC
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number:         9.0.0.0
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Linux
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            3.10.0-1062.18.1.el7.x86_64
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          amd64
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /usr/java/jdk1.8.0_281-amd64/jre
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           1.8.0_281-b09
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         /www/server/tomcat
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         /www/server/tomcat
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/www/server/tomcat/conf/logging.properties
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
17-May-2021 09:19:32.337 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
17-May-2021 09:19:32.338 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
17-May-2021 09:19:32.338 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/www/server/tomcat
17-May-2021 09:19:32.339 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/www/server/tomcat
17-May-2021 09:19:32.339 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/www/server/tomcat/temp
17-May-2021 09:19:32.339 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
17-May-2021 09:19:32.534 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
17-May-2021 09:19:32.558 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
17-May-2021 09:19:32.560 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"]
17-May-2021 09:19:32.561 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
17-May-2021 09:19:32.562 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 728 ms
17-May-2021 09:19:32.582 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service Catalina
17-May-2021 09:19:32.582 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/9.0.0.M18
17-May-2021 09:19:32.610 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive /www/server/tomcat/webapps/ROOT.war
17-May-2021 09:19:37.690 INFO [main] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
17-May-2021 09:19:50.891 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive /www/server/tomcat/webapps/ROOT.war has finished in 18,277 ms
17-May-2021 09:19:50.895 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [http-nio-8080]
17-May-2021 09:19:50.978 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler [ajp-nio-8009]
17-May-2021 09:19:50.983 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 18420 ms

# 启动后

可以从上面的日志看出Caused by: java.net.BindException: Address already in use没有了。

3、/tmp/community/log_error.log日志中关于Kafka的报错:Exception thrown when sending a message with key=‘null’

此时项目是可以通过ip地址访问到的,发现点赞时需要通过刷新才能看到点赞成功,说明redis没有问题,但是Kafka有问题。
此时,/tmp/community下,原先的错误日志太多,分不出是哪个错误。
于是可以:
方案1、删除所有/tmp/community下的日志,然后关闭tomcat再启动tomcat(因为删除日志后,不重新启动tomcat,那么无论你在ip地址访问到的项目上做什么,都不会有日志/tmp/community。),再次测试点赞,查看/tmp/community/log_error.log日志。
或者
方案2:关闭tomcat再启动tomcat,然后在/tmp/community/log_error.log下的原先的错误日志下做分割线,然后再次测试点赞,在宝塔面板的文本编辑器里刷新/tmp/community/log_error.log日志。
下方是点赞后,/tmp/community/log_error.log日志里的报错:

2021-05-17 12:16:52,666 ERROR [http-nio-8080-exec-2] o.s.k.s.LoggingProducerListener [LogAccessor.java:261] Exception thrown when sending a message with key='null' and payload='{"data":{"postId":277},"entityId":277,"entityType":1,"entityUserId":149,"topic":"like","userId":111}' to topic like:
org.apache.kafka.common.errors.TimeoutException: Topic like not present in metadata after 60000 ms.
2021-05-17 12:16:52,669 ERROR [http-nio-8080-exec-2] c.n.c.c.a.ExceptionAdvice 

解决:服务器上Kafka启动报错:error=‘Cannot allocate memory‘ (errno=12)_夜中听雪的博客-优快云博客

4、服务器上的MySQL启动失败:Starting MySQL…The server quit without updating PID file

服务器上的MySQL启动失败:Starting MySQL…The server quit without updating PID file_夜中听雪的博客-优快云博客

5、重启Linux服务器上的elasticsearch时,需要做的步骤

重启Linux服务器上的elasticsearch时,需要做的步骤_夜中听雪的博客-优快云博客

nginx报错:worker process 6610 exited on signal 11 ngx_http_fastdfs_process_init pid=6614

worker process 3135 exited on signal 11 ngx_http_fastdfs_process_init pid=3137,nginx无法访问一直加载_A_XJF01的博客-优快云博客

8.4、项目总结

在这里插入图片描述

图中的下方三行是基石。
原图中带下划线的和带@的内容是重点内容。

算法:前缀树过滤敏感词。
数据结构:Redis的数据结构。Redis有许多种数据结构,每种数据结构适合解决什么样的问题,适合缓存什么样的数据。
Kafka:重点是生产者与消费者模式,只有你理解了,才能明白什么时候用哪些功能来解决什么问题。
ElasticSearch:重点是它的数据结构,以索引(表)方式来存。建议找文章自己学习ES的索引。
Caffeine:本地缓存,有一定局限性,把它和Redis一起回顾,因为它们都是缓存。


从运维角度来讲整个项目(就是分布式部署)

在这里插入图片描述

静态资源(图片)和动态资源(controller)是部署在两个服务器上的。比如:牛客网的是在域名nowcoder.com上,牛客网的图片是在static.nowcoder.com上,这两个是不同的域名,会对应到两个不同的服务器。

客户端找nginx请求动态资源,找CDN请求静态资源。

  • nginx:能对服务器做反向代理,如果你有多个服务器,它能对服务器做负载均衡。nginx会主从备份,即有两台服务器,一台处理客户端请求,一台只是备份。
  • CDN:把你的资源部署到各地的多个服务器上,用户访问网站时,会从最近的服务器加载资源。

有多台服务器,nginx会把客户端请求发送到某一台服务器,每台服务器中都有项目community和本地缓存。

数据库通常要做读写分离的,一台数据库复制读,一台数据库负责写。负责写的数据库在写入数据以后,会把数据同步到负责读取的数据库里。

为什么Redis、Kafka、ElasticSearch都是部署多个,但是数据库却只进行主从备份?因为数据库部署和它们一样做集群式部署的话的话,那么就要处理分布式事务,这个比较麻烦,所以我们一般尽量避免这种情况。而且,一般的业务也达不到要部署多个数据库,因为在访问数据库前,会先访问本地缓存,再访问Redis,最后都没有才访问数据库。

我们用的文件服务器是七牛云。


面试官关注的点:性能、可靠性、安全。

老师:面试官面试你看什么?
1、职业素养,看基本功。看数据结构、算法、基础。看你大学学没学。
2、项目经验。你的技术栈全不全,进来了能不能直接工作。你能直接工作就不需要找人带你,找人带你,你会拖带你的那人的后腿,带你的人工作效率就低了。
3、有多个入围者,他会看你长板,而不是短板。看你最擅长的领域是什么水平,看你的钻研能力、独立解决问题的能力。所以面试官会让你说你哪里熟,他就问你哪里,挖到你的底。建议的几个深入研究方面,任选一个:Redis、数据库读写分离、Nginx、Spring源码、Spring Security、本地缓存、Tomcat。

8.5、常见面试题

悲观锁:不允许出问题。
乐观锁:出问题了我再去解决。
更新数据很频繁,用悲观锁。
更新数据不频繁,查询数据多,用乐观锁。


数据库中,事务是为了保证安全,索引是为了提高效率。


在这里插入图片描述
Interceptor拦截器的三个方法:preHandle()、postHandle()、afterCompletion()。

客户端发出请求。

  • DispatcherServlet:核心。客户端发出的请求由它来处理,它调用一系列组件来解决该请求。
  • HandlerMapping:根据客户端访问路径找到其对应的Controller。
  • HandlerExecutionChain:封装了:1、解决该请求的Controller,2、对该请求实现拦截的拦截器。它把这两样交给了DispatcherServlet。
  • HandlerAdapter:从DispatcherServlet得到Controller并调用。
  • ModelAndView:由Controller返回ModelAndView给DispatcherServlet。
  • ViewResolver:从DispatcherServlet得到ModelAndView,ViewResolver会找到模板引擎,把数据给模板,就是View。
    View:也叫模板引擎,它向客户端做渲染和展现。
SpringBoot实战(十三)集成Actuator 阅读详情

相关推荐

java-问题汇总

开发遇到的问题

xiaopang2020的博客 700

Hadoop 2.6.5 Windows平台下的bug NativeIO$Windows.access0(Ljava/lang/String;I)Z

HTTP Status 500 - Handler processing failed; nested exception is java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z type Exception report me

陈杰 1598

【目录】Java程序设计课程学习导航(完结撒花)

【内容更新中】Java程序设计课程学习路径,快速导航到你需要的位置,还有扩展提升训练推荐的平台。

小火龙的博客 543

发布war包到私服错误解决

发布war包到nexus私服有时会报如下错误: Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project… 这时因为deploy时maven会自动识别所发布war包的版本。试验了一下,如下两种情况会报如上错误: 1、pom.xml文件里配...

se134789836178的博客 903

uniapp自定义tabbar闪屏?3步搞定原生tabbar隐藏+自定义占位(附完整代码)

本文针对UniApp开发中自定义TabBar切换页面闪烁的痛点,提供了一套根治方案。通过隐藏原生TabBar并利用自定义组件进行视觉占位,巧妙结合原生切换的无闪烁优势与自定义设计的灵活性。文章详细解析了闪屏根源,并附上完整的page.json配置与代码实现,帮助开发者彻底解决此问题,提升小程序应用质感。

postgres8guard的博客 1528

python123题目——个税计算器

类型:简单分支。

m0_62488776的博客 5802

仿牛客网社区项目总结 第四章

仿牛客网社区项目总结 第四章

qq_50209297的博客 636

QMK固件OLED显示屏配置教程:从零开始实现个性化键盘显示(实操部分)

本教程详细介绍了如何从零开始配置QMK固件的OLED显示屏,实现个性化键盘显示。首先,文章解释了OLED显示屏的基本概念及其在键盘中的应用,并介绍了I2C和SPI两种通信方式。接着,教程逐步指导用户如何在QMK固件中启用OLED功能,包括在rules.mk中启用OLED、在halconf.h和mcuconf.h中配置I2C功能,以及在config.h中设置I2C和OLED参数。最后,教程展示了如何在keymap.c中编写代码,实现OLED显示内容,并提供了进阶定制功能,如显示当前层信息、按键状态和QMK L

Despacito0o的博客 578

仿牛客网社区项目总结 第一章

仿牛客网社区项目总结 第一章

qq_50209297的博客 1617

华为OD机试 - 小火车最多人时所在园区站点(Java 2024 E卷 100分)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、发现新题目,随时更新,全天优快云在线答疑。

学Java,找哪吒 995

PyTorch实战(2)——使用PyTorch构建神经网络

在本节中,我们使用 PyTorch 在简单数据集上构建了一个神经网络,训练神经网络来映射输入和输出,并通过执行反向传播来更新权重值以最小化损失值,并利用 Sequential 类简化网络构建过程;介绍了获取网络中间值的常用方法,以及如何使用 save、load 方法保存和加载模型,以避免再次训练模型。

盼小辉丶的博客 1万+

仿牛客网社区项目总结 第三章

仿牛客网社区项目总结 第三章

qq_50209297的博客 1159

2026年数字IC设计禾赛科技笔试带答案解析

本文介绍了一份数字IC设计工程师笔试的试卷结构和部分题目解析。试卷包含15道单选题(30分)、10道填空题(20分)和5道简答/编程题(50分),总分100分,考试时长120分钟。单选题涉及同步时序电路、Verilog语法、跨时钟域设计、FPGA优化、存储器层次、功耗优化等知识点;填空题考查环形振荡器、工艺参数、时序约束、LUT结构等基础概念。试题重点考察应聘者对数字电路设计核心概念的理解和实际工程应用能力,特别是针对激光雷达芯片设计中的关键技术点进行考核。

Open 122

仿牛客网社区项目总结 第五章

仿牛客网社区项目总结 第五章

qq_50209297的博客 704

【人工智能论文发表】基于医学病例文本和多模态大模型的医疗影像分割方法研究

摘要:本研究提出MMS-Former,一种基于级联多模态Transformer的文本引导医学图像分割框架。该模型创新性地将临床文本信息深度融入图像分割全过程,通过SwinUNETR提取视觉特征,ClinicalBERT编码病历文本,并在解码器的每个上采样阶段通过交叉注意力模块实现多级文本特征融合。实验表明,相比纯视觉模型,MMS-Former在Dice系数和IoU指标上分别提升3%以上,在处理边界模糊目标时表现尤为突出。模型还设计了结合Dice损失和图文对比损失的复合目标函数,确保分割精度与语义对齐。代码实

u012133341的博客 139

光学材料仿真软件:FDTD Solutions_(4).材料属性的定义与应用

在光学材料仿真软件中,材料属性的定义和应用是至关重要的一步。正确地定义材料属性可以确保仿真结果的准确性和可靠性。本节将详细介绍如何在FDTD Solutions中定义和应用不同的材料属性,包括介质材料、金属材料、色散材料等,并提供具体的代码示例和数据样例。介质材料是光学仿真中最常见的材料类型之一。在FDTD Solutions中,可以通过多种方式定义介质材料,包括使用预定义的材料库、自定义材料参数或导入材料数据文件。FDTD Solutions内置了一个丰富的材料库,包含了许多常用材料的光学性质。

kkchenjj的博客 1400

ATeam社区(牛客网项目第八章)

项目发布与总结1. 单元测试1.1 注解简介1.2 测试2. 项目监控2.1 使用简介2.2 项目监控功能实现3. 项目部署3.1 系统环境3.2 安装软件3.2.1 远程连接服务器的软件3.2.2 安装unzip3.2.3 安装java1.83.2.4 安装Maven3.2.5 安装MySQL3.2.5 安装Redis3.2.6 安装Kafka3.2.7 安装Elasticsearch3.2.8 安装wkhtmltopdf3.2.9 安装Tomcat3.2.10 安装Nginx3.3 项目访问逻辑3.4

m0_48847558的博客 1273

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

霸榜牛客?阿里 P8 大老整理的 Java 面试核心知识点竟如此霸道

在当今的计算机领域,Java作为一种广泛应用的语言,成为了很多企业和程序员首选。Java开发人员拥有广泛知识,是许多高薪职位的必备条件。随着Java程序员市场的不断扩大,Java相关面试显得尤为重要。最近,阿里P8大牛整理的Java面试核心知识点在牛客网上霸榜,并被广泛传播。这份资料内容包罗万象,对于想要成功在Java行业立足的从业者来说,是一份极其珍贵的笔记,本文将介绍这份资料的具体内容以及它之所以如此受欢迎的原因。现在我将这份——

jjc4261的博客 65

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【牛客有书共读】《Java并发编程实战》第七章+第八章

3-6章读书笔记不是我写的,请点击链接移步牛客网。3-4章 5-6章 第七章 取消与关闭 任务取消 如果外部代码能在某个操作正常完成之前将其置入“完成”状态,那么这个操作就可以成为可取消的。 Java中没有一种安全的抢占式方法来停止线程。 一个可取消的任务必须拥有取消策略,策略中详细定义取消操作的How,When以及What。 中断 通常,中断是实现取消的最合理方式。 ...

Fly Away Now 304

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

数据结构与算法(Java笔记15天)

文章目录Java数据结构与算法前言目录结束 Java数据结构与算法 前言 源码:https://github.com/name365/Java-Data-structure 目录 名称 地址 第一章 稀疏数组 https://blog.youkuaiyun.com/m0_46153949/article/details/106266666 第二章 队列 https://blog.youkuaiyun.com/m0_46153949/article/details/106266666 第三章 链表 htt

杨丙寅 1万+

日记:八月份的总结

这个八月,总是充满了各种新奇; 按照时间线来讲,熬过的几个夜; 这个月自己做的决定的几个晚上都写的有相关的长文,都是给自己写的orz 1:考研与否; 2: 队伍是否解散; 3: 规划羊城行程; 4: 思考自己性格测试的缺陷; 5: 项目展示视频的准备; 触景生情的几个场景(图片TODO): 1:北京路,上下九的重复重复的骑楼商圈; 2:珠江旁的反复反复的水泥大...

weixin_34128501的博客 105

最新Android开发面经,助你顺利通过面试、斩获高薪!

面试前应该做哪些准备?一份优秀的简历、了解投递的岗位要求、复习面试岗位相关知识、整理自己做过的项目、适当的做一些算法题...

m0_59162559的博客 206

2020最新Android大厂高频面试题解析大全(BAT TMD JD 小米)

本文首发于简书——Alvin老师,搬运转载请注明出处,否则将追究版权责任。 上次搜集整理字节跳动面试专题文章的时候也过去了差不多一个月了,期间收到了面试交流群友的积极响应,纷纷表示获益匪浅。部分同学也因此收获了理想的offer! 但看到还有很多人最近还在找Android开发工作, 而且很多人都感觉今年受疫情影响,找工作比去年难很多, 竞争力也增加不少, 因此激发我整理这份An...

AndroidAlvin的博客 1289

2024最新Android大厂高频面试题解析大全(BAT TMD JD 小米)

*其实上面说了这么多,钱是永远赚不完的,在这个知识付费的时代,知识技能提升才是是根本!我作为一名8年的高级工程师,知识技能已经学习的差不多。**在看这篇文章的可能有刚刚入门,刚刚开始工作,或者大佬级人物。像刚刚开始学Android开发小白想要快速提升自己,最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以这里分享一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。这么重要的事情说三遍啦!

X7gUWZnYP的博客 1008
上一篇: Spring可执行定时任务的线程池ThreadPoolTaskScheduler报错:required a bean of type that could not be found.
下一篇: 华南农业大学课设——数据结构课设、Java课设、操作系统课设
夜中听雪
博客等级 码龄8年 230粉丝 69原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值