这里写目录标题

  • springboot后台搭建
  • 1. 创建父项目
  • 1.1 创建netseal
  • 2. 创建子项目
  • 2.1 创建webserver
  • 2.2 创建common
  • 3.正式编码
  • 3.1 修改pom文件
  • 3.1.1 netseal的pom.xml
  • 3.1.2 webserver的pom.xml
  • 3.1.3 common的pom.xml
  • 3.2 填充子项目
  • 3.2.1 数据源配置
  • 3.2.2 引入本地jar
  • 3.3 全局统一异常处理
  • 3.4 文件上传
  • 3.4.1 base64
  • 3.4.2 MultipartResolver
  • 4. Q&A
  • 4.1 Test failures
  • 4.2 启动项目无法注入common的dao
  • 5. 打包及运行
  • 跨域问题


springboot后台搭建

本次搭建使用多模块的方式,建立一个父项目netseal,父项目下建立webserver、common、appserver等项目。

  • 父项目——netseal,maven项目即可
  • 子项目——webserver,springboot项目
  • 子项目——common,springboot项目

idea进行项目的创建可参考使用idea搭建springboot项目

1. 创建父项目

1.1 创建netseal

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_数据库


填写group和artifact。

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_maven_02

2. 创建子项目

2.1 创建webserver

填写group和artifact。

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_数据库_03


初始化选择spring web即可。模块分离后,web端只需要spring web,数据库相关的由其他模块引入。

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_spring_04

2.2 创建common

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_spring_05


初始化选择spring web、jdbc、mysql等。此次项目是模块化的测试,故继续沿用jdbc,暂未整合mybatis。

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_xml_06

3.正式编码

3.1 修改pom文件

3.1.1 netseal的pom.xml
  • 重点1:打包方式为pom
  • 重点2:引入子模块
<?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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>cn.com.infosec</groupId>
	<artifactId>netseal</artifactId>
	<version>1.0-SNAPSHOT</version>
	<!--重点1:打包方式为pom-->
	<packaging>pom</packaging>

	<!--重点2:引入子模块-->
	<modules>
		<module>webserver</module>
		<module>common</module>
	</modules>
	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</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>
	</dependencies>

</project>
3.1.2 webserver的pom.xml
  • 重点1:填写父项目的基本信息,relativePath值为…/pom.xml
  • 重点2:打包方式为jar
  • 重点3:依赖common
  • 重点4:打包配置
  • 重点5:关掉单元测试
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<!--重点1:填写父项目的基本信息-->
	<parent>
		<groupId>cn.com.infosec</groupId>
		<artifactId>netseal</artifactId>
		<version>1.0-SNAPSHOT</version>
		<!--子级Maven的pom文件中,relativePath标签使用的默认值:“<relativePath/>”,但编译环境(IDEA和命令行)不认这种写法
		应使用<relativePath>../pom.xml</relativePath>
		-->
		<relativePath>../pom.xml</relativePath>
	</parent>
	<groupId>cn.com.infosec.netseal</groupId>
	<artifactId>webserver</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>webserver</name>
	<!--重点2:打包方式为jar-->
	<packaging>jar</packaging>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!--内部引用-->
		<!--重点3:依赖common-->
		<dependency>
			<groupId>cn.com.infosec.netseal</groupId>
			<artifactId>common</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

		<!--外部引用-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</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>
	</dependencies>

	<build>
		<plugins>
			<!--重点4:打包,使用maven的插件进行打包时:可指定主类的类路径、并把依赖的包打进jar-->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<!--指定主类-->
					<mainClass>cn.com.infosec.netseal.webserver.WebserverApplication</mainClass>
				</configuration>
				<executions>
					<execution>
						<goals>
							<!--可以把依赖的包都打包到生成的Jar包中-->
							<goal>repackage</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<!--重点5:关掉单元测试,否则项目无法正常启动-->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.18.1</version>
				<configuration>
					<skipTests>true</skipTests>    <!--默认关掉单元测试 -->
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>
3.1.3 common的pom.xml
  • 重点1:填写父项目的基本信息
  • 重点2:打包方式为jar
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<!--重点1:填写父项目的基本信息-->
	<parent>
		<groupId>cn.com.infosec</groupId>
		<artifactId>netseal</artifactId>
		<version>1.0-SNAPSHOT</version>
		<relativePath>../pom.xml</relativePath>
	</parent>
	<groupId>cn.com.infosec.netseal</groupId>
	<artifactId>common</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>common</name>
	<!--重点2:打包方式为jar-->
	<packaging>jar</packaging>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</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>
	</dependencies>

</project>

3.2 填充子项目

webserver和common进行建包、添加文件等操作。
webserver:包含controller、service等;
common:包含entity、dao等;

3.2.1 数据源配置

common的application.yml
指定serverTimezone=UTC,不指定可能会报错

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/netseal_4_data?&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
    username: root
    password: root
3.2.2 引入本地jar

不可避免的,在公司开发项目,会使用到公司自己的jar,所以此时就不能从仓库中获取。
方法:在项目下建立lib资源目录,存放自己的jar。
pom.xml
添加完依赖,可以在项目上选择Maven——Reimport。

<!--本地jar-->
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>configuration2</artifactId>
	<version>2.1</version>
	<scope>system</scope>
	<systemPath>${project.basedir}/lib/commons-configuration2-2.1.jar</systemPath>
</dependency>

3.3 全局统一异常处理

Springboot对于异常的处理也做了不错的支持,它提供了一个 @ControllerAdvice(@RestControllerAdvice)注解以及 @ExceptionHandler注解,前者是用来开启全局的异常捕获,后者则是说明捕获哪些异常,对那些异常进行处理。

/**
 * 全局异常处理器
 *
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
	private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	@ExceptionHandler(WebDataException.class)
	public Object WebDataException(WebDataException e) {
		String message = e.getMessage();
		return R.error(message);// R是响应类,在此处统一响应错误状态码及信息
	}

	@ExceptionHandler(Exception.class)
	public R handleException(Exception e) {
		log.error(e.getMessage(), e);
		return R.error(e.getMessage());
	}
}

3.4 文件上传

对于文件,我们可以采用两种方式:

  1. base64:前台获取文件的base64,后台解码就能得到文件;
  2. MultipartResolver:大文件使用传统方式上传;
3.4.1 base64
3.4.2 MultipartResolver

通常情况下,我们使用上传时,是需要将表单信息和文件一起提交给后台的。

前端

通常前端和后台的交互采用json格式。
使用new FormData()封装文件和其他信息,提交的时候大概是自动由json格式转为了文件上传表单的形式。

后端

后台的方法收到的数据就不是json,就不能再用@RequestBody注解来接收参数了。
springboot关于MultipartResolver有个坑,内置的MultipartResolver有点问题,我们可以用下述方式解决;

  1. 显性注册MultipartResolver
package cn.com.infosec.netseal.webserver.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

@Configuration
public class UploadConfig {
	//显示声明CommonsMultipartResolver为mutipartResolver
	@Bean(name = "multipartResolver")
	public MultipartResolver multipartResolver() {
		CommonsMultipartResolver resolver = new CommonsMultipartResolver();
		resolver.setDefaultEncoding("UTF-8");
		//resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常
		resolver.setResolveLazily(true);
		resolver.setMaxInMemorySize(40960);
		//上传文件大小 5M 5*1024*1024
		resolver.setMaxUploadSize(5 * 1024 * 1024);
		return resolver;
	}

}
  1. 启动类排除内置MultipartResolver
    如果不排除内置MultipartResolver,显性注册的MultipartResolver会无效。
@SpringBootApplication(exclude = {MultipartAutoConfiguration.class})
public class WebServerApplication {
	public static void main(String[] args) {
		SpringApplication.run(WebServerApplication.class, args);
	}
}

4. Q&A

4.1 Test failures

Q:
Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test) on project webserver: There are test failures.

  • A:
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-surefire-plugin</artifactId>
	<version>2.18.1</version>
	<configuration>
		<skipTests>true</skipTests>    <!--默认关掉单元测试 -->
	</configuration>
</plugin>

4.2 启动项目无法注入common的dao

Q:
启动webserver的WebserverApplication方法,会发现common的dao无法被自动注入,报错如下:

Field sysUserDao in cn.com.infosec.netseal.webserver.service.sysUser.SysUserServiceImpl required a bean of type 'cn.com.infosec.netseal.common.dao.sysUser.SysUserDaoImpl' that could not be found.
  • A:
    解决办法:
    在WebserverApplication上使用@ComponentScan(“cn.com.infosec.netseal”)
package cn.com.infosec.netseal.webserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("cn.com.infosec.netseal")
public class WebserverApplication {

	public static void main(String[] args) {
		SpringApplication.run(WebserverApplication.class, args);
	}

}

5. 打包及运行

因为主类在webserver,所以打包写在了webserver下的pom.xml,但是操作是点击父项目的package!!!成功会看到控制台输出build success,jar包生成在了webserver下的target目录。

webserver启动:

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_spring_07

父项目打包:

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_数据库_08


spring boot 前后端不分离 怎么打包 springboot前后端分离教程_maven_09


spring boot 前后端不分离 怎么打包 springboot前后端分离教程_spring_10


将webserver-0.0.1-SNAPSHOT.jar复制到其他磁盘下,打开命令窗口,进入该路径,执行

java -jar xxx.jar即可运行。

java -jar xxx.jar

示例:

spring boot 前后端不分离 怎么打包 springboot前后端分离教程_数据库_11

跨域问题

package cn.com.infosec.netseal.webserver.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Filter配置
 *
 * @author lhx
 */
@Configuration
public class FilterConfig implements WebMvcConfigurer {

	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**") // 所有接口
				.allowCredentials(true) // 是否发送 Cookie
				.allowedOriginPatterns("*") // 支持域
				.allowedMethods("GET", "POST", "PUT", "DELETE") // 支持方法
				.allowedHeaders("*")
				.exposedHeaders("*");
	}

}