springdatajpa+vue实现省市区三级联动
一,编写后端代码
1、创建springboot项目,添加 web、jpa、lombok、mysql、jdbc 启动器,加载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 https://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.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xkxx</groupId>
<artifactId>china</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>china</name>
<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-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、在resources下,将application.properties文件后缀改成.yml
server:
port: 8888
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/china?useSSL=false&serverTimezone=GMT%2B8
username: root
password: sasa
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
database: mysql
hibernate:
ddl-auto: update
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
main:
allow-bean-definition-overriding: true
3、编写省,市,区的实体(idea使用了lombok插件),SQL等项目文件文末自取
省份实体类:Province.java
@Data
@Entity
@Table(name = "t_address_province")
public class Province {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id",unique = true,nullable = false,length = 50)
private Integer id;
@Column(name = "code",nullable = false,length = 50)
private String code;
@Column(name = "name",nullable = false,length = 50)
private String name;
}
城市实体类:City.java
@Data
@Entity
@Table(name = "t_address_city")
public class City {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id",unique = true,nullable = false,length = 50)
private Integer id;
@Column(name = "code",nullable = false,length = 50)
private String code;
@Column(name = "name",nullable = false,length = 50)
private String name;
@Column(name = "provincecode",nullable = false,length = 50)
private String provinceCode;
}
区域实体类:Town.java
@Data
@Entity
@Table(name ="t_address_town")
public class Town {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id",unique = true,nullable = false,length = 50)
private Integer id;
@Column(name = "code",nullable = false,length = 50)
private String code;
@Column(name = "name",nullable = false,length = 50)
private String name;
@Column(name = "citycode",nullable = false,length = 50)
private String cityCode;
}
4、编写dao
package com.xkxx.china.dao;
import com.xkxx.china.entity.City;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CityDao extends JpaRepository<City,Integer> {
}
package com.xkxx.china.dao;
import com.xkxx.china.entity.Province;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProvinceDao extends JpaRepository<Province,Integer> {
}
package com.xkxx.china.dao;
import com.xkxx.china.entity.Town;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TownDao extends JpaRepository<Town,Integer> {
}
5、编写service,调用dao接口方法,返回信息
package com.xkxx.china.service;
import com.xkxx.china.dao.CityDao;
import com.xkxx.china.entity.City;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
@Service
@Transactional
public class CityService {
@Autowired
private CityDao cityDao;
public List<City> findAllCity(){
return cityDao.findAll();
}
}
package com.xkxx.china.service;
import com.xkxx.china.dao.ProvinceDao;
import com.xkxx.china.entity.Province;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
@Service
@Transactional
public class ProvinceService {
@Autowired
private ProvinceDao provinceDao;
public List<Province> findAllProvince(){
return provinceDao.findAll();
}
}
package com.xkxx.china.service;
import com.xkxx.china.dao.TownDao;
import com.xkxx.china.entity.Town;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.List;
@Service
@Transactional
public class TownService {
@Autowired
private TownDao townDao;
public List<Town> findAllTown(){
return townDao.findAll();
}
}
6、编写web,调用service方法,编写省,市,区各个接口
package com.xkxx.china.web;
import com.xkxx.china.entity.City;
import com.xkxx.china.entity.Province;
import com.xkxx.china.entity.Town;
import com.xkxx.china.service.CityService;
import com.xkxx.china.service.ProvinceService;
import com.xkxx.china.service.TownService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class ChinaController {
@Autowired
private ProvinceService provinceService;
@Autowired
private CityService cityService;
@Autowired
private TownService townService;
/**
* 查询所有身份信息
* @return
*/
@GetMapping("province")
public List<Province> findAllProvince(){
return provinceService.findAllProvince();
}
/**
* 根据省份编号查询市级信息
* @param provinceCode
* @return
*/
@GetMapping("city/{provinceCode}")
public List<City> findAllProvince(@PathVariable("provinceCode") String provinceCode){
return cityService.findAllCity();
}
/**
* 根据市级编号查询区域信息
* @param cityCode
* @return
*/
@GetMapping("town/{cityCode}")
public List<Town> findAllTown(@PathVariable("cityCode") String cityCode){
return townService.findAllTown();
}
}
7、编写CorsConfig类进行前后端分离跨域请求
package com.xkxx.china.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
// 初始化 CorsConfiguration 对象并设置允许的域名、请求头部信息和请求方式
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1 允许任何域名使用
corsConfiguration.addAllowedHeader("*"); // 2 允许任何头
corsConfiguration.addAllowedMethod("*"); // 3 允许任何方法(post、get 等)
return corsConfiguration;
}
/**
* 创建 CorsFilter 对象
* @return CorsFilter
*/
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); //拦截所有请求
return new CorsFilter(source);
}
}
8、后端最终样式
二,前端VUE+ELEMENT
1、创建vue项目(如何创建vue项目?)
2、安装 axios 插件,在当前项目下的终端输入命令: npm install --save axios vue-axios
安装 Element 插件,在当前项目下的终端输入命令:npm i element-ui -S
3、在 src 文件夹下的程序入口 main.js 中导入
import axios from 'axios'
import VueAxios from 'vue-axios'
// element-ui 引入文件
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
//注册 VueAxios, axios
Vue.use(VueAxios, axios)
Vue.use(ElementUI)
4、创建vue文件,编写代码(下面有详细解析)
<template>
<div>
<el-select v-model="provinceCode" placeholder="省份">
<el-option
v-for="item in AddressProvince"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select v-model="cityCode" placeholder="城市">
<el-option
v-for="item in AddressCity"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select v-model="value" placeholder="区域">
<el-option
v-for="item in AddressTown"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
</div>
</template>
<script>
const axios = require("axios");
export default {
name: 'HelloWorld',
data () {
return {
AddressCity: [],
AddressProvince: [],
AddressTown: [],
provinceCode: '',
cityCode: '',
value: ''
}
},
watch: {//监控一个值的变换
provinceCode: { //
handler () {
this.AddressCity = [];
this.AddressTown = [];
this.cityCode = "";
this.value = "";
this.findByprovinceCode();
}
},
cityCode: {//
handler () {
this.findBycityCode();
}
}
},
created () {
this.init();
},
methods: {
handleChange (value) {
console.log(value);
},
init () {
var app = this;
axios.get("http://localhost:8888/province").then(resp => {
// handle success
app.AddressProvince = resp.data;
})
.catch(function (error) {
// handle error
console.log(error);
});
},
findByprovinceCode () {
var app = this;
axios.get("http://localhost:8888/city/" + app.provinceCode).then(resp => {
// handle success
app.AddressCity = resp.data;
})
.catch(function (error) {
// handle error
console.log(error);
});
},
findBycityCode () {
var app = this;
axios.get("http://localhost:8888/town/" + app.cityCode).then(resp => {
// handle success
// app.provinceCode = '';
// app.cityCode = '';
app.AddressTown = resp.data;
})
.catch(function (error) {
// handle error
console.log(error);
});
},
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
4_1、使用element下拉组件,编写三级下拉框,具体参数示例可参考Element官网介绍
<template>
<div>
<el-select v-model="provinceCode" placeholder="省份">
<el-option
v-for="item in AddressProvince"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select v-model="cityCode" placeholder="城市">
<el-option
v-for="item in AddressCity"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select v-model="value" placeholder="区域">
<el-option
v-for="item in AddressTown"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
</div>
</template>
4_2、上方页面使用了vue.js的v-model和v-for绑定了下方data
data () {
return {
AddressProvince: [],//省份集合
AddressCity: [],//城市集合
AddressTown: [],//区域集合
provinceCode: '',//获取选中时的省份编号
cityCode: '',//获取选中时的城市编号
value: ''}//获取选中时区域的编号
4_3、在methods中编写加载init方法
init () {
var app = this;
axios.get("http://localhost:8888/province").then(resp => {
// handle success
app.AddressProvince = resp.data;//绑定到省份集合
})
.catch(function (error) {
// handle error
console.log(error);
});
}
4_4、在methods在编写,查询城市 和查询区域 方法
//查询城市信息
findByprovinceCode () {
var app = this;
axios.get("http://localhost:8888/city/" + app.provinceCode).then(resp => {
app.AddressCity = resp.data;
})
.catch(function (error) {
console.log(error);
});
},
//查询区域信息
findBycityCode () {
var app = this;
axios.get("http://localhost:8888/town/" + app.cityCode).then(resp => {
app.AddressTown = resp.data;
})
.catch(function (error) {
console.log(error);
});
}
4_5、在created中调用init方法,实现初始化请求,使页面加载时查询省份信息,并绑定到AddressProvince 省份集合中,使省份下拉框具有初始值
created () {
this.init();
},
4_6、在watch中编写监控省份和城市编号的方法,实现当选中省份使provinceCode值发生变化时,触发对应方法查询城市信息,区域同上
watch: {//监控一个值的变换
provinceCode: { //
handler () {
//在选中省份发生变化时,清空后方城市和区域集合的值,和绑定编号的值,
//重新查询对应选中编号的城市和区域值
this.AddressCity = [];
this.AddressTown = [];
this.cityCode = "";
this.value = "";
this.findByprovinceCode();
}
},
cityCode: {
handler () {
this.findBycityCode();
}
}
}
5、运行springboot、vue即可,效果如下