DEV Community

Cover image for Easy Way to Separate Java Backend and Vue Frontend
Yw Zhang
Yw Zhang

Posted on • Edited on

Easy Way to Separate Java Backend and Vue Frontend

How to Run

My complete project is on the github.vue-java-separate

 git clone git@github.com:zhng1456/vue-java-separate.git 
Enter fullscreen mode Exit fullscreen mode

Open the project in IDEA and run Application.java

Image description

Access http://localhost:9090 in chrome

Explore the network tab in chrome dev tool,we find that http://localhost:9090/api/users returns the data of the table.

Image description

The post will help you create the project from scratch and separate backend and frontend.

Java Backend

First,create a maven project in you IDEA.

File→New → Project

create a module,New→module

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"> <parent> <artifactId>vue-java-separate</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>java-backend</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project> 
Enter fullscreen mode Exit fullscreen mode

Create the first controller

 package com.yw; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author henry * @date 2021/8/3 */ @RestController @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @GetMapping("/") public String hello() { return "admin"; } } 
Enter fullscreen mode Exit fullscreen mode

change port in application.yml

 server: port: 9090 context-path: / 
Enter fullscreen mode Exit fullscreen mode

Run the project and curl http://localhost:9090

 $ curl "http://127.0.0.1:9090/" admin% 
Enter fullscreen mode Exit fullscreen mode

Vue project

Init

use vue-cli create webpack project.

I create vue project in root of the maven project.

If you develop more complex project,you can put vue project in another git repository.

 vue init webpack vue-frontend cd vue-frontend # run the application npm run dev # build npm run build 
Enter fullscreen mode Exit fullscreen mode

After execute “npm run build”,the dist dictory is as follows

Image description

Simplify js and css files

Modify the webpack config files to make one js file and one css file in dist directory.

Image description

The detail is in this commit.

Install Element UI

 npm install element-ui -S 
Enter fullscreen mode Exit fullscreen mode

modify main.js

 // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', components: { App }, template: '<App/>' }) 
Enter fullscreen mode Exit fullscreen mode

Send HTTP Request

Add a controller in java backend

 package com.yw.controller; import com.yw.entity.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; @RestController @RequestMapping("/api") public class UserController { @GetMapping("users") public List<User> selectAllUsers() { List<User> userList = new ArrayList<>(); for (int i = 1; i <= 5; i++) { User user = new User(); user.setId(1); user.setName(String.format("name%s", i)); user.setAddress(String.format("address%s", i)); userList.add(user); } return userList; } } 
Enter fullscreen mode Exit fullscreen mode

Call the controller in vue and show results with el-table

 export async function getAllUsers() { const response = await fetch('/api/users'); return await response.json(); } 
Enter fullscreen mode Exit fullscreen mode
 <template> <div class="hello"> <h1>{{ msg }}</h1> <el-row> <el-button>default</el-button> <el-button type="primary">primary</el-button> <el-button type="success">success</el-button> <el-button type="info">info</el-button> <el-button type="warning">warning</el-button> <el-button type="danger">danger</el-button> </el-row> <el-table :data="userList" style="width: 100%"> <el-table-column prop="id" label="id" width="180"> </el-table-column> <el-table-column prop="name" label="name" width="180"> </el-table-column> <el-table-column prop="address" label="address"> </el-table-column> </el-table> </div> </template> <script> import { getAllUsers } from '../services/user' export default { name: 'HelloWorld', data () { return { msg: 'Welcome to Your Vue.js App', userList: [] } }, methods: { getAllUsers() { getAllUsers().then(response => { console.log(response) this.userList = response }) } }, mounted() { this.getAllUsers(); } } </script> 
Enter fullscreen mode Exit fullscreen mode

Run Locally

Before run the project,we need to config proxy in webpack config

 devServer: { proxy: { '/api/*': { target: 'http://localhost:9090', changeOrigin: true, secure: false } } } 
Enter fullscreen mode Exit fullscreen mode

Run java backend and run vue project,access http://localhost:8080

Image description

Separate Backend and Frontend

How to Separate

The role of the front-end project is to provide the built js files and css files.If we can access the file by internet,all links are fine.So the solution to separate backend and frontend is

  • Put the root of pages,index.html to java backend and use FreeMarker to show it
  • Upload files to Google Cloud Storage
  • Import js files and css files in index.html

Add FreeMarker

Add Maven dependency

 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> 
Enter fullscreen mode Exit fullscreen mode

config FreeMarker in application.yaml

 server: port: 9090 context-path: / spring: freemarker: suffix: .ftl 
Enter fullscreen mode Exit fullscreen mode

Create the directory templates in resources and create index.ftl

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>vue-frontend</title> </head> <body> <div id="app"></div> </body> </html> 
Enter fullscreen mode Exit fullscreen mode

Upload Files to Google Cloud Storage

We need to craete a bucket and the most important thing is to set Public to internet.

Image description

Then upload js files and css files(you can find this files in your dist directory of vue project)

Image description

Click “Copy URL” and confirm that you can access it.

Import cloud files in template

Import files in index.ftl

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link href="https://storage.googleapis.com/webpack-frontend/app.css" rel="stylesheet"> <title>vue-frontend</title> </head> <body> <div id="app"></div> <script type="text/javascript" src="https://storage.googleapis.com/webpack-frontend/app.js"></script> </body> </html> 
Enter fullscreen mode Exit fullscreen mode

Run java backend

 /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=64768:/Applications/IntelliJ IDEA.app/Contents/bin -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/legacy8ujsse.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/openjsse.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/rt.jar:/Users/yunwang/workspace/vue-java-separate/java-backend/target/classes:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.1.6.RELEASE/spring-boot-starter-web-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot-starter/2.1.6.RELEASE/spring-boot-starter-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot/2.1.6.RELEASE/spring-boot-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.1.6.RELEASE/spring-boot-autoconfigure-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.1.6.RELEASE/spring-boot-starter-logging-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar:/Users/yunwang/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar:/Users/yunwang/.m2/repository/org/slf4j/slf4j-api/1.7.26/slf4j-api-1.7.26.jar:/Users/yunwang/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.11.2/log4j-to-slf4j-2.11.2.jar:/Users/yunwang/.m2/repository/org/apache/logging/log4j/log4j-api/2.11.2/log4j-api-2.11.2.jar:/Users/yunwang/.m2/repository/org/slf4j/jul-to-slf4j/1.7.26/jul-to-slf4j-1.7.26.jar:/Users/yunwang/.m2/repository/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar:/Users/yunwang/.m2/repository/org/springframework/spring-core/5.1.8.RELEASE/spring-core-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/spring-jcl/5.1.8.RELEASE/spring-jcl-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/yaml/snakeyaml/1.23/snakeyaml-1.23.jar:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.1.6.RELEASE/spring-boot-starter-json-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.9/jackson-databind-2.9.9.jar:/Users/yunwang/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0/jackson-annotations-2.9.0.jar:/Users/yunwang/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.9/jackson-core-2.9.9.jar:/Users/yunwang/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.9.9/jackson-datatype-jdk8-2.9.9.jar:/Users/yunwang/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.9.9/jackson-datatype-jsr310-2.9.9.jar:/Users/yunwang/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.9.9/jackson-module-parameter-names-2.9.9.jar:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.1.6.RELEASE/spring-boot-starter-tomcat-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.21/tomcat-embed-core-9.0.21.jar:/Users/yunwang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/9.0.21/tomcat-embed-el-9.0.21.jar:/Users/yunwang/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/9.0.21/tomcat-embed-websocket-9.0.21.jar:/Users/yunwang/.m2/repository/org/hibernate/validator/hibernate-validator/6.0.17.Final/hibernate-validator-6.0.17.Final.jar:/Users/yunwang/.m2/repository/javax/validation/validation-api/2.0.1.Final/validation-api-2.0.1.Final.jar:/Users/yunwang/.m2/repository/org/jboss/logging/jboss-logging/3.3.2.Final/jboss-logging-3.3.2.Final.jar:/Users/yunwang/.m2/repository/com/fasterxml/classmate/1.4.0/classmate-1.4.0.jar:/Users/yunwang/.m2/repository/org/springframework/spring-web/5.1.8.RELEASE/spring-web-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/spring-beans/5.1.8.RELEASE/spring-beans-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/spring-webmvc/5.1.8.RELEASE/spring-webmvc-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/spring-aop/5.1.8.RELEASE/spring-aop-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/spring-context/5.1.8.RELEASE/spring-context-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/spring-expression/5.1.8.RELEASE/spring-expression-5.1.8.RELEASE.jar:/Users/yunwang/.m2/repository/org/springframework/boot/spring-boot-starter-freemarker/2.1.6.RELEASE/spring-boot-starter-freemarker-2.1.6.RELEASE.jar:/Users/yunwang/.m2/repository/org/freemarker/freemarker/2.3.28/freemarker-2.3.28.jar:/Users/yunwang/.m2/repository/org/springframework/spring-context-support/5.1.8.RELEASE/spring-context-support-5.1.8.RELEASE.jar com.yw.Application . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.6.RELEASE) 2022-09-18 06:21:04.801 INFO 3257 --- [ main] com.yw.Application : Starting Application on Zhangs-MacBook-Air.local with PID 3257 (/Users/yunwang/workspace/vue-java-separate/java-backend/target/classes started by yunwang in /Users/yunwang/workspace/vue-java-separate) 2022-09-18 06:21:04.806 INFO 3257 --- [ main] com.yw.Application : No active profile set, falling back to default profiles: default 2022-09-18 06:21:05.182 INFO 3257 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 9090 (http) 2022-09-18 06:21:05.191 INFO 3257 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-09-18 06:21:05.191 INFO 3257 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.21] 2022-09-18 06:21:05.229 INFO 3257 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-09-18 06:21:05.230 INFO 3257 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 369 ms 2022-09-18 06:21:05.307 INFO 3257 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2022-09-18 06:21:05.342 INFO 3257 --- [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page template: index 2022-09-18 06:21:05.398 INFO 3257 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 9090 (http) with context path '' 2022-09-18 06:21:05.403 INFO 3257 --- [ main] com.yw.Application : Started Application in 15.777 seconds (JVM running for 21.088) ``` Notice “Adding welcome page template: index” and it means your config is correct. Access http://localhost:9090 ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4s3qabqrn3vhwx1hcnwl.png) ### More convenient Way to Upload files It is too troublesome to manually upload the file every time, is there a more convenient way? Yes,we can upload files by node client of Google Cloud Storage. I will detail this part in another post [how-to-deploy-vue-frontend](https://dev.to/zhng1456/how-to-deploy-vue-frontend-17ph). 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)