基于spring cloud + nacos + gateway + ssm+的学生管理系统
- 前端: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+的学生管理系统相关推荐
- Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos /(非阿里组件))
Spring Cloud Alibaba - Gateway 入门案例(二)(Gateway 整合 nacos)(非阿里组件) 回溯 Gateway 整合 nacos 方式一(复杂/灵活/常用) 方式 ...
- Spring cloud 2020 gateway nacos 出现503的情况
Spring cloud 2020 gateway nacos 出现503的情况 参考https://blog.csdn.net/weixin_39233623/article/details/121 ...
- 基于Spring Cloud微服务化开发平台-Cloud Platform后台管理系统 v3.1.0
介绍: Cloud-Platform是国内首个基于Spring Cloud微服务化开发平台,具有统一授权.认证后台管理系统,其中包含具备用户管理.资源权限管理.网关API 管理等多个模块,支持多业务系 ...
- Spring Cloud入门-Gateway服务网关(Hoxton版本)
文章目录 Spring Cloud入门系列汇总 摘要 Gateway 简介 相关概念 创建 api-gateway模块 在pom.xml中添加相关依赖 两种不同的配置路由方式 使用yml配置 使用Ja ...
- 2022最新基于 Spring Cloud 的微服务架构分析,java 技术经理岗位职责
构建在开发团队之外的 API 网关必须具备负载均衡能力,可以配置多个 IP 地址.通过该 API 网关也最好具备和 Docker 容器扩展后的服务自动注册和地址加入扩展能力. Eureka 的竞品分析 ...
- 基于 Spring Cloud 的服务治理实践
http://www.infoq.com/cn/articles/spring-cloud-based-service-governance 大家好,我是来自贝壳金控的赵文乐,目前主要从事架构方面的工 ...
- 流量暴增,掌门教育如何基于 Spring Cloud Alibaba 构建微服务体系?
作者 | 童子龙 掌门教育基础架构部架构师 **导读:**本文整理自作者于 2020 年云原生微服务大会上的分享<掌门教育云原生落地实践>,本文主要介绍了掌门教育云原生落地实践,主要围绕 ...
- 干货|基于 Spring Cloud 的微服务落地
转载自 干货|基于 Spring Cloud 的微服务落地 微服务架构模式的核心在于如何识别服务的边界,设计出合理的微服务.但如果要将微服务架构运用到生产项目上,并且能够发挥该架构模式的重要作用,则需 ...
- 基于Spring Cloud及K8S构建微服务应用
摘要 广发证券蔡波斯先生通过三个大方向来为我们分享基于Spring Cloud及K8S构建微服务应用. 内容来源:2017年6月10日,广发证券蔡波斯在"Spring Cloud中国社区技术 ...
- 贝壳金控赵文乐:基于 Spring Cloud 的服务治理实践
大家好,我是来自贝壳金控的赵文乐,目前主要从事架构方面的工作.今天我想跟大家分享<基于 Spring Cloud 的服务治理实践>.我先简单向大家介绍一下服务治理的概念,然后介绍实际案例中 ...
最新文章
- MongoDB或CouchDB - 适合生产? [关闭]
- 每天一个linux命令(36):diff 命令
- 解析软件测试需要变革的因素
- .NET混淆器 Dotfuscator使用教程七:加强保护之改进重命名混淆
- unity热更新json_Unity3D热更新 CSHotFix入门教程之HelloWorld
- 合并分支到master_我敢打赌!这是全网最全的 Git 分支开发规范手册
- (chap6 Http首部) 请求首部字段 AuthorizationExpectFromHostIf-Match
- soapUI-JDBC Request
- Android 系统(69)---Android7.1.1系统设置默认值大全
- GroovyHelp方便查看java api
- PYTHON博客记录0602
- 使用Jenkins打包和部署Maven工程步骤详解
- SharePoint 2013 创建web应用程序报错This page can’t be displayed
- 教领导“做事”的新人,后来过得好吗?
- 个税计算器 / 微信小程序开发
- Windows 10 支持AAC编码的方法
- 商务部关于促进电子商务规范发展的意见
- 部署学之思在线考试项目
- 最简单DIY基于ESP32CAM的物联网相机系统③(在JSP服务器图传相片给所有客户端欣赏)
- CSS 新属性 《设置容器长宽比》