md文档可在点击下方小卡片获取!
1.搭建环境
1.1 创建项目
- 创建项目:exam-student-vue
1.2 添加坐标
<!-- 父工程 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!-- jar包版本 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.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> </properties> <!-- 导入需要依赖(坐标/jar包) --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- mybatis启动器 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.starter.version}</version> </dependency> <!-- 通用Mapper启动器 --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper-spring-boot-starter</artifactId> <version>${mapper.starter.version}</version> </dependency> <!-- 分页助手启动器 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>${pageHelper.starter.version}</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>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency> </dependencies>
1.3 拷贝properties文件
#端口号 server.port=8080 #数据库基本配置 spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db3?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=1234 #druid 连接池配置 #驱动 #spring.datasource.driver-class-name=com.mysql.jdbc.Driver #初始化连接池大小 spring.datasource.druid.initial-size=1 #最小连接数 spring.datasource.druid.min-idle=1 #最大连接数 spring.datasource.druid.max-active=20 #获取连接时候验证,会影响性能 spring.datasource.druid.test-on-borrow=true # mybatis # mybatis.type-aliases-package=com.czxy.domain.base # mybatis.mapper-locations=classpath:mappers/*.xml #mapper mapper.not-empty=false mapper.identity=MYSQL #开启驼峰映射 mybatis.configuration.map-underscore-to-camel-case=true mybatis.mapper-locations=classpath*:mapper/*.xml #开启log4j打印SQL语句 logging.level.com.czxy.dao=debug
1.4 编写启动类
package com.czxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author manor * */ @SpringBootApplication public class StudentVueApplication { public static void main(String[] args) { SpringApplication.run(StudentVueApplication.class, args); } }
1.5 拷贝封装类
1.6 拷贝配置类
2. 基本结构
2.1 初始化数据库
2.1.1 创建 数据库
create database db1010; use db1010;
2.1.2 建表语句
-- 班级表 create table tb_class( `c_id` varchar(32) primary key comment '班级ID', `c_name` varchar(50) comment '班级名称', `desc` varchar(200) comment '班级描述' ); insert into tb_class(`c_id`,`c_name`,`desc`) values('c001','Java12班','。。。。'); insert into tb_class(`c_id`,`c_name`,`desc`) values('c002','Java34班','。。。。'); # 学生表 create table tb_student( s_id varchar(32) primary key comment '学生ID', sname varchar(50) comment '姓名', age int comment '年龄', birthday datetime comment '生日', gender char(1) comment '性别', c_id varchar(32) ); alter table tb_student add constraint foreign key (c_id) references tb_class (c_id); insert into tb_student(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`) values('s001','赵三',19,'2001-01-17','1','c001'); insert into tb_student(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`) values('s002','钱四',19,'2001-05-16','1','c001'); insert into tb_student(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`) values('s003','孙五',18,'2002-03-15','1','c001'); insert into tb_student(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`) values('s004','李三',19,'2001-04-14','0','c002'); insert into tb_student(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`) values('s005','周四',19,'2001-02-13','0','c002'); insert into tb_student(`s_id`,`sname`,`age`,`birthday`,`gender`,`c_id`) values('s006','王五',18,'2002-06-12','1','c002');
2.2 后端实现:domain、Mapper
2.2.1 班级相关
- JavaBean
package com.czxy.domain; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; /** * @author manor * */ @Table(name="tb_class") public class Classes { @Id @Column(name="c_id") private String cid; @Column(name="c_name") private String cname; @Column(name="`desc`") private String desc; public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } @Override public String toString() { return "Classes{" + "cid='" + cid + '\'' + ", cname='" + cname + '\'' + ", desc='" + desc + '\'' + '}'; } }
- Mapper
package com.czxy.mapper; import com.czxy.domain.Classes; import tk.mybatis.mapper.common.Mapper; /** * @author manor * */ @org.apache.ibatis.annotations.Mapper public interface ClassesMapper extends Mapper<Classes> { }
2.2.2 学生相关
- JavaBean
package com.czxy.domain; import com.fasterxml.jackson.annotation.JsonFormat; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; import java.util.Date; /** * @author manor * */ @Table(name="tb_student") public class Student { @Id @Column(name="s_id") private String sid; //学生ID @Column(name="sname") private String sname; //姓名 @Column(name="age") private Integer age; //年龄 @Column(name="birthday") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") private Date birthday; //生日 @Column(name="gender") private String gender; //性别 @Column(name="c_id") private String cid; //班级外键 private Classes classes; //班级对象 public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public Classes getClasses() { return classes; } public void setClasses(Classes classes) { this.classes = classes; } @Override public String toString() { return "Student{" + "sid='" + sid + '\'' + ", sname='" + sname + '\'' + ", age=" + age + ", birthday=" + birthday + ", gender='" + gender + '\'' + ", cid='" + cid + '\'' + ", classes=" + classes + '}'; } }
- Mapper
package com.czxy.mapper; import com.czxy.domain.Student; import tk.mybatis.mapper.common.Mapper; /** * @author manor * */ @org.apache.ibatis.annotations.Mapper public interface StudentMapper extends Mapper<Student> { }
3.后端实现
3.1 班级后端
3.1.1 查询所有班级
- service
package com.czxy.service; import com.czxy.domain.Classes; import com.czxy.domain.Student; import com.czxy.mapper.ClassesMapper; import com.czxy.mapper.StudentMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource; import java.util.List; /** * @author manor * */ @Service @Transactional public class ClassesService { @Resource private ClassesMapper classesMapper; @Resource private StudentMapper studentMapper; /** * 查询所有 * @return */ public List<Classes> findAll() { List<Classes> list = classesMapper.selectAll(); return list; } }
- 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.*; import javax.annotation.Resource; import java.util.List; /** • @author manor • */ @RestController @RequestMapping("/classes") public class ClassesController {
@Resource private ClassesService classesService; /** * 查询所有 * @return */ @GetMapping public BaseResult findAll(){ // 查询 List<Classes> list = classesService.findAll(); // 返回 return BaseResult.ok("查询成功", list ); }
}
### 3.1.2 添加班级 * service ~~~java /** * 添加班级 * @param classes * @return */ public boolean save(Classes classes) { // 校验 Classes find = classesMapper.selectByPrimaryKey(classes.getCid()); if(find != null){ throw new RuntimeException("ID已存在"); } // 添加 int count = classesMapper.insert(classes); return count == 1; }
- controller
/** * 添加班级 * @param classes * @return */ @PostMapping public BaseResult save(@RequestBody Classes classes){ try { // 添加 boolean result = classesService.save(classes); // 返回 if(result){ return BaseResult.ok("添加成功"); } else { return BaseResult.error("添加失败"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } }
3.1.3 查询班级详情
- service
/** * 查询详情 * @param classId * @return */ public Classes findById(String classId){ Classes classes = classesMapper.selectByPrimaryKey(classId); return classes; }
- controller
/** * 查询详情 * @param classId * @return */ @GetMapping("/{id}") public BaseResult findById(@PathVariable("id") String classId ){ // 查询 Classes classes = classesService.findById(classId); if(classes != null) { // 返回 return BaseResult.ok("查询成功", classes); } else { return BaseResult.error("查询失败"); } }
3.1.4 更新班级
- service
/** * 更新操作 * @param classes * @return */ public boolean update(Classes classes){ // 校验 Classes find = classesMapper.selectByPrimaryKey(classes.getCid()); if(find == null){ throw new RuntimeException("ID不存在"); } // 更新非空项 int count = classesMapper.updateByPrimaryKeySelective(classes); return count == 1; }
- controller
/** * 更新操作 * @param classes * @return */ @PutMapping public BaseResult update(@RequestBody Classes classes){ try { // 添加 boolean result = classesService.update(classes); // 返回 if(result){ return BaseResult.ok("更新成功"); } else { return BaseResult.error("更新失败"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } }
3.1.5 删除班级
- service
/** * 通过id删除详情 * @param classId * @return */ public boolean deleteById(String classId) { // 查询指定班级id的学生数 Example example = new Example(Student.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("cid", classId); int studentCount = studentMapper.selectCountByExample(example); if(studentCount > 0) { throw new RuntimeException("班级已关联学生,不能删除"); } int count = classesMapper.deleteByPrimaryKey(classId); return count == 1; }
- controller
/** * 查询详情 * @param classId * @return */ @DeleteMapping("/{id}") public BaseResult deleteById(@PathVariable("id") String classId ){ try { // 查询 boolean result = classesService.deleteById(classId); // 返回 if(result){ return BaseResult.ok("删除成功"); } else { return BaseResult.error("删除失败"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } }
3.2 学生后端
3.1.1 查询所有学生
- StudentVo
package com.czxy.vo; /** * @author manor * */ public class StudentVo { private String cid; //班级 private String sname; //姓名 private String startAge; //开始年龄 private String endAge; //结束年龄 public String getCid() { return cid; } public void setCid(String cid) { this.cid = cid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getStartAge() { return startAge; } public void setStartAge(String startAge) { this.startAge = startAge; } public String getEndAge() { return endAge; } public void setEndAge(String endAge) { this.endAge = endAge; } @Override public String toString() { return "StudentVo{" + "cid='" + cid + '\'' + ", sname='" + sname + '\'' + ", startAge='" + startAge + '\'' + ", endAge='" + endAge + '\'' + '}'; } }
- service
package com.czxy.service; import com.czxy.domain.Classes; import com.czxy.domain.Student; import com.czxy.mapper.ClassesMapper; import com.czxy.mapper.StudentMapper; import com.czxy.vo.StudentVo; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource; import java.util.List; /** * @author manor * */ @Service @Transactional public class StudentService { @Resource private StudentMapper studentMapper; @Resource private ClassesMapper classesMapper; /** * 查询所有 + 分页 * @return */ public PageInfo<Student> findAllByCondition(StudentVo studentVo, Integer pageSize, Integer pageNum){ // 拼凑条件 Example example = new Example(Student.class); Example.Criteria criteria = example.createCriteria(); if(studentVo != null){ //等值查询 if(studentVo.getCid() != null && !"".equals(studentVo.getCid())) { criteria.andEqualTo("cid",studentVo.getCid()); } // 模糊查询 if(studentVo.getSname() != null && !"".equals(studentVo.getSname())) { criteria.andLike("sname","%"+studentVo.getSname()+"%"); } // 区间查询 if(studentVo.getStartAge() != null && !"".equals(studentVo.getStartAge())){ criteria.andGreaterThanOrEqualTo("age",studentVo.getStartAge()); } if(studentVo.getEndAge() != null && !"".equals(studentVo.getEndAge())) { criteria.andLessThanOrEqualTo("age",studentVo.getEndAge()); } } // 分页 PageHelper.startPage(pageNum,pageSize); // 条件查询 List<Student> list = studentMapper.selectByExample(example); // 关联查询 for(Student student : list){ // 查询班级外键对应的对象 Classes classes = classesMapper.selectByPrimaryKey(student.getCid()); student.setClasses(classes); } // 分页封装 PageInfo pageInfo = new PageInfo(list); return pageInfo; } }
- controller
package com.czxy.controller; import com.czxy.domain.Student; import com.czxy.service.StudentService; import com.czxy.vo.BaseResult; import com.czxy.vo.StudentVo; import com.github.pagehelper.PageInfo; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; /** * @author manor * */ @RestController @RequestMapping("/student") public class StudentController { @Resource private StudentService studentService; /** * 条件查询 * @param studentVo * @return */ @PostMapping("/condition/{pagesize}/{pagenum}") public BaseResult conditioin(@RequestBody StudentVo studentVo, @PathVariable("pagesize") Integer pagesize , @PathVariable("pagenum") Integer pagenum){ // 添加 PageInfo<Student> pageInfo = studentService.findAllByCondition(studentVo,pagesize,pagenum); // 返回 return BaseResult.ok("查询成功", pageInfo); } }
3.1.2 添加学生
- service
/** * 添加学生 * @param student * @return */ public boolean save(Student student){ // 校验 Student find = studentMapper.selectByPrimaryKey(student.getSid()); if(find != null) { throw new RuntimeException("ID已存在"); } // 添加 int count = studentMapper.insert(student); return count == 1; }
- controller
/** * 添加学生 * @param student * @return */ @PostMapping public BaseResult save(@RequestBody Student student){ try { // 添加 boolean result = studentService.save(student); // 返回 if(result){ return BaseResult.ok("添加成功"); } else { return BaseResult.error("添加失败"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } }
3.1.3 查询学生详情
- service
/** * 查询详情 * @param studentId * @return */ public Student findById(String studentId){ Student student = studentMapper.selectByPrimaryKey(studentId); return student; }
- controller
/** * 查询详情 * @param studentId * @return */ @GetMapping("/{id}") public BaseResult findById(@PathVariable("id") String studentId ){ // 查询 Student student = studentService.findById(studentId); if(student != null){ // 返回 return BaseResult.ok("查询成功", student); } else { return BaseResult.error("查询失败"); } }
3.1.4 更新学生
- service
/** * 更新操作 * @param student * @return */ public boolean update(Student student){ // 校验 Student find = studentMapper.selectByPrimaryKey(student.getSid()); if(find == null) { throw new RuntimeException("ID不存在"); } // 更新非空项 int count = studentMapper.updateByPrimaryKeySelective(student); return count == 1; }
- controller
/** * 更新操作 * @param student * @return */ @PutMapping public BaseResult update(@RequestBody Student student){ try { // 添加 boolean result = studentService.update(student); // 返回 if(result){ return BaseResult.ok("更新成功"); } else { return BaseResult.error("更新失败"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } }
3.1.5 删除学生
- service
/** * 通过id删除详情 * @param studentId * @return */ public boolean deleteById(String studentId) { int count = studentMapper.deleteByPrimaryKey(studentId); return count == 1; }
- controller
/** * 通过id删除 * @param studentId * @return */ @DeleteMapping("/{id}") public BaseResult deleteById(@PathVariable("id") String studentId ){ // 查询 boolean result = studentService.deleteById(studentId); // 返回 if(result){ return BaseResult.ok("删除成功"); } else { return BaseResult.error("删除失败"); } }
4. 前端实现:Vue版
- 项目前端目录结构
- 使用Visual Studio Code 开发前端页面
4.1 班级前端
4.1.1 查询所有
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> </head> <body> <div id="app"> <a href="index.html">返回首页</a> <a href="classes_add.html">添加班级</a> <br/> <table id="tid" border="1" width="800"> <tr> <td>班级ID</td> <td>班级名称</td> <td>班级描述</td> <td>操作</td> </tr> <tr v-for="(classes,index) in classesList" :key="index"> <td>{{classes.cid}}</td> <td>{{classes.cname}}</td> <td>{{classes.desc}}</td> <td> <a href="">修改</a> <a href="">删除</a> </td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { classesList: [], //班级数据 }, mounted() { // 查询所有 this.findAll() }, methods: { findAll() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
4.1.2 添加
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <body> </head> <div id="app"> <a href="classes_list.html">返回列表页</a> <table id="tid" border="1"> <tr> <td>班级ID</td> <td><input v-model="classes.cid" /> </td> </tr> <tr> <td>班级名称</td> <td><input v-model="classes.cname" /> </td> </tr> <tr> <td>班级描述</td> <td> <textarea cols="20" rows="5" v-model="classes.desc" ></textarea> </td> </tr> <tr> <td></td> <td><input type="button" value="添加" @click="addClasses" /></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { classes: {}, //学生表单数据 }, mounted() { }, methods: { addClasses() { var url = `/classes`; axios.post(url, this.classes) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "classes_list.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
4.1.3 修改
- 跳转页面
<a :href="'classes_edit.html?id=' + classes.cid">修改</a>
- 回显
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <body> </head> <div id="app"> <a href="classes_list.html">返回列表页</a> <table id="tid" border="1"> <tr> <td>班级名称</td> <td> <input v-model="classes.cname" /> </td> </tr> <tr> <td>班级描述</td> <td> <textarea cols="20" rows="5" v-model="classes.desc" ></textarea> </td> </tr> <tr> <td></td> <td><input type="button" value="更新" /></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { classes: {}, //学生表单数据 }, mounted() { // 通过id查询详情 this.findById() }, methods: { findById() { // 获得id var arr = location.href.split("?id=") var id = arr[1] // 路径 var url = `/classes/${id}`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classes = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
- 提交
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <body> </head> <div id="app"> <a href="classes_list.html">返回列表页</a> <table id="tid" border="1"> <tr> <td>班级名称</td> <td> <input v-model="classes.cname" /> </td> </tr> <tr> <td>班级描述</td> <td> <textarea cols="20" rows="5" v-model="classes.desc" ></textarea> </td> </tr> <tr> <td></td> <td><input type="button" value="更新" @click="editClasses" /></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { classes: {}, //学生表单数据 }, mounted() { // 通过id查询详情 this.findById() }, methods: { findById() { // 获得id var arr = location.href.split("?id=") var id = arr[1] // 路径 var url = `/classes/${id}`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classes = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, editClasses() { var url = `/classes`; axios.put(url, this.classes) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "classes_list.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
4.1.4 删除
- 修改 classes_list.html 页面,填写修改功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> </head> <body> <div id="app"> <a href="index.html">返回首页</a> <a href="classes_add.html">添加班级</a> <br/> <table id="tid" border="1" width="800"> <tr> <td>班级ID</td> <td>班级名称</td> <td>班级描述</td> <td>操作</td> </tr> <tr v-for="(classes,index) in classesList" :key="index"> <td>{{classes.cid}}</td> <td>{{classes.cname}}</td> <td>{{classes.desc}}</td> <td> <a :href="'classes_edit.html?id=' + classes.cid">修改</a> <a href="#" @click="deleteClasses(classes.cid)">删除</a> </td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { classesList: [], //班级数据 }, mounted() { // 查询所有 this.findAll() }, methods: { findAll() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, deleteClasses(id) { if(! confirm("您确定要删除么?")){ return } // 删除 var url = `/classes/${id}`; axios.delete(url) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "classes_list.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
4.2 学生前端
4.2.1 查询所有
1)查询 + 条件 + 分页
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> </head> <body> <div id="app"> <a href="index.html">返回首页</a> <a href="student_add.html">添加学生</a> <br/> <!-- 查询条件 --> <table> <tr> <td>班级</td> <td> <select v-model="student.cid"> <option value="">--选择班级--</option> <option value="c001">--Java12--</option> <option value="c002">--Java34--</option> </select> </td> <td>姓名:</td> <td> <input type="text" placeholder="请输入姓名" v-model="student.sname"size="10"> </td> <td>年龄:</td> <td> <input type="text" placeholder="请输入开始年龄" v-model="student.startAge" size="10"> -- <input type="text" placeholder="请输入结束年龄" v-model="student.endAge" size="10"> </td> <td><input type="button" value="查询" @click="condition(1)"></td> </tr> </table> <!-- 查询列表 --> <table id="tid" border="1" width="800"> <tr> <td>学生ID</td> <td>班级ID</td> <td>学生姓名</td> <td>年龄</td> <td>生日</td> <td>性别</td> <td>操作</td> </tr> <tr v-for="(student,index) in pageInfo.list" :key="index"> <td>{{student.sid}}</td> <td>{{student.classes.cname}}</td> <td>{{student.sname}}</td> <td>{{student.age}}</td> <td>{{student.birthday}}</td> <td>{{student.gender == 1 ? "男" : "女"}}</td> <td> <a href="">修改</a> <a href="">删除</a> </td> </tr> </table> <!-- 分页条 --> <div id="pageId"> <a href="#" v-for="index in pageInfo.pages" :key="index" @click.prevent="condition(index)" >{{index}}</a> </div> </div> </body> </html> <script> new Vue({ el: '#app', data: { pageSize: 2, //每页多少条 student: { //表单对象 }, pageInfo: {}, //分页对象 }, mounted() { // 查询所有 this.condition(1) }, methods: { condition(pageNum) { var url = `/student/condition/${this.pageSize}/${pageNum}`; axios.post(url, this.student) .then( response => { if(response.data.code == 1){ this.pageInfo = response.data.data } else { alert(response.data.message) } }) .catch(error => { }) } }, }) </script>
2)查询条件,下拉列表
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> </head> <body> <div id="app"> <a href="index.html">返回首页</a> <a href="student_add.html">添加学生</a> <br/> <!-- 查询条件 --> <table> <tr> <td>班级</td> <td> <select v-model="student.cid"> <option value="">--选择班级--</option> <option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option> </select> </td> <td>姓名:</td> <td> <input type="text" placeholder="请输入姓名" v-model="student.sname"size="10"> </td> <td>年龄:</td> <td> <input type="text" placeholder="请输入开始年龄" v-model="student.startAge" size="10"> -- <input type="text" placeholder="请输入结束年龄" v-model="student.endAge" size="10"> </td> <td><input type="button" value="查询" @click="condition(1)"></td> </tr> </table> <!-- 查询列表 --> <table id="tid" border="1" width="800"> <tr> <td>学生ID</td> <td>班级ID</td> <td>学生姓名</td> <td>年龄</td> <td>生日</td> <td>性别</td> <td>操作</td> </tr> <tr v-for="(student,index) in pageInfo.list" :key="index"> <td>{{student.sid}}</td> <td>{{student.classes.cname}}</td> <td>{{student.sname}}</td> <td>{{student.age}}</td> <td>{{student.birthday}}</td> <td>{{student.gender == 1 ? "男" : "女"}}</td> <td> <a href="">修改</a> <a href="">删除</a> </td> </tr> </table> <!-- 分页条 --> <div id="pageId"> <a href="#" v-for="index in pageInfo.pages" :key="index" @click.prevent="condition(index)" >{{index}}</a> </div> </div> </body> </html> <script> new Vue({ el: '#app', data: { pageSize: 2, //每页多少条 student: { //表单对象 cid: '' }, pageInfo: {}, //分页对象 classesList: [] //班级列表 }, mounted() { // 查询所有 this.condition(1) // 查询所有班级 this.findAllClasses() }, methods: { condition(pageNum) { var url = `/student/condition/${this.pageSize}/${pageNum}`; axios.post(url, this.student) .then( response => { if(response.data.code == 1){ this.pageInfo = response.data.data } else { alert(response.data.message) } }) .catch(error => { }) }, findAllClasses() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
3)跳转
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> </head> <body> <div id="app"> <a href="index.html">返回首页</a> <a href="student_add.html">添加学生</a> <br/> <!-- 查询条件 --> <table> <tr> <td>班级</td> <td> <select v-model="student.cid"> <option value="">--选择班级--</option> <option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option> </select> </td> <td>姓名:</td> <td> <input type="text" placeholder="请输入姓名" v-model="student.sname"size="10"> </td> <td>年龄:</td> <td> <input type="text" placeholder="请输入开始年龄" v-model="student.startAge" size="10"> -- <input type="text" placeholder="请输入结束年龄" v-model="student.endAge" size="10"> </td> <td><input type="button" value="查询" @click="condition(1)"></td> </tr> </table> <!-- 查询列表 --> <table id="tid" border="1" width="800"> <tr> <td>学生ID</td> <td>班级ID</td> <td>学生姓名</td> <td>年龄</td> <td>生日</td> <td>性别</td> <td>操作</td> </tr> <tr v-for="(student,index) in pageInfo.list" :key="index"> <td>{{student.sid}}</td> <td>{{student.classes.cname}}</td> <td>{{student.sname}}</td> <td>{{student.age}}</td> <td>{{student.birthday}}</td> <td>{{student.gender == 1 ? "男" : "女"}}</td> <td> <a href="">修改</a> <a href="">删除</a> </td> </tr> </table> <!-- 分页条 --> <div id="pageId"> <a href="#" v-for="index in pageInfo.pages" :key="index" @click.prevent="condition(index)" >{{index}}</a> 跳转到第 <input type="text" v-model="pageNum" size="5" @keydown.enter="go" />页 </div> </div> </body> </html> <script> new Vue({ el: '#app', data: { pageSize: 2, //每页多少条 pageNum: 1, //第几页 student: { //表单对象 cid: '' }, pageInfo: {}, //分页对象 classesList: [] //班级列表 }, mounted() { // 查询所有 this.condition(1) // 查询所有班级 this.findAllClasses() }, methods: { condition(pageNum) { var url = `/student/condition/${this.pageSize}/${pageNum}`; axios.post(url, this.student) .then( response => { if(response.data.code == 1){ this.pageInfo = response.data.data } else { alert(response.data.message) } }) .catch(error => { }) }, findAllClasses() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, go() { if(parseInt(this.pageNum) == this.pageNum) { this.condition(this.pageNum) } } }, }) </script>
4)改变分页pageSize
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> </head> <body> <div id="app"> <a href="index.html">返回首页</a> <a href="student_add.html">添加学生</a> <br/> <!-- 查询条件 --> <table> <tr> <td>班级</td> <td> <select v-model="student.cid"> <option value="">--选择班级--</option> <option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option> </select> </td> <td>姓名:</td> <td> <input type="text" placeholder="请输入姓名" v-model="student.sname"size="10"> </td> <td>年龄:</td> <td> <input type="text" placeholder="请输入开始年龄" v-model="student.startAge" size="10"> -- <input type="text" placeholder="请输入结束年龄" v-model="student.endAge" size="10"> </td> <td><input type="button" value="查询" @click="condition(1)"></td> </tr> </table> <!-- 查询列表 --> <table id="tid" border="1" width="800"> <tr> <td>学生ID</td> <td>班级ID</td> <td>学生姓名</td> <td>年龄</td> <td>生日</td> <td>性别</td> <td>操作</td> </tr> <tr v-for="(student,index) in pageInfo.list" :key="index"> <td>{{student.sid}}</td> <td>{{student.classes.cname}}</td> <td>{{student.sname}}</td> <td>{{student.age}}</td> <td>{{student.birthday}}</td> <td>{{student.gender == 1 ? "男" : "女"}}</td> <td> <a href="">修改</a> <a href="">删除</a> </td> </tr> </table> <!-- 分页条 --> <div id="pageId"> 每页 <select v-model="pageSize" @change="condition(1)"> <option value="1">1</option> <option value="2">2</option> <option value="5">5</option> <option value="10">10</option> </select>条, <a href="#" v-for="index in pageInfo.pages" :key="index" @click.prevent="condition(index)" >{{index}}</a> ,跳转到第 <input type="text" v-model="pageNum" size="5" @keydown.enter="go" />页 </div> </div> </body> </html> <script> new Vue({ el: '#app', data: { pageSize: 2, //每页多少条 pageNum: 1, //第几页 student: { //表单对象 cid: '' }, pageInfo: {}, //分页对象 classesList: [] //班级列表 }, mounted() { // 查询所有 this.condition(1) // 查询所有班级 this.findAllClasses() }, methods: { condition(pageNum) { var url = `/student/condition/${this.pageSize}/${pageNum}`; axios.post(url, this.student) .then( response => { if(response.data.code == 1){ this.pageInfo = response.data.data } else { alert(response.data.message) } }) .catch(error => { }) }, findAllClasses() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, go() { if(parseInt(this.pageNum) == this.pageNum) { this.condition(this.pageNum) } } }, }) </script>
4.2.2 添加
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <body> </head> <div id="app"> <a href="student_list.html">返回列表页</a> <table id="tid" border="1"> <tr> <td>学生</td> <td><input v-model="student.sid" /> </td> </tr> <tr> <td>班级ID</td> <td> <!-- <input name="cId" /> --> <select v-model="student.cid"> <option value="">--请选择--</option> <option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option> </select> </td> </tr> <tr> <td>姓名</td> <td><input v-model="student.sname"/> </td> </tr> <tr> <td>年龄</td> <td><input v-model="student.age" /> </td> </tr> <tr> <td>生日</td> <td><input v-model="student.birthday"/> </td> </tr> <tr> <td>性别</td> <td> <input type="radio" v-model="student.gender" value="1" />男 <input type="radio" v-model="student.gender" value="0" />女 </td> </tr> <tr> <td></td> <td><input type="button" value="添加" @click="addStudent"/></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { student: { //表单对象 cid: '' }, classesList: [] //班级列表 }, mounted() { // 查询所有班级 this.findAllClasses() }, methods: { findAllClasses() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, addStudent() { var url = `/student`; axios.post(url, this.student) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "student_list.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, }, }) </script>
4.2.3 修改
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>编辑学生</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <body> </head> <div id="app"> <a href="student_list.html">返回列表页</a> <table id="tid" border="1"> <tr> <td>学生</td> <td><input v-model="student.sid" /> </td> </tr> <tr> <td>班级ID</td> <td> <!-- <input name="cId" /> --> <select v-model="student.cid"> <option value="">--请选择--</option> <option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option> </select> </td> </tr> <tr> <td>姓名</td> <td><input v-model="student.sname"/> </td> </tr> <tr> <td>年龄</td> <td><input v-model="student.age" /> </td> </tr> <tr> <td>生日</td> <td><input v-model="student.birthday"/> </td> </tr> <tr> <td>性别</td> <td> <input type="radio" v-model="student.gender" value="1" />男 <input type="radio" v-model="student.gender" value="0" />女 </td> </tr> <tr> <td></td> <td><input type="button" value="添加" @click="editStudent"/></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { student: { //表单对象 cid: '' }, classesList: [] //班级列表 }, mounted() { // 查询所有班级 this.findAllClasses() }, methods: { findAllClasses() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data // 查询详情 this.findById() } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, findById() { // 获得id var arr = location.href.split("?id=") var id = arr[1] // 路径 var url = `/student/${id}`; axios.get(url) .then( response => { if(response.data.code == 1){ this.student = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, editStudent() { var url = `/student`; axios.put(url, this.student) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "student_list.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, }, }) </script>
4.2.4 删除
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>班级列表</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> </head> <body> <div id="app"> <a href="index.html">返回首页</a> <a href="student_add.html">添加学生</a> <br/> <!-- 查询条件 --> <table> <tr> <td>班级</td> <td> <select v-model="student.cid"> <option value="">--选择班级--</option> <option v-for="(classes,index) in classesList" :key="index" :value="classes.cid">{{classes.cname}}</option> </select> </td> <td>姓名:</td> <td> <input type="text" placeholder="请输入姓名" v-model="student.sname"size="10"> </td> <td>年龄:</td> <td> <input type="text" placeholder="请输入开始年龄" v-model="student.startAge" size="10"> -- <input type="text" placeholder="请输入结束年龄" v-model="student.endAge" size="10"> </td> <td><input type="button" value="查询" @click="condition(1)"></td> </tr> </table> <!-- 查询列表 --> <table id="tid" border="1" width="800"> <tr> <td>学生ID</td> <td>班级ID</td> <td>学生姓名</td> <td>年龄</td> <td>生日</td> <td>性别</td> <td>操作</td> </tr> <tr v-for="(student,index) in pageInfo.list" :key="index"> <td>{{student.sid}}</td> <td>{{student.classes.cname}}</td> <td>{{student.sname}}</td> <td>{{student.age}}</td> <td>{{student.birthday}}</td> <td>{{student.gender == 1 ? "男" : "女"}}</td> <td> <a :href="'student_edit.html?id='+student.sid">修改</a> <a href="#" @click.prevent="deleteStudent(student.sid)">删除</a> </td> </tr> </table> <!-- 分页条 --> <div id="pageId"> 每页 <select v-model="pageSize" @change="condition(1)"> <option value="1">1</option> <option value="2">2</option> <option value="5">5</option> <option value="10">10</option> </select>条, <a href="#" v-for="index in pageInfo.pages" :key="index" @click.prevent="condition(index)" >{{index}}</a> ,跳转到第 <input type="text" v-model="pageNum" size="5" @keydown.enter="go" />页 </div> </div> </body> </html> <script> new Vue({ el: '#app', data: { pageSize: 2, //每页多少条 pageNum: 1, //第几页 student: { //表单对象 cid: '' }, pageInfo: {}, //分页对象 classesList: [] //班级列表 }, mounted() { // 查询所有 this.condition(1) this.condition(1) this.condition(1) this.condition(1) // 查询所有班级 this.findAllClasses() }, methods: { condition(pageNum) { var url = `/student/condition/${this.pageSize}/${pageNum}`; axios.post(url, this.student) .then( response => { if(response.data.code == 1){ this.pageInfo = response.data.data } else { alert(response.data.message) } }) .catch(error => { }) }, findAllClasses() { var url = `/classes`; axios.get(url) .then( response => { if(response.data.code == 1){ this.classesList = response.data.data } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, go() { if(parseInt(this.pageNum) == this.pageNum) { this.condition(this.pageNum) } }, deleteStudent(id) { if(! confirm("您确定要删除么?")){ return } // 删除 var url = `/student/${id}`; axios.delete(url) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "student_list.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
5. 用户操作
5.1 建表语句
create table tb_user( u_id varchar(32) primary key comment '用户编号', user_name varchar(50) comment '用户名', password varchar(32) comment '密码', gender bit comment '性别,1表示男,0表示女' ); insert into tb_user(u_id,user_name,password,gender) values('u001','jack','1234',1); insert into tb_user(u_id,user_name,password,gender) values('u002','rose','1234',0); insert into tb_user(u_id,user_name,password,gender) values('u003','张三','1234',1);
5.2 后端实现:domain、mapper
- domain
package com.czxy.domain; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; /** * @author manor * */ @Table(name = "tb_user") public class User { @Id @Column(name = "u_id") private String uid; //用户编号 @Column(name = "user_name") private String username; //用户名 @Column(name = "password") private String password; //密码 @Column(name = "gender") private Integer gender; //性别,1表示男,0表示女 public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } @Override public String toString() { return "User{" + "uid='" + uid + '\'' + ", username='" + username + '\'' + ", password='" + password + '\'' + ", gender=" + gender + '}'; } }
- mapper
package com.czxy.mapper; import com.czxy.domain.User; import tk.mybatis.mapper.common.Mapper; /** * @author manor * */ @org.apache.ibatis.annotations.Mapper public interface UserMapper extends Mapper<User> { }
5.3 用户注册
5.3.1 分析
- 用户注册,其实就是添加功能
5.3.2 后端实现
- 编写service,用户名存在不允许注册
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BvY3WRpL-1635379567699)(assets/image-20201012111842320.png)]
package com.czxy.service; import com.czxy.domain.User; import com.czxy.mapper.UserMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource; /** * @author manor * */ @Service @Transactional public class UserService { @Resource private UserMapper userMapper; /** * 用户注册 * @param user * @return */ public boolean register(User user){ // 校验:用户名 User findUser = findByUsername(user.getUsername()); if(findUser != null){ throw new RuntimeException("用户名已存在"); } // 添加 int count = userMapper.insert(user); // 返回 return count == 1; } /** * 通过用户名查询 * @param username * @return */ public User findByUsername(String username){ // 拼凑条件 Example example = new Example(User.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("username", username); // 查询 User user = userMapper.selectOneByExample(example); return user; } }
- 编写controller
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EQSlLBvT-1635379567700)(assets/image-20201012112126781.png)]
package com.czxy.controller; import com.czxy.domain.User; import com.czxy.service.UserService; import com.czxy.vo.BaseResult; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @author manor * */ @RestController @RequestMapping("/user") public class UserController { @Resource private UserService userService; /** * 用户注册 * @param user * @return */ @PostMapping("/register") public BaseResult register(@RequestBody User user) { try { // 注册 boolean result = userService.register(user); // 返回 if(result){ return BaseResult.ok("注册成功"); } else { return BaseResult.error("注册失败"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } } }
5.3.3 前端实现
- 修改首页,跳转到注册页面
<a href="user_register.html">注册</a> |
- 编写注册功能:注册成功跳转到首页
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户注册</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <body> </head> <div id="app"> <a href="index.html">返回首页</a> <table id="tid" border="1"> <tr> <td>用户名</td> <td><input v-model="user.username" /> </td> </tr> <tr> <td>密码</td> <td><input type="password" v-model="user.password" /> </td> </tr> <tr> <td>性别</td> <td> <input type="radio" v-model="user.gender" value="1"> 男 <input type="radio" v-model="user.gender" value="0"> 女 </td> </tr> <tr> <td></td> <td><input type="button" value="注册" @click="register" /></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { user: {}, //用户表单数据 }, methods: { register() { var url = `/user/register`; axios.post(url, this.user) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "index.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
5.4 用户登录
5.4.1 分析
- 用户登录,也是就是一个通过用户名和密码的查询功能
5.4.2 后端实现
- 修改service,添加login方法
/** * 用户登录 * @param user * @return */ public User login (User user){ // 校验:用户名 User findUser = findByUsername(user.getUsername()); if(findUser == null){ throw new RuntimeException("用户名不存在"); } // 登录条件 Example example = new Example(User.class); Example.Criteria criteria = example.createCriteria(); criteria.andEqualTo("username", user.getUsername()); criteria.andEqualTo("password", user.getPassword()); // 查询 User loginUser = userMapper.selectOneByExample(example); return loginUser; }
- 修改controller,添加login 方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G9lSq9bM-1635379567702)(assets/image-20201012113858143.png)]
/** * 用户注册 * @param user * @return */ @PostMapping("/login") public BaseResult login(@RequestBody User user) { try { // 注册 User loginUser = userService.login(user); // 返回 if(loginUser != null ){ // 需要将用户信息响应给浏览器 return BaseResult.ok("登录成功", loginUser); } else { return BaseResult.error("用户名或密码不匹配"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } }
5.4.3 localStorage&sessionStorage详解
- localStorage和sessionStorage都是window对象提供的全局属性,在浏览器中存储key/value对的数据
- localStorage,本地存储,浏览器窗口关闭后,数据保留。
- sessionStorage,会话存储,浏览器窗口关闭后,数据删除。
- 基本操作:存储数据、查询数据、删除数据
功能 | 实例 | |
localStorage | 存储数据 | localStorage.setItem(“键”,“值”) |
查询数据 | localStorage.getItem(“键”) | |
删除数据 | localStorage.removeItem(“键”) | |
sessionStorage | 存储数据 | sessionStorage.setItem(“键”,“值”) |
查询数据 | sessionStorage.getItem(“键”) | |
删除数据 | sessionStorage.removeItem(“键”) |
5.4.4 前端实现
- 修改首页
<a href="user_login.html">注册</a> |
- 编写登录页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户登录</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <body> </head> <div id="app"> <a href="index.html">返回首页</a> <table id="tid" border="1"> <tr> <td>用户名</td> <td><input v-model="user.username" /> </td> </tr> <tr> <td>密码</td> <td><input type="password" v-model="user.password" /> </td> </tr> <tr> <td></td> <td><input type="button" value="登录" @click="login" /></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { user: {}, //用户表单数据 }, methods: { login() { var url = `/user/login`; axios.post(url, this.user) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 将用户信息记录到浏览器 var userStr = JSON.stringify(response.data.data) localStorage.setItem("loginUser", userStr) // 跳转 location.href = "index.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) } }, }) </script>
5.4.5 首页优化
- 修改index.html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <div id="app"> <a href="classes_list.html">班级管理</a> | <a href="student_list.html">学生管理</a> | <span v-if="loginUser != null"> <!-- 登录后显示内容 --> 欢迎 {{loginUser.username}} , <a href="#">退出</a> | </span> <span v-if="loginUser == null"> <!-- 登录前显示内容 --> <a href="user_register.html">注册</a> | <a href="user_login.html">登录</a> | </span> </div> </body> </body> </html> <script> new Vue({ el: '#app', data: { loginUser: null, //登录用户信息 }, mounted() { var userStr = localStorage.getItem("loginUser") if(userStr){ this.loginUser = JSON.parse(userStr) } }, }) </script>
5.5 用户注销
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <div id="app"> <a href="classes_list.html">班级管理</a> | <a href="student_list.html">学生管理</a> | <span v-if="loginUser != null"> <!-- 登录后显示内容 --> 欢迎 {{loginUser.username}} , <a href="#" @click.prevent="logout">退出</a> | </span> <span v-if="loginUser == null"> <!-- 登录前显示内容 --> <a href="user_register.html">注册</a> | <a href="user_login.html">登录</a> | </span> </div> </body> </body> </html> <script> new Vue({ el: '#app', data: { loginUser: null, //登录用户信息 }, mounted() { var userStr = localStorage.getItem("loginUser") if(userStr){ this.loginUser = JSON.parse(userStr) } }, methods: { logout() { localStorage.removeItem("loginUser") location.href = "index.html" } }, }) </script>
5.6 用户注册前校验
5.6.1 分析
5.6.2 后端实现
- 修改 UserController
/** * 用户名校验 * @param user * @return */ @PostMapping("/checkname") public BaseResult checkname(@RequestBody User user) { try { // 注册 User findUser = userService.findByUsername(user.getUsername()); // 返回 if(findUser == null ){ return BaseResult.ok("用户名可用"); } else { return BaseResult.error("用户名不可用"); } } catch (Exception e) { return BaseResult.error(e.getMessage()); } }
5.6.3 前端实现
- 修改注册页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户注册</title> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/axios.js"></script> <style> .red { color: red; } .green { color: green; } </style> <body> </head> <div id="app"> <a href="index.html">返回首页</a> <table id="tid" border="1"> <tr> <td>用户名</td> <td> <input v-model="user.username" @blur="checkname" /> <span :class="{'red': result.code == 0,'green': result.code == 1}" >{{result.message}}</span> </td> </tr> <tr> <td>密码</td> <td><input type="password" v-model="user.password" /> </td> </tr> <tr> <td>性别</td> <td> <input type="radio" v-model="user.gender" value="1"> 男 <input type="radio" v-model="user.gender" value="0"> 女 </td> </tr> <tr> <td></td> <td><input type="button" :disabled="result.code==0" value="注册" @click="register" /></td> </tr> </table> </div> </body> </html> <script> new Vue({ el: '#app', data: { user: {}, //用户表单数据 result: { //查询结果 code: 0 } }, methods: { register() { var url = `/user/register`; axios.post(url, this.user) .then( response => { if(response.data.code == 1){ // 成功提示 alert(response.data.message) // 跳转 location.href = "index.html" } else { alert(response.data.message) } }) .catch(error => { alert(error) }) }, checkname() { var url = `/user/checkname`; axios.post(url, this.user) .then( response => { // 记录查询结果 this.result = response.data }) .catch(error => { alert(error) }) } }, }) </script>