关于SpringBoot + Vue,这里列出一个基本的项目实例。
源码:https://github.com/slhuang520/study/tree/master/spring-boot-vue-cli-parent
1. 环境
使用的开发工具为IDEA,最新版本,专为开发Springboot而制。
JDK 版本为8,
Apache Server 为 Tomcat,版本为8
使用Maven来管理开发项目,进行项目的整个合与编译。整个项目结构如下:
2. 项目架构
基本采用前后端分离,使用是的先分离后结合的方案,开发是独立进行的,但最后打包成一个项目进行发布。
前端使用 node js 环境,使用 Vue Cli 3.0以上版本。
后端使用 SpringBoot 搭建整体项目架构,版本为2.1.7-Release。
最后项目整合打包时,使用 Maven 工具。
3. 具体手顺
3.1 创建前后端管理父类
使用IDEA父级别的 Module:
然后,在新建 module中创建一个 Maven 项目:
指定groupId 和 artifactId,Next 创建好。
整个 parent 项目中,删除自动生成的一些目录,比如src | test,只留下 pom.xml 和 iml配置文件,其他的全部删除,没有用。
同时将 packaging 指定为 pom
<!-- parent pom.xml -->
<?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>cn.com.love.hsl</groupId>
<artifactId>spring-boot-vue-cli-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
</project>
3.2 创建前端 UI 项目
整体的项目结构图如下:
3.2.1 使用 IDEA 创建 UI 项目,使其作为之前创建的 Parent的一个 module
需要将目录结构指定在之前创建的 Parent 目录之下:
注意,这里前端我们还是创建一个带有 Maven 的 Module,跟之前的 Parent 项目一样。
将 packaging 也指定为 pom.
删除 src 目录下的其他所有子目录,那些是不需要的。
只需要留下:
- src 空目录,
- pom.xml
- iml 配置文件
3.2.2 安装 vue
创建 Vue Cli 项目,可以完全参考官网给的手顺:
官网地址:https://cli.vuejs.org/zh/guide/installation.html
如果电脑Vue环境已经安装好了,需要确认一下版本是否对,若是不对的话,请按如下方式更新。
- 关于旧版本
Vue CLI 的包名称由 vue-cli 改成了 @vue/cli。 如果你已经全局安装了旧版本的 vue-cli (1.x 或 2.x),你需要先通过 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸载它。
- Node 版本要求
Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+)。你可以使用 nvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。
可以使用下列任一命令安装这个新的包:
npm install -g @vue/cli
查看版本信息,确认是否安装成功:
vue --version
3.2.3 创建 Vue Cli 项目
打开 IDEA的 terminal 窗口(需要将路径调整到UI 项目下),在其中输入以下命令,创建项目:
vue create .
注意这里不需要再指定项目名称了,之前已经创建好的,只需要将 vue的环境配置好。
这个过程可能会有一点慢,需要下载第三方的一些包,在这之前,最好将 npm 的镜像使用为淘宝的,这样下载速度会快一些。
3.2.3.1 .eslintrc.js
配置好自己的编码规则:
module.exports = {
root: true,
env: {
node: true
},
extends: ["plugin:vue/essential", "@vue/prettier"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
"vue/html-indent": [
"error",
4,
{
attribute: 1,
alignAttributesVertically: true,
ignores: []
}
],
"vue/max-attributes-per-line": [
2,
{
singleline: 10,
multiline: {
max: 5,
allowFirstLine: false
}
}
],
"vue/html-self-closing": "off",
"vue/name-property-casing": ["error", "PascalCase"],
"prettier.jsxBracketSameLine": true,
"editor.formatOnSave": true,
"eslint.autoFixOnSave": true,
"prettier/prettier": "off"
},
globals: {
$: true,
Vue: true
},
parserOptions: {
parser: "babel-eslint"
}
};
3.2.3.2 package.json
引入外部的 jquery bootstrap axios
{
"name": "spring-boot-vue-cli-ui",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10",
"vue-router": "^3.0.3"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.10.0",
"@vue/cli-plugin-eslint": "^3.10.0",
"@vue/cli-service": "^3.10.0",
"@vue/eslint-config-prettier": "^5.0.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-vue": "^5.0.0",
"prettier": "^1.18.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.33.0",
"jquery": "^3.4.1",
"bootstrap": "^4.3.1",
"popper.js": "^1.15.0",
"axios": "^0.19.0"
}
}
3.2.3.3 配置 pom.xml 文件
需要让不同的用户,直接将项目拿过去可以进行编译打包,而不需要自己手动搭建环境。
<?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>cn.com.love.hsl</groupId>
<artifactId>spring-boot-vue-cli-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-vue-cli-ui</artifactId>
<packaging>pom</packaging>
<name>spring-boot-vue-cli-ui</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<node.version>v10.15.0</node.version>
<node.directory>${project.parent.build.directory}/${node.version}</node.directory>
<npm.version>6.10.3</npm.version>
<npm-cache.directory>${project.build.directory}\npm-cache</npm-cache.directory>
</properties>
<build>
<plugins>
<!--安装前端自己的编译环境-->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<installDirectory>${node.directory}</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<phase>initialize</phase>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>${node.version}</nodeVersion>
<npmVersion>${npm.version}</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<phase>initialize</phase>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<npmRegistryURL>https://registry.npm.taobao.org</npmRegistryURL>
<arguments>install --no-optional --cache="${npm-cache.directory}"</arguments>
</configuration>
</execution>
<execution>
<id>npm run release</id>
<phase>compile</phase>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<!--将前端打印成 zip 包,方便后面自动拷贝到后端项目-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>make-bundles</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly/zip.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
<finalName>${project.name}-${project.version}</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
3.2.3.4 在根目录下面新建 Vue cli 的配置文件 vue.config.js
引入外部的 jquery,将jquery 作为一个全局的块,直接引入项目中,这样就不用在项目的每个块中再单独引入了。
并指定整个前端项目的 publicPath.
publicPath 其实就是后端项目指定的 context-path,如果后端没有指定的话,这里也可以不用指定。
const webpack = require("webpack");
module.exports = {
publicPath: "sbvc",
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
Popper: ["popper.js", "default"]
})
]
}/*,
devServer: {
proxy: {
"/apis": {
target: "http://localhost:8443/sbvc/",
ws: true,
changeOrigin: true,
pathRewrite: {
'^/apis': ''
}
}
}
}*/
};
这样在项目的任何地方都可以正常使用 $ 符号了。
3.2.3.5 引入外部 bootstrap
前面 package.json文件中,已经将需要的 jquery 和 bootstrap 下载下来了,这里只需要将其引入到项目模块中。
3.2.3.5.1 引入 bootstrap 的静态 css
在 src 目录下面新建一个 static 子目录,用于存放静态资源。
3.2.3.5.2 修改 main.js入口文件
引入 bootstrap.js 和 bootstrap.css.
后面需要使用 axios 发送 http 请求(跟 jquery 的 ajax 类似),这里也一起引入了。
并指定后端的接口,注意目前这个接口是无法使用的,都还没有搭建呢。。。。
import "bootstrap";
import "./static/bootstrap.css";
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import axios from "axios";
Object.defineProperty(Vue.prototype, "$http", {
value: axios
});
Vue.config.productionTip = false;
//后台接口
axios.defaults.baseURL = 'http://localhost:8080/sbvc/';
new Vue({
router,
render: h => h(App)
}).$mount("#app");
其他的都可以不用再另行配置了,使用默认的,到这里应该是可以正常启动前端项目了。
3.2.4 启动前端项目
在 IDEA 的 Terminal 窗口中(注意这里还是需要指定到 UI 目录下),输入如下命令启动前端项目:
npm run serve
启动成功后,直接在浏览器中访问:
http://localhost:8080/sbvc/
应该就可以直接看到画面了。
3.2.5 编写自己的前端页面
以下以创建部门列表页面为列:
3.2.5.1 Dept.vue
在 views 目录下创建页面。
<template>
<div class="dept">
<table id="dept_table" class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr :key="dept.id" v-for="dept in deptList">
<td>{{dept.id}}</td>
<td>{{dept.name}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<style>
.dept {
width: 80%;
margin: 0 auto;
}
</style>
<script>
export default {
name: "Dept",
data() {
return {
deptList: []
}
},
created() {
//this.deptList.push({id: 1, name: "dept1"}, {id: 2, name: "dept2"});
this.getDeptList();
},
watch: {},
methods: {
getDeptList() {
//这里的请求只是模拟的,只获取一个dept信息,而没有获取列表信息
this.$http.get("/dept/get?id=6abad1b324fd438a9cfe1099ab4c78d7").then(res => {
this.deptList = [res.data];
});
}
},
computed: {},
mounted() {
},
components: {}
};
</script>
3.2.5.2 修改 App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>
|
<router-link to="/about">About</router-link>
|
<router-link to="/dept">Dept</router-link>
</div>
<router-view />
</div>
</template>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
3.2.5.3 修改router.js
import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
Vue.use(Router);
export default new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: "/",
name: "home",
component: Home
},
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "./views/About.vue")
},
{
path: "/dept",
name: "dept",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "./views/Dept.vue")
}
]
});
注意,这些修改后,前端环境是会自动编译的,不用我们再次手动编译,并且页面也会刷新,如果页面有打开的话。
3.3 创建后端SpringBoot项目
使用 IDEA 的 Spring Initializr 功能模块,生成 SpringBoot 项目架构。
3.3.1 创建项目
3.3.1.1 New Project
注意这里使用的是 project,而不再是 module。
3.3.1.2 选择 Spring Initializr 功能, next >
3.3.1.3 指定自己的 gourp 和 artical,并将 packaging 修改为war。
3.3.1.4 选择自己的功能。
我这里选择的功能如下:
Spring Boot DevTools
Spring Web Strarter
MYSQL Driver
JDBC API
MyBatis Framework
3.3.1.5 指定项目名称
注意需要在最开始创建的 parent 目录之下。
3.3.2 项目整体结构图
3.3.3 添加自己的配置
3.3.3.1 修改 pom.xml
- 引入 Log4j2 并引入 yml 的配置方式。
- 使用自己配置的 tomcat
- 修改一些打war包的配置
- 结合前端的项目,将前端编译好的文件,直接解压过来,然后再生成 war 包
<?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.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<artifactId>spring-boot-vue-cli</artifactId>
<name>spring-boot-vue-cli</name>
<description>Spring Boot Vue Cli</description>
<packaging>war</packaging>
<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>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--Read application.yml-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--log4j2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<!--<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.css</include>
<include>**/*.js</include>
</includes>
<filtering>true</filtering>
</resource>-->
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>prepare-package</id>
<phase>process-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>cn.com.love.hsl</groupId>
<artifactId>spring-boot-vue-cli-ui</artifactId>
<version>1.0-SNAPSHOT</version>
<type>zip</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.basedir}/src/main/resources/static/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.3.RELEASE</version>
<configuration>
<mainClass>cn.com.love.hsl.Application</mainClass>
<fork>true</fork>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<!--<webResources>
<resource>
<directory>src/main/resources/lib</directory>
<targetPath>WEB-INF/lib</targetPath>
<filtering>false</filtering>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
</webResources>-->
<attachClasses>true</attachClasses>
<classesClassifier>api</classesClassifier>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>-->
</plugins>
</build>
</project>
3.3.3.2 配置application.yml
- 不使用SpringBoot 提供的模板。
- 配置context-path(这里需要与前端配置的 pubicPaht一致)
- 配置 datasource
- 配置 Logging
- 配置静态资源处理
- 指定配置环境(生产还是开发,目前这里只做的生产)
- 开启SSL,注入 server-key(有需要的就添加,具体生成方式,请百度)
debug: false
trace: false
server:
port: 8080
servlet:
context-path: /sbvc
# session:
# timeout: 30
# ssl:
# enabled: true
# ## server single ssl auth
# key-store: classpath:key/server.key.p12
# key-store-password: welcome02@
# key-store-type: PKCS12
# key-alias: fx_cq.alias
#
# ## client more ssl auth
# trust-store: classpath:key/server.key.p12
# trust-store-password: welcome02@
# trust-store-type: PKCS12
# client-auth: need
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: jp.co.fujixerox.log.analysis.model
configuration:
log-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl #这里需要使用log4j2生成日志,因为整个项目都是使用的log4j2
spring:
profiles:
active: prod
devtools:
restart:
enabled: true
additional-paths: src/main/java
datasource:
hikari:
idle-timeout: 300000
minimum-idle: 5
auto-commit: true
max-lifetime: 1200000
connection-timeout: 20000
maximum-pool-size: 12
mvc:
view:
suffix: .html
static-path-pattern: /**
resources:
static-locations: classpath:/templates/,classpath:/static/
# thymeleaf:
# prefix: classpath:/templates/
# suffix: .html
logging:
config: classpath:log4j2.yml
3.3.3.3 配置生产环境数据源
注意:如果mysql版本使用得比较高,在url 中需要如下配置:
&characterEncoding=utf-8&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
否则不能成功连接DB。
spring:
datasource:
# driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/chat?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
url: jdbc:mysql://127.0.0.1:3306/sbvc?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
name: mysql
3.3.3.4 log4j2.yml
Configuration:
status: warn
monitorInterval: 30
Properties:
Property:
- name: log.level.console
value: info
- name: log.path
value: log
- name: project.name
value: sbvc
- name: log.pattern
value: "%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID:-} [%15.15t] %-30.30C{1.} : %m%n"
Appenders:
Console:
name: CONSOLE
target: SYSTEM_OUT
PatternLayout:
pattern: ${log.pattern}
RollingFile:
- name: ROLLING_FILE
fileName: ${log.path}/${project.name}.log
filePattern: "${log.path}/historyRunLog/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Filters:
ThresholdFilter:
- level: error
onMatch: DENY
onMismatch: NEUTRAL
- level: info
onMatch: ACCEPT
onMismatch: DENY
Policies:
TimeBasedTriggeringPolicy:
modulate: true
interval: 1
DefaultRolloverStrategy:
max: 100
- name: PLATFORM_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/platform/${project.name}_platform.log
filePattern: "${log.path}/platform/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy:
modulate: true
interval: 1
DefaultRolloverStrategy:
max: 100
- name: BUSINESS_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/business/${project.name}_business.log
filePattern: "${log.path}/business/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy:
modulate: true
interval: 1
DefaultRolloverStrategy:
max: 100
- name: EXCEPTION_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/exception/${project.name}_exception.log
filePattern: "${log.path}/exception/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
ThresholdFilter:
level: error
onMatch: ACCEPT
onMismatch: DENY
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy:
modulate: true
interval: 1
DefaultRolloverStrategy:
max: 100
- name: DB_ROLLING_FILE
ignoreExceptions: false
fileName: ${log.path}/db/${project.name}_db.log
filePattern: "${log.path}/db/$${date:yyyy-MM}/${project.name}-%d{yyyy-MM-dd}-%i.log.gz"
PatternLayout:
pattern: ${log.pattern}
Policies:
TimeBasedTriggeringPolicy:
modulate: true
interval: 1
DefaultRolloverStrategy:
max: 100
Loggers:
Root:
level: info
AppenderRef:
- ref: CONSOLE
- ref: ROLLING_FILE
- ref: EXCEPTION_ROLLING_FILE
Logger:
- name: platform
level: info
additivity: false
AppenderRef:
- ref: CONSOLE
- ref: PLATFORM_ROLLING_FILE
- name: business
level: debug
additivity: false
AppenderRef:
- ref: BUSINESS_ROLLING_FILE
- name: exception
level: debug
additivity: true
AppenderRef:
- ref: EXCEPTION_ROLLING_FILE
- name: db
level: debug
additivity: true
AppenderRef:
- ref: DB_ROLLING_FILE
- name: jp.co.fujixerox.log.analysis.mapper
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: jp.co.fujixerox.log.analysis.model
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: jp.co.fujixerox.log.analysis.service
level: debug
additivity: false
AppenderRef:
- ref: BUSINESS_ROLLING_FILE
- ref: CONSOLE
- name: jp.co.fujixerox.log.analysis.controller
level: debug
additivity: false
AppenderRef:
- ref: BUSINESS_ROLLING_FILE
- ref: CONSOLE
- name: org.springframework
level: info
additivity: false
AppenderRef:
- ref: PLATFORM_ROLLING_FILE
- ref: CONSOLE
- name: javax.servlet
level: info
additivity: false
AppenderRef:
- ref: PLATFORM_ROLLING_FILE
- ref: CONSOLE
- name: org.mybatis
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: java.sql
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: java.sql.Connection
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: java.sql.Statement
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: java.sql.PreparedStatement
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: java.sql.ResultSet
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: javax.sql
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: com.ibatis
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: org.apache.ibatis
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: org.mybatis.spring
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: com.zaxxer.hikari
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: org.springframework.jdbc
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: org.springframework.transaction
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
- name: javax.sql.DataSource
level: debug
additivity: false
AppenderRef:
- ref: DB_ROLLING_FILE
- ref: CONSOLE
3.3.3.5 处理静态资源 WebMvcConfig.java
这个是必须处理的,不然static下面的 html 无法获取css 或是 js 资源。
package cn.com.love.hsl.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
3.3.3.6 编写启动类Application.java
package cn.com.love.hsl;
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.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.UUID;
@Controller
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
/**
* war package required
* @param builder
* @return
*/
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args) {
System.out.println(UUID.randomUUID().toString().replaceAll("-", ""));
SpringApplication.run(Application.class, args);
}
@GetMapping({"/index/", "/"})
public String index() {
return "index";
}
// /**
// * Open http and https two port
// */
// @Bean
// public ServletWebServerFactory servletContainer() {
// TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
// tomcat.addAdditionalTomcatConnectors(createHTTPConnector());
// return tomcat;
// }
//
// private Connector createHTTPConnector() {
// Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
// //open http(8080)、https(8443)two ports
// connector.setScheme("http");
// connector.setSecure(false);
// connector.setPort(8080);
// connector.setRedirectPort(8443);
// return connector;
// }
// /**
// * http redirect to https
// */
// @Bean
// public TomcatServletWebServerFactory servletContainer() {
// TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
// @Override
// protected void postProcessContext(Context context) {
// SecurityConstraint constraint = new SecurityConstraint();
// constraint.setUserConstraint("CONFIDENTIAL");
// SecurityCollection collection = new SecurityCollection();
// collection.addPattern("/*");
// constraint.addCollection(collection);
// context.addConstraint(constraint);
// }
// };
// tomcat.addAdditionalTomcatConnectors(httpConnector());
// return tomcat;
// }
// @Bean
// public Connector httpConnector() {
// Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
// connector.setScheme("http");
// //Connector listening http port
// connector.setPort(8080);
// connector.setSecure(false);
// //and the redirect to https port
// connector.setRedirectPort(8443);
// return connector;
// }
}
其他的一些都可以使用 SpringBoot的默认配置。
目前整个后端项目应该是可以正常启动了。
3.3.4 启动后端项目
直接运行 Application.java 文件的 main 类就可以了。能正常启动说明配置就好了。
若是不能,请具体查找一下相应的错误,比如:
An incompatible version [1.1.32] of the APR based Apache Tomcat Native library is installed
3.3.5 编写业务逻辑代码
3.3.5.1 Controller(DeptController.java)
package cn.com.love.hsl.controller;
import cn.com.love.hsl.model.Dept;
import cn.com.love.hsl.service.DeptService;
import cn.com.love.hsl.utils.ContextProp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
@Autowired
private ContextProp prop;
private final static Logger logger = LoggerFactory.getLogger(DeptController.class);
@RequestMapping("/get")
public ResponseEntity get(String id) {
logger.info(this.getClass().getName() + "{} {}", ".get(" + id + ")", "started..");
System.out.println(1222222222);
logger.debug(prop.getName());
return ResponseEntity.ok(deptService.get(id));
}
@RequestMapping("/save")
public ResponseEntity save(Dept dept) {
if (StringUtils.isEmpty(dept.getId()))
return ResponseEntity.ok(deptService.insert(dept));
else
return ResponseEntity.ok(deptService.update(dept));
}
@RequestMapping("/delete")
// public ResponseEntity delete(Integer id) {
// deptService.delete(id);
// return ResponseEntity.ok("Delete success!");
// }
public @ResponseBody String delete(String id) {
deptService.delete(id);
return "Delete success!";
}
@RequestMapping("/list")
public ResponseEntity find() {
return ResponseEntity.ok(deptService.findAll());
}
}
3.3.5.2 Mapper (DeptMapper.java)
package cn.com.love.hsl.mapper;
import cn.com.love.hsl.model.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
@Mapper
@Component
public interface DeptMapper {
List<Dept> findAll();
int insert(Dept dept);
int update(Dept dept);
void delete(String id);
Dept get(String id);
}
3.3.5.3 Model
3.3.5.3.1 BaseModel.java
package cn.com.love.hsl.model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.Date;
public class BaseModel implements Serializable {
private String id;
private User creator;
private Date createDate;
private User Updater;
private Date updateDate;
private final static Logger logger = LoggerFactory.getLogger(BaseModel.class);
public String getId() {
//String.format("Hello, %s!", name);
logger.info(this.getClass().getName() + "{} {}", ".get(" + id + ")", "started..");
return id;
}
public void setId(String id) {
this.id = id;
}
public User getCreator() {
return creator;
}
public void setCreator(User creator) {
this.creator = creator;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
public User getUpdater() {
return Updater;
}
public void setUpdater(User updater) {
Updater = updater;
}
public Date getUpdateDate() {
return updateDate;
}
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
}
3.3.5.3.2 Dept.java
package cn.com.love.hsl.model;
import cn.com.love.hsl.controller.DeptController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class Dept extends BaseModel {
private String name;
private final static Logger logger = LoggerFactory.getLogger(DeptController.class);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.3.5.3.3 User.java
package cn.com.love.hsl.model;
import org.springframework.stereotype.Component;
@Component
public class User extends BaseModel {
}
3.3.5.4 Service
3.3.5.4.1 BaseService.java
package cn.com.love.hsl.service;
import cn.com.love.hsl.model.BaseModel;
import cn.com.love.hsl.model.User;
import java.util.Date;
import java.util.UUID;
public class BaseService {
protected void preInsert(BaseModel entity) {
entity.setId(UUID.randomUUID().toString().replaceAll("-", ""));
entity.setCreator(new User());
entity.setCreateDate(new Date());
entity.setUpdater(new User());
entity.setUpdateDate(new Date());
}
protected void preUpdate(BaseModel entity) {
entity.setUpdater(new User());
entity.setUpdateDate(new Date());
}
}
3.3.5.4.2 DeptService.java
package cn.com.love.hsl.service;
import java.util.List;
public interface DeptService<T> {
List<T> findAll();
int insert(T dept);
int update(T dept);
void delete(String id);
T get(String id);
}
3.3.5.4.3 DeptServiceImpl.java
package cn.com.love.hsl.service.impl;
import cn.com.love.hsl.controller.DeptController;
import cn.com.love.hsl.mapper.DeptMapper;
import cn.com.love.hsl.model.Dept;
import cn.com.love.hsl.service.BaseService;
import cn.com.love.hsl.service.DeptService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class DeptServiceImpl extends BaseService implements DeptService<Dept> {
@Autowired
private DeptMapper deptMapper;
private final static Logger logger = LoggerFactory.getLogger(DeptController.class);
@Override
public List<Dept> findAll() {
return deptMapper.findAll();
}
@Override
@Transactional
public int insert(Dept dept) {
this.preInsert(dept);
return deptMapper.insert(dept);
}
@Override
@Transactional
public int update(Dept dept) {
this.preUpdate(dept);
return deptMapper.update(dept);
}
@Override
@Transactional
public void delete(String id) {
deptMapper.delete(id);
}
@Override
public Dept get(String id) {
logger.info(this.getClass().getName() + "{} {}", ".get(" + id + ")", "started..");
return deptMapper.get(id);
}
}
3.3.5.5 Utils
3.3.5.5.1 LogEnum.java
package cn.com.love.hsl.utils;
public enum LogEnum {
BUSINESS("business"),
PLATFORM("platform"),
DB("db"),
EXCEPTION("exception"),
;
private String category;
LogEnum(String category) {
this.category = category;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
3.3.5.5.2 LogUtils.java
package cn.com.love.hsl.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogUtils {
/**
* Get Business logger
*/
public static Logger getBusinessLogger() {
return LoggerFactory.getLogger(LogEnum.BUSINESS.getCategory());
}
/**
* Get Platform logger
*/
public static Logger getPlatformLogger() {
return LoggerFactory.getLogger(LogEnum.PLATFORM.getCategory());
}
/**
* Get DB logger
*/
public static Logger getDBLogger() {
return LoggerFactory.getLogger(LogEnum.DB.getCategory());
}
/**
* Get normal exception logger
*/
public static Logger getExceptionLogger() {
return LoggerFactory.getLogger(LogEnum.EXCEPTION.getCategory());
}
}
3.3.5.5.3 ContextProp.java
package cn.com.love.hsl.utils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class ContextProp {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.3.5.6 DB Mapper(DeptMapper.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.com.love.hsl.mapper.DeptMapper">
<select id="get" resultType="cn.com.love.hsl.model.Dept" parameterType="java.lang.String">
select * from dept where id= #{id};
</select>
<select id="findAll" resultType="cn.com.love.hsl.model.Dept">
SELECT * from dept;
</select>
<insert id="insert">
insert into dept ( name ) values (#{name});
</insert>
<delete id="delete" parameterType="java.lang.String">
delete from dept where id= #{id};
</delete>
<update id="update">
update dept set name=#{name} where id=#{id};
</update>
</mapper>
业务逻辑编写完了,这时项目应该会自动重启,若是启动成功,说明环境是好的。
4 发布项目
4.1 环境的整合
之前已经将前端的打包,以及后台拷贝前端的文件的逻辑,都已经实现了。
现在只需要整合一下两个项目,在parent 中配置一下,使得一步操作,可以完成所有的编译。
4.2 修改 parent 的 pom.xml 文件
<?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>cn.com.love.hsl</groupId>
<artifactId>spring-boot-vue-cli-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<-- 将前后端作为模块管理 -->
<modules>
<module>spring-boot-vue-cli-ui</module>
<module>spring-boot-vue-cli</module>
</modules>
</project>
4.3 打包整个项目
在 IDEA 的 Terminal 窗口中(注意这里的路径需要指向 parent,也就是在 parent 项目中进行编译),输入如下命令:
mvn clean package
慢慢等。
这里会:
- 下载前端使用需要的 node 和 npm 环境,并进行安装。
- 编译前端并打成 zip 包
- 后端拷贝前端的 zip 文件,并解压到 java/main/resources/static 目录下
- 后台生成 war 包
4.4 发面项目
将生成好的 war 包拷贝到指定的 Apache server 中,比如Tomcat,如果是 Tomcat的话,需要使用Tomcat8,并启动server .
启动成功后, 直接在浏览器中访问,就可以了。