• 前端:vue + spa + axios
  • 后端:spring cloud + nacos + gateway + ssm+

1.环境搭建

1.0 数据库

#学生数据库
CREATE DATABASE nacos_ssm_student;
USE nacos_ssm_student;CREATE TABLE tb_city(c_id VARCHAR(32) PRIMARY KEY COMMENT '城市ID',city_name VARCHAR(20) COMMENT '城市名称' ,parent_id VARCHAR(32) COMMENT '父ID'
);INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('320000','江苏省','0');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('140000','山西省','0');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('130000','河北省','0');INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('320100','南京市','320000');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('320102','玄武区','320100');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('320103','白下区','320100');INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('321300','宿迁市','320000');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('321322','沭阳县','321300');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('321323','泗阳县','321300');INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('140100','太原市','140000');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('140106','迎泽区','140100');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('140108','尖草坪区','140100');INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('140800','运城市','140000');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('140823','闻喜县','140800');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('140828','夏 县','140800');INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('130100','石家庄市','130000');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('130127','高邑县','130100');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('130185','鹿泉市','130100');INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('131000','廊坊市','130000');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('131003','广阳区','131000');
INSERT INTO tb_city(c_id,city_name,parent_id) VALUES('131022','固安县','131000');CREATE TABLE `tb_student` (`s_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学生ID',`sname` VARCHAR(50) DEFAULT NULL COMMENT '姓名',`age` INT(11) DEFAULT NULL COMMENT '年龄',`birthday` DATETIME DEFAULT NULL COMMENT '生日',`gender` CHAR(1) DEFAULT NULL COMMENT '性别',`c_id` INT DEFAULT NULL,`city_ids` VARCHAR(32) DEFAULT NULL COMMENT '城市:320000,321300,321322'
);INSERT  INTO `tb_student`(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`,`city_ids`) VALUES (1,'赵三33',21,'2001-01-17 00:00:00','1',1,'320000,321300,321322');
INSERT  INTO `tb_student`(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`,`city_ids`) VALUES (2,'钱四444',1900,'2001-05-16 00:00:00','1',2,'320000,321300,321322');
INSERT  INTO `tb_student`(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`,`city_ids`) VALUES (3,'孙五56',189,'2022-03-15 00:00:00','0',1,'320000,321300,321322');
INSERT  INTO `tb_student`(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`,`city_ids`) VALUES (4,'张三',20,'2020-12-21 00:00:00','0',2,'320000,321300,321322');
INSERT  INTO `tb_student`(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`,`city_ids`) VALUES (5,'xxx',18,'2020-12-21 00:00:00','0',2,'140000,140800,140823');
INSERT  INTO `tb_student`(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`,`city_ids`) VALUES (6,'123',18,'2020-11-01 00:00:00','0',3,'130000,130100,130127');
INSERT  INTO `tb_student`(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`,`city_ids`) VALUES (7,'xx',18,'2020-11-02 00:00:00','0',1,'130000,131000,131003');

1.1 后端环境

1.1.1 父项目

  • 坐标

        <!-- 1 确定spring boot的版本--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version></parent><!--2  确定版本--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version><spring-cloud-release.version>Hoxton.SR3</spring-cloud-release.version><nacos.version>1.1.0</nacos.version><alibaba.cloud.version>2.2.1.RELEASE</alibaba.cloud.version><mybatis.starter.version>1.3.2</mybatis.starter.version><mapper.starter.version>2.0.2</mapper.starter.version><mysql.version>5.1.32</mysql.version><pageHelper.starter.version>1.2.5</pageHelper.starter.version><durid.starter.version>1.1.10</durid.starter.version><swagger.version>2.7.0</swagger.version><jwt.jjwt.version>0.9.0</jwt.jjwt.version><jwt.joda.version>2.9.7</jwt.joda.version><beanutils.version>1.9.3</beanutils.version><student.version>1.0-SNAPSHOT</student.version></properties><!-- 3 锁定版本--><dependencyManagement><dependencies><!-- sprig cloud--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud-release.version}</version><type>pom</type><scope>import</scope></dependency><!--nacos --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>${nacos.version}</version></dependency><!--nacos cloud 发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${alibaba.cloud.version}</version></dependency><!--nacos cloud 配置 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${alibaba.cloud.version}</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>${alibaba.cloud.version}</version></dependency><!-- mybatis plus启动器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-annotation</artifactId><version>3.4.0</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!-- Druid连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${durid.starter.version}</version></dependency><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>${swagger.version}</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>${swagger.version}</version></dependency><!--jwt--><!--JavaBean工具类,用于JavaBean数据封装--><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>${beanutils.version}</version></dependency><!--jwt工具--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>${jwt.jjwt.version}</version></dependency><!--joda 时间工具类 --><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>${jwt.joda.version}</version></dependency><!-- 自定义项目 --><dependency><groupId>com.czxy</groupId><artifactId>nacos-ssm-fx-domain-bg12</artifactId><version>${student.version}</version></dependency></dependencies></dependencyManagement>

1.1.2 domain项目

  • 坐标

        <dependencies><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--jackson--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-annotation</artifactId></dependency></dependencies>
    
  • JavaBean

    package com.czxy.domain;import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import lombok.Data;import java.util.Date;@TableName("tb_student")
    @Data
    public class Student {@TableId("s_id")private Integer sid;@TableField("sname")private String sname;@TableField("age")private Integer age;@TableField("birthday")@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")private Date birthday;@TableField("gender")private String gender;@TableField("c_id")private Integer cid;@TableField("city_ids")private String cityIds;}/*
    CREATE TABLE `tb_student` (`s_id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学生ID',`sname` VARCHAR(50) DEFAULT NULL COMMENT '姓名',`age` INT(11) DEFAULT NULL COMMENT '年龄',`birthday` DATETIME DEFAULT NULL COMMENT '生日',`gender` CHAR(1) DEFAULT NULL COMMENT '性别',`c_id` INT DEFAULT NULL,`city_ids` VARCHAR(32) DEFAULT NULL COMMENT '城市:320000,321300,321322'
    );*/
    
  • 拷贝:BaseResult

    package com.czxy.vo;import lombok.Getter;import java.util.HashMap;
    import java.util.Map;@Getter
    public class BaseResult<T> {//成功状态码public static final int OK = 20000;//失败状态码public static final int ERROR = 0;//返回码private Integer code;//返回消息private String message;//存放数据private T data;//其他数据private Map<String,Object> other = new HashMap<>();public BaseResult() {}public BaseResult(Integer code, String message) {this.code = code;this.message = message;}public BaseResult(Integer code, String message, T data) {this.code = code;this.message = message;this.data = data;}/*** 快捷成功BaseResult对象* @param message* @return*/public static BaseResult ok(String message){return new BaseResult(BaseResult.OK , message);}public static BaseResult ok(String message, Object data){return new BaseResult(BaseResult.OK , message, data );}/*** 快捷失败BaseResult对象* @param message* @return*/public static BaseResult error(String message){return new BaseResult(BaseResult.ERROR , message);}/*** 自定义数据区域* @param key* @param msg* @return*/public BaseResult append(String key , Object msg){other.put(key , msg);return this;}//    public Integer getCode() {//        return code;
    //    }
    //
    //    public String getMessage() {//        return message;
    //    }
    //
    //    public T getData() {//        return data;
    //    }
    //
    //    public Map<String, Object> getOther() {//        return other;
    //    }
    }
    

1.1.3 网关gateway

  • 坐标

        <dependencies><!-- 网关 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- nacos 服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--JavaBean工具类,用于JavaBean数据封装--><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId></dependency><!--jwt工具--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency><!--joda 时间工具类 --><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId></dependency></dependencies>
    
  • yml配置文件:application.yml

    #端口号
    server:port: 10010
    spring:application:name: student-gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848   #nacos服务地址gateway:discovery:locator:enabled: true               #开启服务注册和发现的功能,自动创建router以服务名开头的请求路径转发到对应的服务lowerCaseServiceId: true    #将请求路径上的服务名配置为小写
  • 启动类

    package com.czxy;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication
    @EnableDiscoveryClient  //服务发现
    public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class,args);}
    }
  • 跨域配置类:config/GlobalGatewayCorsConfig.java

    package com.czxy.config;import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.web.cors.reactive.CorsUtils;
    import org.springframework.web.server.ServerWebExchange;
    import org.springframework.web.server.WebFilter;
    import org.springframework.web.server.WebFilterChain;
    import reactor.core.publisher.Mono;@Configuration
    public class GlobalGatewayCorsConfig {@Beanpublic WebFilter corsFilter2() {return (ServerWebExchange ctx, WebFilterChain chain) -> {ServerHttpRequest request = ctx.getRequest();if (CorsUtils.isCorsRequest(request)) {HttpHeaders requestHeaders = request.getHeaders();ServerHttpResponse response = ctx.getResponse();HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();HttpHeaders headers = response.getHeaders();headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,requestHeaders.getAccessControlRequestHeaders());if (requestMethod != null) {headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());}headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");if (request.getMethod() == HttpMethod.OPTIONS) {response.setStatusCode(HttpStatus.OK);return Mono.empty();}}return chain.filter(ctx);};}}

1.1.4 学生服务

  • 坐标

        <dependencies><!--web起步依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- nacos 客户端 --><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId></dependency><!-- nacos 服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- mybatis plus启动器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- Druid连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId></dependency><!-- feign 远程调用 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- 自定义项目 --><dependency><groupId>com.czxy</groupId><artifactId>nacos-ssm-fx-domain-bg12</artifactId></dependency></dependencies>
  • yml配置文件

    #端口号
    server:port: 9001spring:application:name: student-plus-service          #服务名datasource:driverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/nacos_ssm_student?useUnicode=true&characterEncoding=utf8username: rootpassword: 1234druid:    #druid 连接池配置initial-size: 1       #初始化连接池大小min-idle: 1           #最小连接数max-active: 20        #最大连接数test-on-borrow: true  #获取连接时候验证,会影响性能cloud:nacos:discovery:server-addr: 127.0.0.1:8848   #nacos服务地址sentinel:transport:dashboard: 127.0.0.1:8080
    
  • 启动类

    package com.czxy;import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;@SpringBootApplication
    @EnableDiscoveryClient
    public class StudentServiceApplication {public static void main(String[] args) {SpringApplication.run(StudentServiceApplication.class,args);}
    }
  • 配置类:config/Swagger2ConfigurationV3.java

    package com.czxy.config;import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.*;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spi.service.contexts.SecurityContext;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.ArrayList;
    import java.util.List;/*** Swagger2 配置类,* 访问路径:swagger-ui.html* 自动注册:*     位置:resources/META-INF/spring.factories*     内容:*        org.springframework.boot.autoconfigure.EnableAutoConfiguration=\*          com.czxy.config.Swagger2Configuration*/
    @Configuration
    @EnableSwagger2
    public class Swagger2ConfigurationV3 {@Beanpublic Docket createRestApi() {// 1 确定文档Swagger版本Docket docket = new Docket(DocumentationType.SWAGGER_2);// 2 设置 api基本信息docket.apiInfo(apiInfo());// 3 设置自定义加载路径docket = docket.select().apis(RequestHandlerSelectors.basePackage("com.czxy")).paths(PathSelectors.any()).build();//4 设置权限docket.securitySchemes(securitySchemes());docket.securityContexts(securityContexts());return docket;}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("API").description("基于swagger接口文档").contact(new Contact("梁桐","http://www.javaliang.com","liangtong@itcast.cn")).version("1.0").build();}private List<ApiKey> securitySchemes() {List<ApiKey> list = new ArrayList<>();// name 为参数名  keyname是页面传值显示的 keyname, name在swagger鉴权中使用list.add(new ApiKey("Authorization", "Authorization", "header"));return list;}private List<SecurityContext> securityContexts() {List<SecurityContext> list = new ArrayList<>();list.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("^(?!auth).*$")).build());return list;}private List<SecurityReference> defaultAuth() {AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;List<SecurityReference> list = new ArrayList();list.add(new SecurityReference("Authorization", authorizationScopes));return list;}}

1.2 前端环境

1.2.1 创建项目:

vue create nacos-fx-spa-bg12

1.2.2 整合axios

  • 下载axios

    cnpm install axios --save
    
  • 抽取工具 request.js

    npm i element-ui --save
    

    src/utils/request.js

    import axios from 'axios'
    import { MessageBox, Message } from 'element-ui'// 方式1:设置基本路径
    // axios.defaults.baseURL='http://localhost:10010/api'// 方式2:create an axios instance,并设置基本路径
    const service = axios.create({baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url// withCredentials: true, // send cookies when cross-domain requeststimeout: 5000 // request timeout
    })// request interceptor
    service.interceptors.request.use(config => {// 请求头中追加tokenlet token = localStorage.getItem('token')if (token) {config.headers.Authorization = token}return config},error => {// do something with request errorconsole.log(error) // for debugreturn Promise.reject(error)}
    )// response interceptor
    service.interceptors.response.use(response => {const res = response.data// if the custom code is not 20000, it is judged as an error.if (res.code !== 20000) {Message({message: res.message || 'Error',type: 'error',duration: 5 * 1000})// ajax异常提示信息 (路径信息,数据)console.info(response.config, response.data )return Promise.reject(new Error(res.message || 'Error'))} else {return res}},error => {console.log('err' + error) // for debugif(error.response.status == 401) {MessageBox.confirm(error.response.data, '重新登录确认框', {confirmButtonText: '重新登录',cancelButtonText: '取消',type: 'warning'}).then(() => {// 删除tokenlocalStorage.removeItem('token')location.reload()})} else {Message({message: error.message,type: 'error',duration: 5 * 1000})}return Promise.reject(error)}
    )export default service
  • 抽取api:

    • 将ajax抽取到一个student.js文件中,student.js调用request.js(使用增强后的axios)

      // 导入工具 request.js
      import axios from '@/utils/request.js'// 编写功能方法
      export function selectAll() {return axios.get('/student-plus-service/student')
      }
      
    • request.js ajax访问路径的前缀baseURL,抽取到配置文件中 .env.development

~~~
# just a flag
ENV = 'development'# base api
VUE_APP_BASE_API = 'http://localhost:10010/'
~~~

2. 学生管理

2.1 查询所有的学生

2.1.1 后端

  • 步骤:

    • 步骤1:编写mapper,通用mapper
    • 步骤2:编写service,通用service 接口 + 实现类
    • 步骤3:编写controller
  • 步骤1:编写mapper,通用mapper

    package com.czxy.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.czxy.domain.Student;
    import org.apache.ibatis.annotations.Mapper;@Mapper
    public interface StudentMapper extends BaseMapper<Student> {}
  • 步骤2:编写service,通用service 接口 + 实现类

    • 接口

      package com.czxy.service;import com.baomidou.mybatisplus.extension.service.IService;
      import com.czxy.domain.Student;public interface StudentService extends IService<Student> {}
    • 实现类

      package com.czxy.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import com.czxy.domain.Student;
      import com.czxy.mapper.StudentMapper;
      import com.czxy.service.StudentService;
      import org.springframework.stereotype.Service;
      import org.springframework.transaction.annotation.Transactional;@Service
      @Transactional
      public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {}
  • 步骤3:编写controller, GET请求 + BaseResult

    package com.czxy.controller;import com.czxy.domain.Student;
    import com.czxy.service.StudentService;
    import com.czxy.vo.BaseResult;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
    import java.util.List;@RestController
    @RequestMapping("/student")
    public class StudentController {@Resourceprivate StudentService studentService;@GetMappingpublic BaseResult selectAll() {// 1.请求数据// 2 查询List<Student> list = studentService.list();// 3 响应结果return BaseResult.ok("查询成功", list);/*BaesResult baseResult = new BaseResult();baseResult.setCode(20000);          //自定义编码baseResult.setMessage("查询成功");  //提示信息baseResult.setData( list );         //结果数据*/}
    }

2.1.2 前端

1)访问页面

  • 步骤1:修改App.vue页面,确定访问路径

    <template><div id="app"><!-- 导航条,切换路由 --><div id="nav"><router-link to="/">Home</router-link> |<router-link to="/studentList">学生列表</router-link></div><!-- 路由视图,用于显示内容 --><router-view/></div>
    </template><style></style>
  • 步骤2:修改路由 src/router/index.js 编写访问路径

    import Home from '../views/Home.vue'
    const routes = [{path: '/',name: 'Home',component: Home},{path: '/studentList',name: '学生列表',component: () => import('../views/StudentList.vue')}
    ]
    
  • 步骤3:创建StudentList.vue页面

    <template><div>学生列表页面</div>
    </template><script>
    export default {}
    </script><style></style>
    

2)显示查询结果

  • 步骤:

    • 步骤1:导入api,获得查询所有函数
    • 步骤2:编写查询所有学生函数,调用导入api函数,完成ajax操作,查询结果保存studentList
    • 步骤3:页面加载成功后,查询
    • 步骤4:遍历展示
<template><div><!-- 4 展示数据 --><table border="1"><tr><td>编号</td><td>姓名</td><td>年龄</td><td>生日</td><td>性别</td><td>班级</td><td>操作</td></tr><tr v-for="(student,index) in studentList" :key="index"><td>{{student.sid}}</td><td>{{student.sname}}</td><td>{{student.age}}</td><td>{{student.birthday}}</td><td>{{student.gender == 1 ? '男' : '女'}}</td><td>{{student.cid}}</td><td>修改删除</td></tr></table></div>
</template><script>
//1 导入查询函数
import {selectAll} from '../api/student'
export default {data() {return {studentList: []}},methods: {async selectAllStudent() {  //2 ajax查询 -- request.js 中对响应结果response进行再处理,返回的是 response.datalet {data} = await selectAll()   // {data} 从 baseResult中结果data,也就是查询结果// 将查询结果保存数据区域this.studentList = data}},  mounted() {// 3 页面加载成功,查询所有this.selectAllStudent()},
}
</script><style></style>

2.2 条件查询 + 分页

2.2.1 后端步骤

  • 确定访问路径

    http://localhost:10010/student-plus-service/student/condition/{size}/{current}
    
  • 步骤1:准备条件封装StudentVo

  • 步骤2:编写controller,获得分页参数+条件,返回 Page进行结果封装

  • 步骤3:编写service

    • 1)查询条件
    • 2)分页
    • 3)查询
    • 4)关联
    • 5)处理/返回结果
  • 步骤4:拷贝MyBatisPlus分页配置类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pEssSDxP-1645576553138)(assets/image-20220222150608792.png)]

2.2.2 后端实现

  • 步骤1:准备条件封装StudentVo

    package com.czxy.vo;import lombok.Data;@Data
    public class StudentVo {private String cid;private String sname;private String startAge;private String endAge;
    }
  • 步骤2:编写controller,获得分页参数+条件,返回 Page进行结果封装

        /**** @param studentVo 条件* @param size 每页个数* @param current 第几页* @return*/@PostMapping("/condtion/{size}/{current}")public BaseResult condition(@RequestBody StudentVo studentVo,@PathVariable("size") Integer size,@PathVariable("current") Integer current){// 2 查询Page<Student> page = studentService.condition(studentVo,size,current);// 3 返回return BaseResult.ok("查询成功", page);}
  • 步骤3:编写service

    • 接口

      package com.czxy.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
      import com.baomidou.mybatisplus.extension.service.IService;
      import com.czxy.domain.Student;
      import com.czxy.vo.StudentVo;public interface StudentService extends IService<Student> {/*** 分页 + 条件 查询* @param studentVo* @param size* @param current* @return*/Page<Student> condition(StudentVo studentVo, Integer size, Integer current);
      }
    • 实现类

          @Overridepublic Page<Student> condition(StudentVo studentVo, Integer size, Integer current) {//1 条件QueryWrapper<Student> queryWrapper = new QueryWrapper<>();// 1.1 班级queryWrapper.eq(StringUtils.isNotBlank(studentVo.getCid()), "c_id", studentVo.getCid());// 1.2 姓名 - like %张%queryWrapper.like(StringUtils.isNotBlank(studentVo.getSname()),"sname", studentVo.getSname());// 1.3 开始年龄queryWrapper.ge(StringUtils.isNotBlank(studentVo.getStartAge()),"age", studentVo.getStartAge());// 1.4 结束年龄queryWrapper.le(StringUtils.isNotBlank(studentVo.getEndAge()),"age", studentVo.getEndAge());// 2 分页Page page = new Page(current, size);// 3 查询this.baseMapper.selectPage(page, queryWrapper);//TODO 4 关联--查询班级// 5 返回return page;}
      
  • 步骤4:拷贝MyBatisPlus分页配置类

    package com.czxy.config;import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;@Configuration
    public class MybatisPlusConfig {/*** 配置插件* @return*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();// 分页插件mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}
    }

2.2.3 前端步骤

  • 步骤1:编写页面 StudentCondition.vue + 路由
  • 步骤2:编写ajax student.js 写 condition函数
  • 步骤3:修改StudentCondition.vue
    • 基本查询:page、studentVo
    • 条件查询
    • 分页查询

2.2.4 前端实现

  • 步骤1:编写页面 StudentCondition.vue + 路由

  • 步骤2:编写ajax student.js 写 condition函数

// 查询所有学生+条件+分页
export function condition(page,studentVo) {var url = `/student-plus-service/student/condtion/${page.size}/${page.current}`return axios.post(url, studentVo)
}
  • 步骤3:修改StudentCondition.vue

    • 基本查询:page、studentVo

      <template><div><!-- 列表展示 --><table border="1"><tr><td>编号</td><td>姓名</td><td>年龄</td><td>生日</td><td>性别</td><td>班级</td><td>操作</td></tr><tr v-for="(student,index) in page.records" :key="index"><td>{{student.sid}}</td><td>{{student.sname}}</td><td>{{student.age}}</td><td>{{student.birthday}}</td><td>{{student.gender == 1 ? '男' : '女'}}</td><td>{{student.cid}}</td><td>修改删除</td></tr></table></div>
      </template><script>
      // 导入ajax函数
      import {condition} from '../api/student'
      export default {data() {return {page: {     //分页size: 3,current: 1},studentVo: {  //条件cid: '',sname: '',startAge: '',endAge: '',}}},methods: {async conditionFn(num) {// 设置第几页if(num) {this.page.current = num}// ajax查询let { data } = await condition(this.page, this.studentVo)// 获得结果this.page = data}},mounted() {// 查询第一页this.conditionFn(1)},
      }
      </script><style></style>
      
    • 条件查询:(使用模拟数据显示班级列表)

            classesList: [ //班级的模拟数据{cid:1, cname: 'Java56'},{cid:2, cname: 'Java78'},{cid:3, cname: 'Java12'},{cid:4, cname: 'Java34'},]
      
          <!-- 条件查询表单 -->班级 <select v-model="studentVo.cid"><option value="">--选择班级--</option><option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option></select>姓名:<input type="text" size="8" v-model="studentVo.sname"/>年龄:<input type="text" size="8" v-model="studentVo.startAge"/> -- <input type="text" size="8" v-model="studentVo.endAge"/><input type="button" value="查询" @click="conditionFn(1)" />
      
      <!--条件查询的完整版-->
      <template><div><!-- 条件查询 -->班级 <select v-model="studentVo.cid"><option value="">--选择班级--</option><option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option></select>姓名:<input type="text" size="8" v-model="studentVo.sname"/>年龄:<input type="text" size="8" v-model="studentVo.startAge"/> -- <input type="text" size="8" v-model="studentVo.endAge"/><input type="button" value="查询" @click="conditionFn(1)" /><!-- 列表展示 --><table border="1"><tr><td>编号</td><td>姓名</td><td>年龄</td><td>生日</td><td>性别</td><td>班级</td><td>操作</td></tr><tr v-for="(student,index) in page.records" :key="index"><td>{{student.sid}}</td><td>{{student.sname}}</td><td>{{student.age}}</td><td>{{student.birthday}}</td><td>{{student.gender == 1 ? '男' : '女'}}</td><td>{{student.cid}}</td><td>修改删除</td></tr></table></div>
      </template><script>
      // 导入ajax函数
      import {condition} from '../api/student'
      export default {data() {return {page: {     //分页size: 3,current: 1},studentVo: {  //条件cid: '',sname: '',startAge: '',endAge: '',},classesList: [ //班级的模拟数据{cid:1, cname: 'Java56'},{cid:2, cname: 'Java78'},{cid:3, cname: 'Java12'},{cid:4, cname: 'Java34'},]}},methods: {async conditionFn(num) {// 设置第几页if(num) {this.page.current = num}// ajax查询let { data } = await condition(this.page, this.studentVo)// 获得结果this.page = data}},mounted() {// 查询第一页this.conditionFn(1)},
      }
      </script><style></style>
      
    • 分页查询

          <!-- 分页条 -->每页<select v-model="page.size" @change="conditionFn(1)"><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="5">5</option><option value="10">10</option></select>条,<a href="" @click.prevent="conditionFn(num)" v-for="(num,index) in page.pages" :key="index">{{num}}</a>,跳转到第<input type="text" size="4" v-model="page.current" @keyup.enter="conditionFn()">页
      

2.2.5 前端完整代码

<template><div><!-- 条件查询 -->班级 <select v-model="studentVo.cid"><option value="">--选择班级--</option><option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option></select>姓名:<input type="text" size="8" v-model="studentVo.sname"/>年龄:<input type="text" size="8" v-model="studentVo.startAge"/> -- <input type="text" size="8" v-model="studentVo.endAge"/><input type="button" value="查询" @click="conditionFn(1)" /><!-- 列表展示 --><table border="1"><tr><td>编号</td><td>姓名</td><td>年龄</td><td>生日</td><td>性别</td><td>班级</td><td>操作</td></tr><tr v-for="(student,index) in page.records" :key="index"><td>{{student.sid}}</td><td>{{student.sname}}</td><td>{{student.age}}</td><td>{{student.birthday}}</td><td>{{student.gender == 1 ? '男' : '女'}}</td><td>{{student.cid}}</td><td>修改删除</td></tr></table><!-- 分页条 -->每页<select v-model="page.size" @change="conditionFn(1)"><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="5">5</option><option value="10">10</option></select>条,<a href="" @click.prevent="conditionFn(num)" v-for="(num,index) in page.pages" :key="index">{{num}}</a>,跳转到第<input type="text" size="4" v-model="page.current" @keyup.enter="conditionFn()">页</div>
</template><script>
// 导入ajax函数
import {condition} from '../api/student'
export default {data() {return {page: {     //分页size: 3,current: 1},studentVo: {  //条件cid: '',sname: '',startAge: '',endAge: '',},classesList: [ //班级的模拟数据{cid:1, cname: 'Java56'},{cid:2, cname: 'Java78'},{cid:3, cname: 'Java12'},{cid:4, cname: 'Java34'},]}},methods: {async conditionFn(num) {// 设置第几页if(num) {this.page.current = num}// ajax查询let { data } = await condition(this.page, this.studentVo)// 获得结果this.page = data}},mounted() {// 查询第一页this.conditionFn(1)},
}
</script><style></style>

2.3 添加或修改

2.3.1 后端实现

    @PostMappingpublic BaseResult saveOrUpdate(@RequestBody Student student) {try {// 保存或更新:如果没有id进行添加操作;如果有id进行更新操作boolean result = studentService.saveOrUpdate(student);//处理if(result) {return BaseResult.ok("编辑成功");}return BaseResult.error("编辑失败");} catch (Exception e) {e.printStackTrace();return BaseResult.error(e.getMessage());}}
  • 数据库的id为自动增强,如果JavaBean没有设置,会出现类型不匹配异常。

3. 班级管理

3.1 查询所有班级

3.1.1 后端

  • 步骤:

    • 步骤1:编写JavaBean,Classes
    • 步骤2:编写Mapper,ClassesMapper,实现通用mapper
    • 步骤3:编写service,接口+实现类+通用
    • 步骤4:编写controller
  • 步骤1:编写JavaBean,Classes

    package com.czxy.domain;import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;@TableName("tb_class")
    @Data
    public class Classes {@TableId(value = "cid", type = IdType.AUTO)private Integer cid;@TableField("cname")private String cname;
    }/*
    CREATE TABLE `tb_class` (`cid` int(11) NOT NULL AUTO_INCREMENT,`cname` varchar(50) DEFAULT NULL,PRIMARY KEY (`cid`)
    )*/
    
  • 步骤2:编写Mapper,ClassesMapper,实现通用mapper

    package com.czxy.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.czxy.domain.Classes;
    import org.apache.ibatis.annotations.Mapper;@Mapper
    public interface ClassesMapper extends BaseMapper<Classes> {}
  • 步骤3:编写service,接口+实现类+通用

    • 接口

      package com.czxy.service;import com.baomidou.mybatisplus.extension.service.IService;
      import com.czxy.domain.Classes;public interface ClassesService extends IService<Classes> {}
    • 实现类

      package com.czxy.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import com.czxy.domain.Classes;
      import com.czxy.mapper.ClassesMapper;
      import com.czxy.service.ClassesService;
      import org.springframework.stereotype.Service;
      import org.springframework.transaction.annotation.Transactional;@Service
      @Transactional
      public class ClassesServiceImpl extends ServiceImpl<ClassesMapper, Classes> implements ClassesService {}
  • 步骤4:编写controller

    package com.czxy.controller;import com.czxy.domain.Classes;
    import com.czxy.service.ClassesService;
    import com.czxy.vo.BaseResult;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
    import java.util.List;@RestController
    @RequestMapping("/classes")
    public class ClassesController {@Resourceprivate ClassesService classesService;/*** 查询所有* @return*/@GetMappingpublic BaseResult findAll() {// 2 查询List<Classes> list = classesService.list();// 3 返回return BaseResult.ok("查询成功", list );}
    }

基于spring cloud + nacos + gateway + ssm+的学生管理系统相关推荐

  1. Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos /(非阿里组件))

    Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos)(非阿里组件) 回溯 Gateway 整合 nacos 方式一(复杂/灵活/常用) 方式 ...

  2. Spring cloud 2020 gateway nacos 出现503的情况

    Spring cloud 2020 gateway nacos 出现503的情况 参考https://blog.csdn.net/weixin_39233623/article/details/121 ...

  3. 基于Spring Cloud微服务化开发平台-Cloud Platform后台管理系统 v3.1.0

    介绍: Cloud-Platform是国内首个基于Spring Cloud微服务化开发平台,具有统一授权.认证后台管理系统,其中包含具备用户管理.资源权限管理.网关API 管理等多个模块,支持多业务系 ...

  4. Spring Cloud入门-Gateway服务网关(Hoxton版本)

    文章目录 Spring Cloud入门系列汇总 摘要 Gateway 简介 相关概念 创建 api-gateway模块 在pom.xml中添加相关依赖 两种不同的配置路由方式 使用yml配置 使用Ja ...

  5. 2022最新基于 Spring Cloud 的微服务架构分析,java 技术经理岗位职责

    构建在开发团队之外的 API 网关必须具备负载均衡能力,可以配置多个 IP 地址.通过该 API 网关也最好具备和 Docker 容器扩展后的服务自动注册和地址加入扩展能力. Eureka 的竞品分析 ...

  6. 基于 Spring Cloud 的服务治理实践

    http://www.infoq.com/cn/articles/spring-cloud-based-service-governance 大家好,我是来自贝壳金控的赵文乐,目前主要从事架构方面的工 ...

  7. 流量暴增,掌门教育如何基于 Spring Cloud Alibaba 构建微服务体系?

    作者 | 童子龙  掌门教育基础架构部架构师 **导读:**本文整理自作者于 2020 年云原生微服务大会上的分享<掌门教育云原生落地实践>,本文主要介绍了掌门教育云原生落地实践,主要围绕 ...

  8. 干货|基于 Spring Cloud 的微服务落地

    转载自 干货|基于 Spring Cloud 的微服务落地 微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需 ...

  9. 基于Spring Cloud及K8S构建微服务应用

    摘要 广发证券蔡波斯先生通过三个大方向来为我们分享基于Spring Cloud及K8S构建微服务应用. 内容来源:2017年6月10日,广发证券蔡波斯在"Spring Cloud中国社区技术 ...

  10. 贝壳金控赵文乐:基于 Spring Cloud 的服务治理实践

    大家好,我是来自贝壳金控的赵文乐,目前主要从事架构方面的工作.今天我想跟大家分享<基于 Spring Cloud 的服务治理实践>.我先简单向大家介绍一下服务治理的概念,然后介绍实际案例中 ...

最新文章

  1. MongoDB或CouchDB - 适合生产? [关闭]
  2. 每天一个linux命令(36):diff 命令
  3. 解析软件测试需要变革的因素
  4. .NET混淆器 Dotfuscator使用教程七:加强保护之改进重命名混淆
  5. unity热更新json_Unity3D热更新 CSHotFix入门教程之HelloWorld
  6. 合并分支到master_我敢打赌!这是全网最全的 Git 分支开发规范手册
  7. (chap6 Http首部) 请求首部字段 AuthorizationExpectFromHostIf-Match
  8. soapUI-JDBC Request
  9. Android 系统(69)---Android7.1.1系统设置默认值大全
  10. GroovyHelp方便查看java api
  11. PYTHON博客记录0602
  12. 使用Jenkins打包和部署Maven工程步骤详解
  13. SharePoint 2013 创建web应用程序报错This page can’t be displayed
  14. 教领导“做事”的新人,后来过得好吗?
  15. 个税计算器 / 微信小程序开发
  16. Windows 10 支持AAC编码的方法
  17. 商务部关于促进电子商务规范发展的意见
  18. 部署学之思在线考试项目
  19. 最简单DIY基于ESP32CAM的物联网相机系统③(在JSP服务器图传相片给所有客户端欣赏)
  20. CSS 新属性 《设置容器长宽比》

热门文章

  1. Redis-stack 初体验
  2. win2008 SP2下USB鼠标不能使用的一个解决方案
  3. html横线标记_html中横线怎么写代码
  4. 如何退出企业微信?退出之后,企业微信的聊天记录还在吗?
  5. E php短信平台接口
  6. 电信dns服务器哪个稳定,电信宽带dns设置哪个最快? dns设置哪个最好最快
  7. 十一式:开发者思维模式-简单而纯粹
  8. CPU占用100%的一般原因及解决办法
  9. 微信公众平台和微信开放平台的区别
  10. 初探三维计算机视觉(三维重建) —— 相机模型 + 双目系统 + 点云模型