前后端分离:实战——“全栈”路上的一大步

了解到了前后端分离的技术后,非常眼热的想试一下,在前几篇文章中分别整理了SSM框架整合、Vue的使用、ElementUI的使用、Axios的使用,今天终于通过一个小Demo实现了前后端分离,这是“全栈”路上的一小步,却是我个人的一大步,冲!


0.准备工作

准备工作一定是要放在前面的,这次的准备工作大家可以先看看大纲:

关于SSM框架的知识点

紫薇星上的SSM——浅谈MyBatis的使用

紫薇星上的SSM——浅谈Spring的使用

紫薇星上的SSM——浅谈SpringMVC的使用

紫薇星上的SSM——整合SSM框架

关于Vue的知识点

前后端分离:前导——后端程序员能看懂的VUE

前后端分离:必备——你不得不知道的那些事儿

准备

当你掌握了Vue-CLI、ElementUI、SSM框架、Axios后,就可以来着手准备实现前后端分离了,关于前后端分离的概念已经提过很多次了:前后端分离就是前端从后端中分离出来,由之前的JSP实现业务逻辑变成了前端后端各自编写业务逻辑,前端只需要将需要的数据从后端方面获取就行,而后端再也不用兼职美工切图,进行前端开发了,只需要将准备好的数据以JSON的格式发送给前端等待接收就好了。

前后端分离的好处除了提供了大量的前端岗位,这句划掉,让前端程序员更加有价值,后端程序员更加专注于自己的业务逻辑,同时前后端分离使得前端版本迭代再也不用和后端商量,只需要忙自己的就可以,唯一麻烦的就是定义接口,这是前端程序员和后端程序员日常争吵甩锅80%的原因。

在正式开始前后端分离人不分离的“全栈”开发前,你需要:

SSM框架整合能力、Tomcat的配置使用、Vue-CLI的使用能力、Bootstrap或ElementUI前端组件的使用、Node.js的使用(npm还是要会敲的)、至少一门数据库语言

掌握这些后,我们一起来看一下前后端分离的实现👇

1.前端实现

首先我们需要前端的界面,这个Demo实现了登录功能并且在登陆后可以显示登录者的USERNAME,功能很简单,我们现在画界面,首先建立一个新的Vue-CLI工程,工程目录如下:

这里router、views文件夹以及ststic目录下的data.json都是我们自己新建的,首先配置路由:

import Vue from 'vue'
import VueRouter from 'vue-router'

import Main from '../views/Main'
import Login from '../views/Login'

Vue.use(VueRouter);

export default new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/main',
      name: 'main',
      component: Main
    },
    {
      path: '/login',
      name: 'login',
      component: Login
    }
  ]
});

路由简单配置一下,传递参数我们使用params,所以在路由这里体现不出来,然后是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 router from './router/index'

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(router);
Vue.use(ElementUI);

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

在main.js中配置好路由后,紧随其后的APP.vue:

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>

APP.vue中只有一个<router-view>来显示页面,接下来是重头戏,Login.vue页面:

<template>
  <div>
    <el-form ref="loginForm" :model="form" :rules="rules" label-width="80px " class="login-box">
      <h3 class="login-title">欢迎登录</h3>
      <el-form-item label="账号" prop="username">
        <el-input type="text" placeholder="请输入账号" v-model="form.username"/>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" placeholder="请输入密码" v-model="form.password"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
      </el-form-item>
    </el-form>
 
    <el-dialog
      title="温馨提示"
      :visible.sync="dialogVisible"
      width="30%"
      :before-close="handleClose">
      <span>请输入账号和密码</span>
      <span slot="footer" class="dialog-footer">
          <el-button type="primary" @click="dialogVisible = false">确定</el-button>
        </span>
    </el-dialog>
  </div>
</template>
 
<script>
  export default {
    name: "Login",
    data() {
      return {
        form: {
          username: '',
          password: ''
        },
 
        //表单验证,需要在el-form-item元素中增加prop属性
        rules: {
          username: [
            {required: true, message: '账号不可为空', trigger: 'blur'}
          ],
          password: [
            {required: true, message: '密码不可为空', trigger: 'blur'}
          ]
        },
 
        //对话框显示和隐藏
        dialogVisible: false
      }
    },
 
    methods: {
      onSubmit(formName) {
        //为表单绑定验证功能
        this.$refs[formName].validate((vaild) => {
          if (vaild) {
            //使用vue-router 路由指导到指定页面,该方式称为编程式导航
            this.$router.push("/main");
          } else {
            this.dialogVisible = true;
            return false;
          }
        });
      }
    }
  }

</script>

<style lang="scss" scoped>
  .login-box {
    border: 1px solid #DCDFE6;
    width: 350px;
    margin: 180px auto;
    padding: 35px 35px 15px 35px;
    box-shadow: 1px 1px 15px 1px black;
  }

</style>

我们使用了ElementUI中的组件,进行了一点小小的改动,现在只要是输入内容就可以跳转:

然后是主页面:

<template>
  <div>
    <h1>首页</h1>
  </div>
</template>

<script>

    export default {
      name: "Main"
    }

</script>

<style scoped>

</style>

接下来进行后端页面的代码编写👇

2.后端实现

新建一个程序,这是目录:

这个结构就是紫薇星上的SSM——整合SSM框架中的架构,可以直接拿来用,我还是重新把代码贴一遍,讲解部分可以去文章中查看,首先是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>org.example</groupId>
    <artifactId>background-json</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.4</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>3.0-alpha-1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.0-M1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2.1-b03</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.71</version>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

    <!--配置JDK版本,必须配置!-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>9.0.4</maven.compiler.source>
        <maven.compiler.target>9.0.4</maven.compiler.target>
    </properties>

</project>

然后是web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


    <filter>
        <filter-name>encoding</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>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>
</web-app>

这时我们建立一个新的数据库,只存放两个属性:

然后是pojo类:

package com.test.pojo;

public class User {
    private String realUsername;
    private String realPassword;

    public User() {
    }

    public User(String realUsername, String realPassword) {
        this.realUsername = realUsername;
        this.realPassword = realPassword;
    }

    public String getRealUsername() {
        return realUsername;
    }

    public void setRealUsername(String realUsername) {
        this.realUsername = realUsername;
    }

    @Override
    public String toString() {
        return "User{" +
                "realUsername='" + realUsername + '\'' +
                ", realPassword='" + realPassword + '\'' +
                '}';
    }

    public String getRealPassword() {
        return realPassword;
    }

    public void setRealPassword(String realPassword) {
        this.realPassword = realPassword;
    }
}

mapper中我们只定义一个方法:

package com.test.mapper;

import com.test.pojo.User;

import java.util.List;

public interface UserMapper {
    public List<User> selectUsers();
}

然后配置mybatis-config.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <typeAliases>
        <package name="com.test.pojo"/>
    </typeAliases>

    <mappers>
        <mapper class="com.test.mapper.UserMapper"/>
    </mappers>

</configuration>

配置数据库连接文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/vue_ssm?useSSL=true&useUnicode=true&charsetEncoding=utf8
jdbc.username=#你的账号#
jdbc.password=#你的密码#

然后是整合spring和mybatis:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--关联数据库文件-->
    <context:property-placeholder location="classpath:database.properties"/>

    <!--<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource"></bean>-->
    <!--数据库连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!--c3p0私有属性-->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!--关闭连接后不自动commit-->
        <property name="autoCommitOnClose" value="false"/>
        <!--获取连接超时时间-->
        <property name="checkoutTimeout" value="10000"/>
        <!--连接失败重试次数-->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <!--SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--绑定Mybatis的配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <!--配置dao接口扫描包,动态实现dao接口注入到Spring中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--要扫描的dao包-->
        <property name="basePackage" value="com.test.mapper"/>
    </bean>

</beans>

UserMapper.xml实现sql:

<?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="com.test.mapper.UserMapper">
    <select id="selectUsers" resultType="User">
        select * from vue_ssm.user;
    </select>
</mapper>

接下来是service,同理只有一个方法:

package com.test.service;

import com.test.pojo.User;

import java.util.List;

public interface UserService {
    public List<User> selectUsers();
}

然后UserServiceImpl实现:

package com.test.service;

import com.test.mapper.UserMapper;
import com.test.pojo.User;

import java.util.List;

public class UserServiceImpl implements UserService{

    private UserMapper mapper;

    public UserServiceImpl() {
    }

    public UserServiceImpl(UserMapper mapper) {
        this.mapper = mapper;
    }

    public UserMapper getMapper() {
        return mapper;
    }

    @Override
    public String toString() {
        return "UserServiceImpl{" +
                "mapper=" + mapper +
                '}';
    }

    public void setMapper(UserMapper mapper) {
        this.mapper = mapper;
    }

    

    @Override
    public List<User> selectUsers() {
        return mapper.selectUsers();
    }
}

整合spring和service:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描Service下的包-->
    <context:component-scan base-package="com.test.service"/>
    <!--将业务类注入到Spring,通过注解或者配置-->
    <bean id="UserServiceImpl" class="com.test.service.UserServiceImpl">
        <property name="mapper" ref="userMapper"/>
    </bean>
    <!--声明式事务配置-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

然后是controller层,同样的只有一个方法:

package com.test.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.pojo.User;
import com.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {

    @Autowired
    @Qualifier("UserServiceImpl")
    private UserService userService;

    @RequestMapping("/selectUser")
    public String list() throws JsonProcessingException {
        List<User> list =userService.selectUsers();

        ObjectMapper toJson = new ObjectMapper();

        String json =toJson.writeValueAsString(list);

        return json;
    }
}

这里使用@RestController将返回值变为字符串而不是跳转,再来整合spring-mvc:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--扫描包-->
    <context:component-scan base-package="com.test.controller"/>
    <!--注解驱动-->
    <mvc:annotation-driven/>
    <!--静态资源过滤-->
    <mvc:default-servlet-handler/>
    <!--视图解析器-->
    <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">-->
    <!--    <property name="prefix" value="/WEB-INF/jsp/"/>-->
    <!--    <property name="suffix" value=".jsp"/>-->
    <!--</bean>-->

    <!--这一段是SpringMVC的自动处理乱码配置-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="utf-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

</beans>

最后将这些整合在applicationContext.xml中:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="classpath:spring-mapper.xml"/>
    <import resource="classpath:spring-service.xml"/>
    <import resource="classpath:spring-mvc.xml"/>

</beans>

这时我们配置Tomcat:

看一下是否可以输出:

没有问题,启动Tomcat先不要关闭,接下来准备连接前后端分离👇

3.进行连接

在编写后端代码的时候我们就要准备定义点后端分离的接口格式了,最终决定是传递一个数组对象,数组中包括多个User对象,每个对象有realUsername和realPassword两个属性,接下来需要对前端代码进行一点修改。

首先是Login.vue:

<template>
  <div>
    <el-form ref="loginForm" :model="form" label-width="80px " class="login-box">
      <h3 class="login-title">欢迎登录</h3>
      <el-form-item label="账号" prop="username">
        <el-input type="text" placeholder="请输入账号" v-model="form.username"/>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" placeholder="请输入密码" v-model="form.password"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onSubmit(form.username, form.password)">登录</el-button>
      </el-form-item>
    </el-form>

  </div>
</template>

<script>
  import axios from 'axios';
  export default {
    name: "Login",
    data(){
      return{
        form: {
          username: '',
          password: ''
        },
        json:[
          {
            realUsername: '',
            realPassword: ''
          }
        ]
      }
    },

    created() {
      axios.get('http://127.0.0.1:8080/selectUser').then(successResponse=>{
        this.json = successResponse.data;
      });
    },

    methods: {
      onSubmit(username, password) {
        var falg = false;
        for (let i = 0; i < this.json.length; i++) {
          if (username == this.json[i].realUsername && password == this.json[i].realPassword) {
            this.$router.push({
              path: '/main',
              name: 'main',
              params: {
                name: username
              }
            });
            falg = true;
          }
        }
        if (falg === false){
          alert("失败!");
          return false;
        }
      }
    }
  }

</script>

<style lang="scss" scoped>
  .login-box {
    border: 1px solid #DCDFE6;
    width: 350px;
    margin: 180px auto;
    padding: 35px 35px 15px 35px;
    box-shadow: 1px 1px 15px 1px black;
  }

</style>

主要增加了created钩子函数,在data和methods刚初始化好就进行数据的异步加载,加载的url为本机的8080端口下的selectUser路径,与刚才检测JSON返回值的路径是一个,这样才能拿到需要的数据;

为了避免冲突,从表单中获取的数据为username和password,从后端获取的数据为realUsername和realPassword,这样就可以区分并进行下一步操作;

因为传过来的数据是数组,所以methods中对于数组进行循环遍历,判断是否为数据库中正确的数据,然后返回;

上面我们说到视图跳转传递参数用的是params,没有用router-link和query,这三种方法都可以,但是都有需要注意的点,通过动态路由router-link来传:

//路由配置文件中 配置动态路由
{
     path: '/detail/:id',
     name: 'Detail',
     component: Detail
   }
//跳转时页面
var id = 1;
this.$router.push('/detail/' + id)
 
//跳转后页面获取参数
this.$route.params.id

需要注意得是:

  • to前面一定要加 : ,一定要记得加!记得加!加!
  • to后面 { 中的name值(这里是userid)要与路由中的name值一致

通过query来传:

//路由配置文件中
{
     path: '/detail',
     name: 'Detail',
     component: Detail
   }
//跳转时页面
this.$router.push({
  path: '/detail',
  query: {
    name: '张三',
    id: 1,
  }
})
 
//跳转后页面获取参数对象
this.$route.query 

 需要注意的是:

  • 路由配置中不用配置参数
  • 传输的值会在url后面以参数的形式显示出来,刷新页面数据不变

通过params来传:

//路由配置文件中
{
     path: '/detail',
     name: 'Detail',
     component: Detail
   }
//跳转时页面
this.$router.push({
  name: 'Detail',
  params: {
    name: '张三',
    id: 1,
  }
})
 
//跳转后页面获取参数对象
this.$route.params 

需要注意的是:

  • 跳转时页面除了path和params外,必须要有name属性
  • 传输的值不会显示,刷新页面数据会发生改变

然后我们修改Main.vue页面:

<template>
  <div>
    <h1>首页</h1>
    <span>{{username}}</span>
  </div>
</template>

<script>

    export default {
      name: "Main",
      data(){
        return{
          username: this.$route.params.name
        }
      }
    }

</script>

<style scoped>

</style>

通过params获取数据并赋值给页面,这时我们就可以进行测试了,但是,一般人都会遇到第一个问题:页面加载不出来,这是因为端口没有修改,前端的页面要和后端的页面不同,如果不修改则都是8080,就会报错;

修改后大家就会遇到第二个问题:跨域!一般来说,会使用过滤器或拦截器来进行跨域请求的处理,但是在springMVC4.2版本之后,使用注解@CrossOrigin就可以解决跨域问题,在后端代码UserController中修改:

package com.test.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.pojo.User;
import com.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {

    @Autowired
    @Qualifier("UserServiceImpl")
    private UserService userService;

    @RequestMapping("/selectUser")
    @CrossOrigin
    public String list() throws JsonProcessingException {
        List<User> list =userService.selectUsers();

        ObjectMapper toJson = new ObjectMapper();

        String json =toJson.writeValueAsString(list);

        return json;
    }
}

如果注解放在类上,此类中所有方法启用跨域支持,如果放在方法上,仅此方法启用跨域支持。如果发现注解不起作用,那么要注意是springMVC的版本要在4.2或以上版本才支持@CrossOrigin,在Controller注解上方添加@CrossOrigin注解后,仍然出现跨域问题,解决方案之一就是:在@RequestMapping注解中没有指定Get、Post方式,具体指定后问题解决。

解决了跨域问题我们来看一下最终效果👇

4.最终效果


简单的前后端分离效果就通过这个Demo来实现啦,一通百通的你应该对如何进行一个前后端分离的项目有点数了,继续保持学习,向着“全栈”进发!我们下次见👋

  • 11
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值