记录这两年的学习以及简述这次基于springboot框架的课程设计和打war包部署的坑

    技术2025-10-11  14

    一、前言

    一想都是满满的经历呀。如果不想看我废话,可以直接跳到后面。

    1 关于编程

    1.1 C、C++

    作为一名软件工程生,编程是我以后自力更生的必备技能。奈何大一的我不懂得轻重,基本没有把精力放在编程上,以至于大一结束时只是似懂非懂地学了下C语言,对于作为C语言灵魂的指针那是一概不知。对于C语言的内存模型以及指针的理解还是在这学期加深的。学了C语言一定得学C++,它基于C,拓展C,对C语言的一些不足进行了优化,效率不输于C多少,更重要的是它采用了面向对象思想。

    1.2 Python

    大二我突然觉醒,意识到编程对我的重要性,但那时对编程的兴趣不算太大,于是找了相对简单的Python来学习,一学就上瘾。学Python基础用的是老师推荐的HeadFirst Python,简单易懂。跟着书我用flask框架设计出了我的第一个网页。 学完Python基础后,我去了解了一下更深的学习方向,有Web开发、爬虫、数据分析、人工智能等等。我选择了爬虫,于是买了本爬虫实战想要系统学习,正逢那会儿实验室招新,也许老师见我学习力十足,放我进去,于是我有了个可以专心搞技术的地方,有桌有电有网,何乐而不为?刚进去老师就让我跟着学长学姐一起做一个知识图谱的项目,需要某个网站的所有数据,而正好我又在学爬虫。于是,两个周内,我和搭档用各种爬虫(普通爬虫、多线程爬虫、scrapy框架、selenium爬虫)把那个网站所有的数据都整了下来,总共三百多兆。我现在都觉得我那两个周的学习不可思议,放在平时是不敢想象的。由于拿数据要分析网站,于是我对前端的理解(认知上)更深刻了。 在那之后,我产生一个想法,既然爬虫能够爬数据,那我是不是可以搞一个程序,把我想看的小说都给爬到本地来看呢。二话不说直接开整,一天不到我的初代小说爬虫就诞生了,不过是黑窗口,而且只能爬一本固定的小说。不过万事有个开头嘛,接下来不知道多少天,我对我的爬虫进行拓展,它慢慢开始成长。第一个我觉得比较重大的成长是它能够爬某个网站的指定小说了,不过依然是在黑窗口执行。 渐渐的,到了暑假实训的时候了,去了沈阳东软,报的Python方向。实训期间我那个爽呀,基础我都学完了,再听老师将就是巩固了,加深了我对Python的理解。学习之余,我又在摸索我的小说爬虫,想让它快快长大。实训接近尾声的时候,它成长到可以爬取若干本网站的指定小说了,而且我改用了多线程,解决了多线程爬取章节顺序的问题,大大加快了爬取速度。本次实训,老师讲了两个周的人工智能,不过说实话,我应该连门都没入。 假期剩下的这段时间,我一直在摸索人工智能,买了本深度学习入门,先学的神经网络,在转过去理解机器学习的一些算法。到假期结束,我已经会搭建卷积神经网络对图像进行识别,和对简单的英文问句进行分类,也理解了一些算法,比如朴素贝叶斯等等(现在都忘了)。 大三上的时候,我继续让我的爬虫成长,用了Python QT,把它设计成了一个桌面程序,总共可以爬取三十多个网站的任何小说(现在不知道还剩多少),而且可以搜索一些小说进行爬取,过滤了部分垃圾数据,并且增加了简单的阅读功能。 我会把软件放上,喜欢小说的小伙伴可以拿去试试,也可以给我评论哦!

    小软件->小说爬虫 提取码:b1yw

    1.3 Java

    写完小说爬虫之后,我都在学习Java,也是从基础开始。在学习的过程中逐渐加深对面向对象的理解。学习时间比较漫长,直到寒假,才算是简单地过了一遍。紧接着就开始了JavaWeb的学习。从写html开始,学习简单的样式和js,学习servlet,以及理解网站开发的层次结构。用了半个寒假,我基本学完了传统的JavaWeb。正逢那会儿我在玩一个Steam上叫SpaceEngine的游戏,每次录制完视频之后都得放到格式工厂转码才能上传到某站。我就想:现在视频转换的软件那么多,我是不是可以搞个网页办的?正好刚学完Web基础,二话不说,直接开整。不做不知道,一做那个难呀。涉及到视频处理,那就得有上传、下载、预览的功能,注册和找回密码还得有邮件发送的功能,最重要的是视频处理,于是又去安装编译ffmpeg(超级坑)。网站做完了总得发布吧,不然别人怎么看,于是又去租用阿里云服务器,在上面搭建JavaWeb环境(也是超级坑)。我现在说的这么简短,开发期间那个难呀,不知道多少次整到我怀疑人生,网上的很多解决办法看似能解决问题,实则只能解决它们自己的问题,很多时候还得靠自己摸索。最终还是没有让自己失望,用传统的Web技术整出个简单的视频、音频上传、处理、下载的功能。 虽然功能不多,支持的音视频格式不多,但也算有个样子了。开发过程中涉及到的一些问题解决在我的另外一些博客里。网站也有一些问题没解决,比如断点续传,不过也能用。 接下来把网址放上,想体验的可以体验一下(服务器毕竟是学生机,下载速度堪忧)。

    小网站->音视频简单处理

    接下来当然是学习框架啦,想都不用想,从Spring开始,在这里,我第一次感受到了Java反射和注解的强大。Spring基础使用学完之后则学习持久化层框架Mybatis,我惊叹于把sql写到XML然后用反射创建对象是多么厉害的方式。接下来学习视图层SpringMVC,解决了之前做传统Web每个Servlet都要写一个类,并且在web.xml配置的繁琐操作。本学期的专业选修就是学习SSM,正好和我的学习进度对上。结课之后,我把Spring、SpringMVC还有Mybatis集成在一起(应该还可以更优化,不过能用),形成了SSM框架,并且做了个简单的好友录功能。

    SSM集成(文笔不好勿怪)->SSM集成心得 提取码:cvgg

    SSM运用->简单好友录

    二、SpringBoot框架搭建和运用

    接下来是正文。。。

    1 SpringBoot框架搭建

    1.1 Maven环境安装

    Maven的安装和配置可以参照我的另一篇博客(注意加上阿里云镜像的配置,我那篇没有配置),只不过那篇是在Maven里面运用,而Springboot框架的搭建和使用在IDEA,只需要再在IDEA中配置一下maven就行。

    1.2 用Maven创建Springboot项目

    如图: 有些可能会遇到创建maven web项目之后没有生成webapp文件夹(很显然我遇到了)的情况(好像跟plugin有关),可以试试把下面的pom.xml配置好,然后maven会自动生成该目录。如果仍然没有,很可能是maven plugins不完整的原因,下面这一步给出了可能的解决方案。

    1.3 pom.xml的配置

    直接上代码,如果不要求特定版本的springboot,则可以直接复制,然后注意下有注释的地方:

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.neusoft</groupId> <artifactId>his3</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>his Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- 如果打war包,在打包的时候把这块取消注释 --> <!-- <exclusions>--> <!-- <exclusion>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-tomcat</artifactId>--> <!-- </exclusion>--> <!-- </exclusions>--> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <!--maven模板创建的工程,在IDEA运行时需要注释如下标记--> <!--maven模板创建的工程,打包时需要打开如下标记--> <!-- <scope>provided</scope>--> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!-- jstl标签库 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1.3-b06</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!--分页插件依赖--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.10</version> </dependency> <!-- 配置spring jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.5</version> </dependency> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-starter-thymeleaf</artifactId>--> <!-- </dependency>--> </dependencies> <build> <!-- 打包时,换成自己的项目名 --> <finalName>his3</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>

    如果Maven安装并配置成功、在IDEA配置Maven仓库成功,那么pom.xml里面的依赖将自动从仓库加载,如果没有,则会到阿里云下载,我们只需要点击右下角的import changes。

    注:如果在自动导入或安装依赖的时候报什么plugin的错(我配置的时候遇到),请检查仓库里面org\apache\maven\plugins路径下的文件是否完整(不完整可能是下载网不好),找到并删掉相应部分,或者干脆直接把plugins目录下的文件全删掉,在IDEA里import changes,maven会自动下回来。

    1.3 项目目录

    如果上诉步骤成功由于我将要打包的方式是war包,因此静态资源(如果要打jar则把静态资源放在resources文件夹下)放在webapp下(springboot能自动识别四个位置的静态资源,webapp根目录就是其一),总体目录如下: 其中java目录要 右键->Make Directory As->Sources Root, resources目录(没有自己创建)要 右键->Make Directory As->Resources Root。 target目录不用管,它是用来存放打包结果的。

    接下来是java具体目录: com.neusoft这个可以自己取, controller存放表述层的代码, entity存放实体类代码, interceptor存放自定义的拦截器以及注册实现, mapper存放与数据库进行持久化操作的mapper接口, service存放业务逻辑层代码,许多判断逻辑在这实现, utils存放我实现ApplicationContextAware接口获取上下文来从springboot容器中获取对象的类。 HisApplication为springboot启动类:

    package com.neusoft; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class HisApplication { public static void main(String[] args) { SpringApplication.run(HisApplication.class, args); } }

    ServletInitializer为打包时需要另外实现的类(这个地方很重要,我打包找了半天发现没写Configuration注解,这样springboot就扫描不到):

    package com.neusoft; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Configuration; @Configuration public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(HisApplication.class); } }

    接下来是resources目录: 其中的mapper目录需要自己创建,存放各种写sql语句的xxxmapper.xml映射文件。 static和templates目录需要的话自己创建,一般打jar包的话,js、css这些放在static目录,html放在templates目录,使用thymeleaf模板的话html也放在templates目录,springboot默认会识别这两个目录。我是打war包,所以都放在webapp了。

    application.properties是springboot允许自定义设置的地方,里面可以配置数据库账号、*mapper.xml地址、thymeleaf模板等等。

    # 用到的数据库名要改成自己的,是his spring.datasource.url=jdbc:mysql://localhost:3306/his?serverTimezone=UTC&rewriteBatchStatements=true&useUnicode=true&characterEncoding=utf8 # 改成自己的 spring.datasource.username=mysql用户名 spring.datasource.password=mysql密码 # mysql版本为5.7的话改成com.mysql.jdbc.Driver,当然pom.xml里面相应连接mysql的依赖mysql-connector-java也要改成5.7的 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # mybatis对应的映射文件路径,改成自己的 mybatis.mapper-locations=classpath:com/neusoft/mapper/*.xml # mybatis对应的实体类,改成自己的 mybatis.type-aliases-package=com.neusoft.entity pagehelper.helper-dialect=mysql

    webapp用于存放静态资源,其中web.xml不需要怎么配置,可以配置一个解决post请求中文乱码的过滤器:

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>his</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>login.html</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- springmvc的核心控制器 --> <!-- <servlet>--> <!-- <servlet-name>DispatcherServlet</servlet-name>--> <!-- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>--> <!-- <init-param>--> <!-- <param-name>contextConfigLocation</param-name>--> <!-- <param-value>classpath:springMVC.xml</param-value>--> <!-- </init-param>--> <!-- <load-on-startup>1</load-on-startup>--> <!-- </servlet>--> <!-- <servlet-mapping>--> <!-- <servlet-name>DispatcherServlet</servlet-name>--> <!-- <url-pattern>/</url-pattern>--> <!-- </servlet-mapping>--> <!-- 解决post请求中文乱码 --> <filter> <filter-name>EncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置监听器:加载所有spring容器 --> <!-- <context-param>--> <!-- <param-name>contextConfigLocation</param-name>--> <!-- <param-value>classpath:applicationContext-*.xml</param-value>--> <!-- </context-param>--> <!-- <listener>--> <!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>--> <!-- </listener>--> </web-app>

    因为没有集成springmvc,因此不需要配置核心控制器,spring的监听器也不需要配置,springboot启动类上的 @SpringBootApplication注解会默认扫描启动类所在目录及其子目录中加上了注解的类,entity的实体类注解为@Component,Contoller的控制器的注解为@Controller,mapper的数据持久化接口的注解为Mybatis提供的@Mapper,service的业务逻辑类的注解为@Service,自定义的拦截器注解为@Component,注册拦截器的类注解为@Configuration。

    1.4 打包及排坑

    这次课设使用springboot和idea还挺方便的,前面一周我整得那是风风火火,就算有困难也很快解决了。今天儿寻思发到服务器上去,没想到打包部署才是终极大Boss,又让我体验到绝望的感觉,我甚至都怀疑服务器出问题了(本地能运行,在服务器部署完一访问就报404,能不怀疑么),在接近一天的时间内,我经历了打包的各种坑,网上资料都翻遍了,很多不是没用,而是那些坑我尽占了,只解决一种当然不能解决问题,得同时解决,这就很难受。 终于成功了,综合起来就是下面的几步,缺一就能让人绝望。

    第一步:继承SpringBootServletInitializer实现自己的ServletInitializer,

    package com.neusoft; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Configuration; @Configuration public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(HisApplication.class); } }

    其中那个HisApplication改为自己的启动类名,放在启动类同级目录下。

    这里有个坑:@Configuration注解一定要加上,否则扫描不到。

    第二步:在pom.xml中排除打包时带上的springboot内置tomcat(因为要打包成war包放到自己的服务器运行,不排除会冲突),把之前写的pom.xml文件中注释的部分取消注释就行。 第三步:修改路径,修改所有的html、js里面关于路径的地方,加上项目名。在本地idea运行时,你会发现访问页面不用加上项目名,比如项目名为demo,登陆页面为login.html,那么通过http://localhost:8080/login.html就能访问页面,其它的诸如css、js、image以及Controller里的路径同理。然而将war包部署到服务器的tomcat后,它会默认以war包名为访问项目的根路径,也就是http://localhost:8080/demo,此时想要访问这些路径就得这样:http://localhost:8080/demo/login.html,那么原先写的路径就有问题了。可是这样一个一个改,万一项目复杂就麻烦了,如果用jsp还好,可以通过EL表达式:${pageContext.request.contentPath}来获取上下文路径,这样打包也不用改路径,屡试不爽,那么用html呢?我没想到其它办法,也许使用thymeleaf模板可以通过它的表达式来获取路径,纯html就只能通过写base标签了:

    <base href=‘http://服务器ip:服务器端口/项目名/’>

    这样其它的路径就不用改了,只不过换服务器后就得改相应的ip和端口。

    当然,也可以修改tomcat的配置文件,网上一大堆,修改后就可以按照原先的方式访问了。不过不建议这样,万一项目一多,每个项目都有login.html,怎么搞?

    第四步:打包,先说下我错误的打包方式: 首先使用clean命令没有问题, 接下来问题来了,使用install报什么plugin2.5的错, 查了一堆资料… 后来使用war,咦,打包竟然成功了? 赶快部署到服务器运行,哈,解压成功! 再按照路径访问,嘿,成功打开了登陆页面,静态资源也能请求到! 输入用户名密码,点击登陆,咦,怎么没反应? 我打开开发者工具,发现是Controller路径请求404,也就是不能访问Controller,我就奇了怪了,前端能访问,你Controller就不行,难道更傲娇? 几个小时过去了… 我怀疑过自己定义的拦截器是不是把Controller给拦截了,一顿操作,碰一鼻子灰… 后来我偶然点击进入了tomcat解压的项目里面,看了看WEB-INF文件夹, 我去!!!空的,根本没有编译好的class文件以及配置文件!!! 恍然大悟,感情是java代码根本就没有打包进来啊!!! 又是一顿搜索,查到一篇博客说一堆maven的声明周期问题,,总之就是要这样操作才行: 点击右上角那个m,在弹出的界面使用mvn clean和mvn package或mvn install,打包成功!放到服务器,解压成功,访问成功,WEB-INF目录也有编译好的class等文件。

    我滴个乖乖,我对maven的生命周期了解不深,为什么要这么打包、这是什么原理我也不知道。不过能成功就万幸了。

    附上登陆界面:

    附上网址(不能注册):可以体验一下登陆界面的特效 登陆界面

    登陆界面的背景我从网上找的动态3D背景,一顿修改改成了自己的。

    附上登陆界面模板: 登陆界面模板 提取码:qypw

    1.5小结

    遇上问题不可怕,互联网是我们的老师,得耐心求解。 我遇到的这些问题不一定能够帮人解决,但真心希望能有所帮助!

    Processed: 0.011, SQL: 10