SpringBoot综合实验
1 实验类型
验证型,2学时,必选实验
2 实验目的
掌握Spring Boot项目的开发流程
熟悉Spring MVC、MyBatis、Freemarker等框架的使用
熟悉第三方依赖的引入方法
3 实验要求
使用SSM(Spring、Spring MVC、Mybatis)实现学生表的CRUD操作
可以自行选择框架组合,只要实现CRUD功能即可
4 实验环境
Windows 7 64、Open JDK 23+、Tomcat 11+、Spring Tools 4(STS4)、Visual Studio Code(VS Code)、Microsoft Edge/Chrome/Firefox等浏览器
5 实验步骤
创建Spring Boot项目
-
打开STS4,选择File -> New -> Spring Starter Project
-
输入项目参数;指定项目名称、选择Maven项目、选择Spring Boot版本、勾选Web、MySQL、MyBatis、Freemarker等依赖,点击Finish按钮创建项目
-
打开
pom.xml
,手工添加以下依赖:
依赖名 | 描述 |
---|---|
spring-boot-starter-validation | 有效性校验 |
validation-api | 有效性校验 |
poi | POI操作Excel |
poi-ooxml | POI操作Excel |
sqlite-jdbc | Sqlite驱动 |
Stu/pom.xml | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
|
配置
-
打开
Stu/src/main/resources/application.properties
文件,配置Sqlite数据库连接信息,参考代码如下: -
创建文件:
Stu/src/main/resources/application-dev.properties
文件,设置数据库初始化,参考代码如下: -
设定Mybatis配置参数,参考代码如下:
完整配置文件如下:
创建学生表
-
编写学生表定义及测试数据SQL代码,存放在
src/main/resources/sql
stu_schema.sql 前步配置中已设置自动执行这两个脚本
-
创建实体类:
xust.demo.stu.domain.Student
xust.demo.stu.domain.Student类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
/* * File name : Student.java 2023-04-20 * @generated May 28, 2023, 9:37:49 AM * @author XUST * Copyright 2023 XUST. All rights reserved. */ package xust.demo.stu.domain; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; //import javax.validation.constraints.Email; import javax.validation.constraints.Max; import javax.validation.constraints.Min; //import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; /** * Class Student * 学生表 * @author XUST * @version 1.0, 2023-04-20 */ public class Student{ private static final long serialVersionUID = -8178158848305435288L; public static ObjectMapper objectMapper = new ObjectMapper(); /** * Id */ private String id; /** * 学号 */ @NotNull private String no; /** * 姓名 */ private String name; /** * 性别 */ private String gender; /** * 年龄 */ private Integer age; /** * 所在系 */ private String dept; /** * Id */ public String getId(){ return id; } /** * Id */ public void setId(String newValue){ id = newValue; } /** * 学号 */ public String getNo(){ return no; } /** * 学号 */ public void setNo(String newValue){ no = newValue; } /** * 姓名 */ public String getName(){ return name; } /** * 姓名 */ public void setName(String newValue){ name = newValue; } /** * 性别 */ public String getGender(){ return gender; } /** * 性别 */ public void setGender(String newValue){ gender = newValue; } /** * 年龄 */ public Integer getAge(){ return age; } /** * 年龄 */ public void setAge(Integer newValue){ age = newValue; } /** * 所在系 */ public String getDept(){ return dept; } /** * 所在系 */ public void setDept(String newValue){ dept = newValue; } @Override public String toString() { String res = ""; try { res = objectMapper.writeValueAsString(this); } catch (Exception e) { } return res; } }
实现CRUD操作
-
创建数据访问接口:
xust.demo.stu.dao.StudentMapper
,定义CRUD操作方法,参考代码如下: -
创建数据访问代码文件:
Stu/src/main/resources/mapper/StudentMapper.xml
文件,实现CRUD操作,参考代码如下: -
创建服务接口:
xust.demo.stu.service.StudentService
接口和实现类:xust.demo.stu.service.StudentServiceImpl
,实现CRUD操作,参考代码如下:xust.demo.stu.service.StudentServiceImpl实现类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
package xust.demo.stu.service; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.util.CellRangeAddress; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import xust.Result; import xust.ErrEnum; import xust.demo.stu.dao.StudentDao; import xust.demo.stu.domain.Student; /** * Class StudentServiceImpl * StudentService interface implementation. * @generated May 28, 2023, 9:37:49 AM * @author XUST * @version 1.0, 2023-04-20 */ @Service public class StudentServiceImpl implements StudentService{ private final static Logger log = LoggerFactory.getLogger(StudentServiceImpl.class); @Autowired private StudentDao studentDao; @Override public Result<Student> create(Student newValue) { Result<Student> oc = new Result<Student>(); try{ //newValue.setSys_create_date(new Date()); newValue.setId(UUID.randomUUID().toString()); int effected = studentDao.create(newValue); if(effected > 0){ oc.setData(newValue); }else{ oc.setErr(ErrEnum.DB_CREATE_FAIL); } }catch(Exception e){ oc.setErr(ErrEnum.DB_CREATE_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } @Override public Result<Integer> deleteAll() { Result<Integer> oc = new Result<Integer>(); try{ oc.setData(studentDao.deleteAll()); }catch(Exception e){ oc.setErr(ErrEnum.DB_DELETE_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } @Override public Result<Integer> deleteItems(List<String> items) { Result<Integer> oc = new Result<Integer>(); try{ oc.setData(studentDao.deleteItems(items)); }catch(Exception e){ oc.setErr(ErrEnum.DB_DELETE_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } @Override public Result<Integer> delete(Map<String, Object> params) { Result<Integer> oc = new Result<Integer>(); try { oc.setData(studentDao.delete(params)); }catch(Exception e) { oc.setErr(ErrEnum.DB_DELETE_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } @Override public Result<Integer> update(Student newValue) { Result<Integer> oc = new Result<Integer>(); try{ //newValue.setSys_last_update_date(new Date()); oc.setData(studentDao.update(newValue)); }catch(Exception e){ oc.setErr(ErrEnum.DB_UPDATE_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } @Override public Result<Integer> size(Map<String, Object> params) { Result<Integer> oc = new Result<Integer>(); try { oc.setData(studentDao.size(params)); }catch(Exception e) { oc.setErr(ErrEnum.DB_SIZE_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } @Override public Result<List<Student>> getPage(Map<String, Object> params, int pageNum, int pageSize) { Result<List<Student>> oc = new Result<List<Student>>(); oc.setData(new ArrayList<Student>()); try { oc.setData(studentDao.getPage(params, pageNum, pageSize)); }catch(Exception e) { oc.setErr(ErrEnum.DB_PAGE_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } public Result<Boolean> buildXLSTemplate(String worksheet_name, String title, OutputStream output) { Result<Boolean> oc = new Result<Boolean>(); try { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(worksheet_name); // Header title HSSFRow row1 = sheet.createRow(0); HSSFCell cell = row1.createCell(0); cell.setCellValue(title); sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 5)); // Header HSSFRow row2 = sheet.createRow(1); // 设置列标题 row2.createCell(0).setCellValue("学号"); row2.createCell(1).setCellValue("姓名"); row2.createCell(2).setCellValue("性别"); row2.createCell(3).setCellValue("年龄"); row2.createCell(4).setCellValue("所在系"); wb.write(output); //wb.close(); } catch (Exception e) { oc.setErr(ErrEnum.EXPORT_EXCEL_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } @Override public Result<Boolean> export2XLS(List<Student> data, String worksheet_name, String title, OutputStream output) { Result<Boolean> oc = new Result<Boolean>(); try { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(worksheet_name); // Header title HSSFRow row1 = sheet.createRow(0); HSSFCell cell = row1.createCell(0); cell.setCellValue(title); sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 5)); // Header HSSFRow row2 = sheet.createRow(1); // 设置列标题 row2.createCell(0).setCellValue("Id"); row2.createCell(1).setCellValue("学号"); row2.createCell(2).setCellValue("姓名"); row2.createCell(3).setCellValue("性别"); row2.createCell(4).setCellValue("年龄"); row2.createCell(5).setCellValue("所在系"); // 填充数据 int row_number = 2; for (Student item : data) { HSSFRow row_new = sheet.createRow(row_number++); row_new.createCell(0).setCellValue(NullValue(item.getId())); row_new.createCell(1).setCellValue(NullValue(item.getNo())); row_new.createCell(2).setCellValue(NullValue(item.getName())); row_new.createCell(3).setCellValue(NullValue(item.getGender())); row_new.createCell(4).setCellValue(NullValue(item.getAge())); row_new.createCell(5).setCellValue(NullValue(item.getDept())); } wb.write(output); //wb.close(); } catch (Exception e) { oc.setErr(ErrEnum.EXPORT_EXCEL_FAIL); oc.setDetail(e.getLocalizedMessage()); log.error(e.getMessage()); } return oc; } private String NullValue(Object o) { return null == o ? "" : o.toString(); } }
-
创建控制类:
StudentController
,实现学生表CRUD操作Web Api(包名:xust.demo.stu.controller
),参考代码如下:xust.demo.stu.controller.StudentController类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
/* * File name : StudentController.java 2023-04-20 * Copyright 2023 XUST. All rights reserved. */ package xust.demo.stu.controller; import java.util.HashMap; import java.util.Map; import java.io.OutputStream; import java.util.ArrayList; import java.net.URLEncoder; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import java.util.List; import org.springframework.validation.annotation.Validated; import xust.Result; import xust.Result4GetPage; import xust.demo.stu.domain.DeleteItems4Student; import xust.demo.stu.domain.GetPage4Student; import xust.demo.stu.domain.Student; import xust.demo.stu.service.StudentServiceImpl; import java.util.TreeMap; /** * Class StudentController * Student action class. * @generated May 28, 2023, 9:37:49 AM * @author XUST * @version 1.0, 2023-04-20 */ @RestController @RequestMapping("/demo/Student") public class StudentController{ private final static Logger log = LoggerFactory.getLogger(StudentController.class); @Autowired private StudentServiceImpl studentService = null; @RequestMapping(value = "/list-jquery") public ModelAndView doListJquery(){ ModelAndView mv = new ModelAndView("/demo/Student/list-jquery"); return mv; } @RequestMapping(value = "/list-bootstrap") public ModelAndView doListBootstrap(){ ModelAndView mv = new ModelAndView("/demo/Student/list-bootstrap"); return mv; } @PostMapping(value = "/add") public Result<Student> doAdd(@RequestBody(required=true) @Validated Student o){ Result<Student> oc = studentService.create(o); return oc; } @PostMapping(value="/delete") public Result<Integer> doDelete(@RequestBody(required=true) List<String> ids){ Result<Integer> oc = studentService.deleteItems(ids); return oc; } @PostMapping(value="/update") public Result<Integer> doUpdate(@RequestBody(required=true) @Validated Student o){ Result<Integer> oc = studentService.update(o); return oc; } @PostMapping(value="/getPage") public Result<Result4GetPage<List<Student>>> doGetPage(@RequestBody(required=true) @Validated GetPage4Student p){ Result<Result4GetPage<List<Student>>> res = new Result<Result4GetPage<List<Student>>>(); Map<String, Object> params = new HashMap<String, Object>(); params.put("id", p.getId()); Result<Integer> oc_size = studentService.size(params); if(oc_size.getCode() == 0){ Result<List<Student>> oc_getPage = studentService.getPage(params, p.getPageNum(), p.getPageSize()); if(oc_getPage.getCode() == 0){ Result4GetPage<List<Student>> result = new Result4GetPage<List<Student>>(); result.setTotal(oc_size.getData()); result.setData(oc_getPage.getData()); res.setData(result); }else{ res.setCode(oc_getPage.getCode()); res.setMessage(oc_getPage.getMessage()); } }else{ res.setCode(oc_size.getCode()); res.setMessage(oc_size.getMessage()); } return res; } @PostMapping(value="/template") public void doTemplate(HttpServletResponse response){ try { String file_name = "学生表.xls"; response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setHeader("Content-disposition", "attachment;filename=" + file_name); response.flushBuffer(); OutputStream outputStream = response.getOutputStream(); studentService.buildXLSTemplate("学生表", "学生表", outputStream); outputStream.flush(); outputStream.close(); } catch (Exception e) { log.error(e.getLocalizedMessage()); } } @PostMapping(value="/toExcel") public void doToExcel(HttpServletResponse response, @RequestBody(required=true) @Validated GetPage4Student p){ Map<String, Object> params = new HashMap<String, Object>(); params.put("id", p.getId()); Result<Integer> oc_size = studentService.size(params); String title="学生表"; OutputStream outputStream = null; if(oc_size.getCode() == 0){ Result<List<Student>> oc_getPage = studentService.getPage(params, 1, 2000); if(oc_getPage.getCode() == 0){ try { outputStream = response.getOutputStream(); response.setContentType("application/vnd.ms-excel;charset=utf-8"); String fileName = URLEncoder.encode(title + ".xls", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName); response.flushBuffer(); studentService.export2XLS(oc_getPage.getData(), title, title, outputStream); outputStream.flush(); outputStream.close(); } catch (Exception e) { log.error("导出Excel异常", e); }finally { try { if(outputStream != null){ outputStream.close(); } } catch (Exception e1) { log.error("导出Excel关闭异常", e1); } } } } } }
测试
-
在Spring Boot Dashbord启动Stu工程
-
使用CRUD测试代码:
Stu/api_test.http
(Rest Client代码),参考代码如下: -
分别点击各REST Client链接,检查返回结果是否正确
Stu/api.md
中包含各Web Api的使用说明,可据此检查返
学生表
学生表增
调用地址: http://my_host:8080/Demo/stu/Student/add
请求方式: POST
返回类型: JSON
请求参数(Headers)
参数 | 值 |
---|---|
content-type | application/json |
请求参数(Query)
请求参数(Body)
{
"id": String, //Id
"no": String, //学号
"name": String, //姓名
"gender": String, //性别
"age": Integer, //年龄
"dept": String //所在系
}
请求示例
POST http://localhost:8080/Demo/stu/Student/add HTTP/1.1
content-type: application/json
{
"id": "X100",
"no": "X101",
"name": "X102",
"gender": "X103",
"age": 104,
"dept": "X105"
}
Rest Client请求格式
正常返回示例
失败返回示例
{
"code": 1001,
"message": "创建失败!",
"detail": "[SQLITE_CONSTRAINT_UNIQUE] A UNIQUE constraint failed (UNIQUE constraint failed: Student.no)",
"data": null
}
错误码定义
错误码 | 错误信息 | 描述 |
---|---|---|
0 | 成功 |
学生表删
调用地址: http://my_host:8080/Demo/stu/Student/delete
请求方式: POST
返回类型: JSON
请求参数(Headers)
参数 | 值 |
---|---|
content-type | application/json |
请求参数(Query)
请求参数(Body)
请求示例
POST http://localhost:8080/Demo/stu/Student/delete HTTP/1.1
content-type: application/json
["1", "2"]
Rest Client请求格式
正常返回示例
失败返回示例
错误码定义
错误码 | 错误信息 | 描述 |
---|---|---|
0 | 成功 |
学生表改
调用地址: http://my_host:8080/Demo/stu/Student/update
请求方式: POST
返回类型: JSON
请求参数(Headers)
参数 | 值 |
---|---|
content-type | application/json |
请求参数(Query)
请求参数(Body)
{
"id": String, //Id
"no": String, //学号
"name": String, //姓名
"gender": String, //性别
"age": Integer, //年龄
"dept": String //所在系
}
请求示例
POST http://localhost:8080/Demo/stu/Student/update HTTP/1.1
content-type: application/json
{
"id": "X100",
"no": "X101",
"name": "X102",
"gender": "X103",
"age": 104,
"dept": "X105"
}
Rest Client请求格式
正常返回示例
失败返回示例
{
"code": 1001,
"message": "创建失败!",
"detail": "[SQLITE_CONSTRAINT_UNIQUE] A UNIQUE constraint failed (UNIQUE constraint failed: Student.no)",
"data": null
}
错误码定义
错误码 | 错误信息 | 描述 |
---|---|---|
0 | 成功 |
学生表查
调用地址: http://my_host:8080/Demo/stu/Student/getPage
请求方式: POST
返回类型: JSON
请求参数(Headers)
参数 | 值 |
---|---|
content-type | application/json |
请求参数(Query)
请求参数(Body)
请求示例
POST http://localhost:8080/Demo/stu/Student/getPage HTTP/1.1
content-type: application/json
{
"pageNum": 1,
"pageSize": 5
}
Rest Client请求格式
正常返回示例
{
"code": 0,
"message": "操作成功!",
"detail": null,
"data": {
"total": 4,
"data": [
{
"id": "X100",
"no": "X101",
"name": "X102",
"gender": "X103",
"age": 104,
"dept": "X105"
}
]
}
}
失败返回示例
错误码定义
错误码 | 错误信息 | 描述 |
---|---|---|
0 | 成功 |
基于jQuery的界面
-
打开
Stu/src/main/resources/templates
目录,创建目录:demo/Student
-
创建
list-jquery.f
文件,用于显示学生表,参考代码如下:list-jquery.f 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>学生表表管理</title> </head> <body> <h3>学生表信息管理</h3> <div id="queryForm"> <label for="id">id</label> <input type="text" id="id" name="id" value=""> <button id="buttonQuery">查询</button> <button id="buttonAdd">添加</button> </div> <!-- 学生表列表 --> <table id="objTable"> <thead> <tr> <th style="display:none;">Id</th> <th>学号</th> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>所在系</th> <th>操作</th> </tr> </thead> <tbody> <!-- 这里用jQuery动态生成表格行 --> </tbody> </table> </body> <div id="objModel"> <div id="objModelContent"> <span id="close">×</span> <h2 id="updateTitle">修改学生表记录</h2> <div id="updateForm"> <input type="hidden" id="update-id" name="id"> <div class="mb-3"> <label for="update-no" class="form-label">学号</label> <input type="text" id="update-no" name="no" required> </div> <div class="mb-3"> <label for="update-name" class="form-label">姓名</label> <input type="text" id="update-name" name="name" required> </div> <div class="mb-3"> <label for="update-gender" class="form-label">性别</label> <input type="text" id="update-gender" name="gender" required> </div> <div class="mb-3"> <label for="update-age" class="form-label">年龄</label> <input type="text" id="update-age" name="age" required> </div> <div class="mb-3"> <label for="update-dept" class="form-label">所在系</label> <input type="text" id="update-dept" name="dept" required> </div> <button id="updateSave">保存</button> </div> </div> </div> <!-- 弹出框 --> <div id="popup"> <div id="popupHeader"> <h3 id="popupTitle">消息</h3> <button id="popupClose">X</button> </div> <div id="popupBody"> <p>消息内容</p> </div> </div> <script src="/jquery/jquery-3.6.1.min.js"></script> <script> const idsUpdate = ["update-id","update-no","update-name","update-gender","update-age","update-dept"]; $(document).ready(function () { getPage(); //注册查询 $('#buttonQuery').click(function () { getPage() }); $('#buttonAdd').click(function () { showModel4Add(); }); //注册关闭错误信息 $('#popupClose').click(function () { $('#popup').hide(); }) //注册关闭错误信息 $('#close').click(function () { $('#objModel').hide(); }) }); /** * 从修改对话框提取学生表信息 */ function loadFromUI(ids) { var res = {}; ids.forEach((id) => { res[id.match(/-(\w+)/)[1]] = $("#" + id).val(); }); return res; } /** * 将学生表信息填充到有val属性的界面 */ function fill2Val(ids, obj) { ids.forEach((id) => { //id约定以成员名结束,如-id $("#" + id).val(obj[id.match(/-(\w+)$/)[1]]); }); } /** * 将学生表信息填充到有text属性的界面 */ function fill2Text(ids, obj) { ids.forEach((id) => { //id约定以成员名结束,如-id $("#" + id).text(obj[id.match(/-(\w+)$/)[1]]); //console.log(id + ":" + id.match(/-(\w+)$/)[1] + "=" + obj[id.match(/-(\w+)$/)[1]]); }); } function buildRowIds(id) { return [ "row-" + id + "-id", "row-" + id + "-no", "row-" + id + "-name", "row-" + id + "-gender", "row-" + id + "-age", "row-" + id + "-dept" ]; } /** * 显示修改学生表信息对话框 */ function update(id) { // 获取学生表信息 $.ajax({ url: '/demo/Student/getPage', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id": id, "pageNum": 1, "pageSize": 1 }), success: function (response) { if (response.code == 0) { $.each(response.data.data, function (index, obj) { showModel4Update(obj); }); } else { showError(response.message); } }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 学生表信息对话框用作修改 */ function showModel4Update(obj) { fill2Val(idsUpdate, obj); $('#updateTitle').text("修改学生表信息"); $('#updateSave').text("修改"); //注册修改 $('#updateSave').off(); $('#updateSave').click(function () { var obj = loadFromUI(idsUpdate); updateObj(obj) }); $("#objModel").show(); } /** * 学生表信息对话框用作增加 */ function showModel4Add() { fill2Val(idsUpdate, { "id": "", "no": "", "name": "", "gender": "", "age": "", "dept": "" }); $('#updateTitle').text("新建学生表信息"); $('#updateSave').text("新建"); //注册增加 $('#updateSave').off(); $('#updateSave').click(function () { var obj = loadFromUI(idsUpdate); addObj(obj) }); $("#objModel").show(); } /** * 增加学生表信息 */ function addObj(obj) { // 获取学生表信息 $.ajax({ url: '/demo/Student/add', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id" : obj.id, "no" : obj.no, "name" : obj.name, "gender" : obj.gender, "age" : obj.age, "dept" : obj.dept }), success: function (response) { if (response.code == 0) { const obj_new = response.data; appendRow(obj_new); fill2Text(buildRowIds(obj_new.id), obj_new); $("#objModel").hide(); } showError(response.message); }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 修改学生表信息 */ function updateObj(obj) { // 获取学生表信息 $.ajax({ url: '/demo/Student/update', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id" : obj.id, "no" : obj.no, "name" : obj.name, "gender" : obj.gender, "age" : obj.age, "dept" : obj.dept }), success: function (response) { if (response.code == 0) { fill2Text(buildRowIds(obj.id), obj); $("#objModel").hide(); } showError(response.message); }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 获取学生表信息 */ function getPage() { // 获取学生表信息 $.ajax({ url: '/demo/Student/getPage', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id": $('#id').val(), "pageNum": 1, "pageSize": 1 }), success: function (response) { if (response.code == 0) { $('#objTable tbody').empty(); // 遍历学生表信息,生成表格行 $.each(response.data.data, function (index, obj) { appendRow(obj); }); } else { showError(response.message); } }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 学生表列表中新增一行 */ function appendRow(obj) { var tr = $('<tr id="row-' + obj.id + '">'); tr.append('<td style="display:none;" id="row-' + obj.id + '-id">' + obj.id + '</td>'); tr.append('<td id="row-' + obj.id + '-no">' + obj.no + '</td>'); tr.append('<td id="row-' + obj.id + '-name">' + obj.name + '</td>'); tr.append('<td id="row-' + obj.id + '-gender">' + obj.gender + '</td>'); tr.append('<td id="row-' + obj.id + '-age">' + obj.age + '</td>'); tr.append('<td id="row-' + obj.id + '-dept">' + obj.dept + '</td>'); tr.append('<td><button onclick="update(\'' + obj.id + '\')">编辑</button><button onclick="del(\'' + obj.id + '\')">删除</button></td>'); $('#objTable tbody').append(tr); } /* * 删除 */ function del(id) { $.ajax({ url: "/demo/Student/delete", type: "POST", contentType: "application/json", data: JSON.stringify([id]), success: function (response) { showError(response.message); $("#row-" + id).remove(); }, error: function (xhr, status, error) { showError(error.responseJSON.message); } }); } function showError(message) { $('#popupBody').text(message); $('#popup').show(); } </script> <!-- 学生表列表 --> <style> #objTable { border-collapse: collapse; width: 100%; } #objTable th, #objTable td { border: 1px solid #ddd; padding: 8px; text-align: center; } #objTable th { background-color: #f2f2f2; } </style> <!-- 学生表信息框 --> <style> /* 模式对话框样式 */ #objModel { display: none; position: fixed; top: 50%; left: 50%; z-index: 666; overflow: auto; background-color: #fff; border: 1px solid #ccc; padding: 10px; } #modalContent { background-color: #fff; margin: 10% auto; padding: 20px; border: 1px solid #888; width: 50%; } #close { color: #aaa; float: right; font-size: 28px; font-weight: bold; } #close:hover, #close:focus { color: black; text-decoration: none; cursor: pointer; } </style> <!-- 错误消息框 --> <style> #popup { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #fff; border: 1px solid #ccc; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 9999; display: none; } #popupHeader { padding: 10px; background-color: #f5f5f5; border-bottom: 1px solid #ccc; position: relative; } #popupTitle { margin: 0; } #popupClose { position: absolute; top: 5px; right: 5px; border: none; background-color: transparent; font-size: 20px; cursor: pointer; } #popupBody { padding: 10px; } </style> </html>
-
在浏览器中打开
http://localhost:8080/demo/Student/list-jquery
基于Bootstrap的界面
-
打开
Stu/src/main/resources/templates
目录 -
创建
list-bootstrap.f
文件,用于显示学生表,参考代码如下:list-bootstrap.f 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>学生表管理</title> <!-- 引入Bootstrap 5和相关的JavaScript库 --> <link rel="stylesheet" href="/bootstrap-5.2.3-dist/css/bootstrap.min.css"> <style> html, body { height: 100%; } .row { height: 100%; } .container-fluid { height: 100%; } </style> </head> <body> <h3>学生表信息管理</h3> <nav class="navbar navbar-expand-sm navbar-light bg-light"> <div class="row g-3 align-items-center"> <div class="input-group input-group-sm" style="width: 250px;"> <span class="input-group-text" id="label-id">id</span> <input type="text" class="form-control" id="id" name="id" value="" placeholder="id" aria-label="id" aria-describedby="label-id" style="width: 150px;"> <!-- <button class="btn btn-outline-secondary" type="button" id="btn-label-no-clear">清除</button> --> </div> <div class="col-auto"> <button id="buttonQuery" class="btn btn-primary btn-sm">查询</button> </div> <div class="col-auto"> <button id="buttonAdd" class="btn btn-success btn-sm">添加</button> </div> </div> </nav> <!-- 学生表列表 --> <table class="table table-bordered table-striped"> <thead> <tr> <th style="display:none;">Id</th> <th>学号</th> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>所在系</th> <th>操作</th> </tr> </thead> <tbody id="objTableBody"> <!-- 这里用JavaScript动态生成表格行 --> </tbody> </table> <nav class="navbar navbar-expand-sm navbar-light bg-light fixed-bottom bg-body-tertiary"> <div class="row g-3 align-items-center"> <div class="input-group input-group-sm" style="width: 150px;"> <label class="input-group-text" for="pageSize">每页显示:</label> <select class="form-control" id="pageSize" name="pageSize" required> <option value="10" selected>10</option> <option value="30">30</option> <option value="100">100</option> </select> </div> <div class="input-group input-group-sm" style="width: 150px;"> <label class="input-group-text" for="total">总页数:</label> <input type="number" min="1" class="form-control" id="total" value="0" disabled> </div> <div class="input-group input-group-sm" style="width: 150px;"> <label class="input-group-text" for="pageSize">当前页码:</label> <input type="number" min="1" class="form-control" id="pageNum" value="0"> </div> <div class="col-auto"> <button id="buttonTo" class="btn btn-success btn-sm">跳转</button> </div> </div> </nav> <!-- 学生表信息对话框 --> <div class="modal fade" data-bs-backdrop="static" data-bs-keyboard="false" id="objModel" tabindex="-1" aria-labelledby="objModelTitle" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="objModelTitle">修改学生表记录</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <form id="updateForm"> <input type="hidden" id="update-id" name="id"> <div class="mb-3"> <label for="update-no" class="form-label">学号</label> <input type="text" class="form-control" id="update-no" name="no" required> </div> <div class="mb-3"> <label for="update-name" class="form-label">姓名</label> <input type="text" class="form-control" id="update-name" name="name" required> </div> <div class="mb-3"> <label for="update-gender" class="form-label">性别</label> <input type="text" class="form-control" id="update-gender" name="gender" required> </div> <div class="mb-3"> <label for="update-age" class="form-label">年龄</label> <input type="text" class="form-control" id="update-age" name="age" required> </div> <div class="mb-3"> <label for="update-dept" class="form-label">所在系</label> <input type="text" class="form-control" id="update-dept" name="dept" required> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button> <button type="button" class="btn btn-primary" id="updateSave">保存</button> </div> </div> </div> </div> <!-- 错误信息弹窗 --> <div class="modal fade" id="errorModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="errorModalTitle" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <!-- <div class="modal-header"> <h5 class="modal-title" id="errorModalTitle">信息</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> --> <div class="modal-body" id="errorModalBody"> <!-- 这里用JavaScript动态生成错误信息 --> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button> </div> </div> </div> </div> <script src="/bootstrap-5.2.3-dist/js/bootstrap.bundle.min.js"></script> <script src="/jquery/jquery-3.6.1.min.js"></script> <script> const idsUpdate = ["update-id","update-no","update-name","update-gender","update-age","update-dept"]; $(document).ready(function () { $('#pageNum').val(1); getPage(); //注册查询 $('#buttonQuery').click(function () { $('#pageNum').val(1); getPage() }); $('#buttonAdd').click(function () { showModel4Add(); }); $('#updateSave').click(function () { var obj = loadFromUI(idsUpdate); addObj(obj) }); $('#buttonTo').click(function () { getPage(); }); //注册关闭错误信息 $('#close').click(function () { $('#objModel').modal("hide"); }) }); /** * 从修改对话框提取学生表信息 */ function loadFromUI(ids) { var res = {}; ids.forEach((id) => { res[id.match(/-(\w+)/)[1]] = $("#" + id).val(); }); return res; } /** * 将学生表信息填充到有val属性的界面 */ function fill2Val(ids, obj) { ids.forEach((id) => { //id约定以成员名结束,如-id $("#" + id).val(obj[id.match(/-(\w+)$/)[1]]); }); } /** * 将学生表信息填充到有text属性的界面 */ function fill2Text(ids, obj) { ids.forEach((id) => { //id约定以成员名结束,如-id $("#" + id).text(obj[id.match(/-(\w+)$/)[1]]); //console.log(id + ":" + id.match(/-(\w+)$/)[1] + "=" + obj[id.match(/-(\w+)$/)[1]]); }); } function buildRowIds(id) { return [ "row-" + id + "-id", "row-" + id + "-no", "row-" + id + "-name", "row-" + id + "-gender", "row-" + id + "-age", "row-" + id + "-dept" ]; } /** * 显示修改学生表信息对话框 */ function update(id) { // 获取学生表信息 $.ajax({ url: '/demo/Student/getPage', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id": id, "pageNum": 1, "pageSize": 1 }), success: function (response) { if (response.code == 0) { $.each(response.data.data, function (index, obj) { showModel4Update(obj); }); } else { showError(response.message); } }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 学生表信息对话框用作修改 */ function showModel4Update(obj) { fill2Val(idsUpdate, obj); $('#updateTitle').text("修改学生表信息"); $('#updateSave').text("修改"); //注册修改 $('#updateSave').off(); $('#updateSave').click(function () { var obj = loadFromUI(idsUpdate); updateObj(obj) }); $("#objModel").modal("show"); } /** * 学生表信息对话框用作增加 */ function showModel4Add() { fill2Val(idsUpdate, { "id" : "", "no" : "", "name" : "", "gender" : "", "age" : "", "dept" : "" }); $('#updateTitle').text("新建学生表信息"); $('#updateSave').text("新建"); //注册增加 $('#updateSave').off(); $('#updateSave').click(function () { var obj = loadFromUI(idsUpdate); addObj(obj) }); $("#objModel").modal("show"); } /** * 增加学生表信息 */ function addObj(obj) { // 获取学生表信息 $.ajax({ url: '/demo/Student/add', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id" : obj.id, "no" : obj.no, "name" : obj.name, "gender" : obj.gender, "age" : obj.age, "dept" : obj.dept }), success: function (response) { if (response.code == 0 && response.data != null) { const obj_new = response.data; appendRow(obj_new); fill2Text(buildRowIds(obj_new.id), obj_new); $("#objModel").modal("hide"); } showError(response.message); }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 修改学生表信息 */ function updateObj(obj) { // 获取学生表信息 $.ajax({ url: '/demo/Student/update', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id" : obj.id, "no" : obj.no, "name" : obj.name, "gender" : obj.gender, "age" : obj.age, "dept" : obj.dept }), success: function (response) { if (response.code == 0 && response.data > 0) { fill2Text(buildRowIds(obj.id), obj); $("#objModel").modal("hide"); } showError(response.message); }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 获取学生表信息 */ function getPage() { // 获取学生表信息 const pageNum = $('#pageNum').val(); const pageSize = $('#pageSize').val(); $.ajax({ url: '/demo/Student/getPage', type: 'POST', dataType: "json", contentType: 'application/json', data: JSON.stringify({ "id": $('#id').val(), "pageNum": pageNum, "pageSize": pageSize }), success: function (response) { if (response.code == 0) { $('#objTableBody').empty(); // 遍历学生表信息,生成表格 $.each(response.data.data, function (index, obj) { appendRow(obj); }); $('#pagination').empty(); //更新分页 var total = Math.ceil(response.data.total / parseInt(pageSize)); $('#total').val(total); for (var i = 1; i <= total; i++) { var li = $("<li class='page-item'></li>"); var a = $("<a class='page-link' href='#'>" + i + "</a>"); a.click(function () { $('#pageNum').val($(this).text()); getPage(); }); li.append(a); $("#pagination").append(li); } } else { showError(response.message); } }, error: function (error) { showError(error.responseJSON.message); } }); } /** * 学生表列表中新增一行 */ function appendRow(obj) { var tr = $('<tr id="row-' + obj.id + '">'); tr.append('<td style="display:none;" id="row-' + obj.id + '-id">' + obj.id + '</td>'); tr.append('<td id="row-' + obj.id + '-no">' + obj.no + '</td>'); tr.append('<td id="row-' + obj.id + '-name">' + obj.name + '</td>'); tr.append('<td id="row-' + obj.id + '-gender">' + obj.gender + '</td>'); tr.append('<td id="row-' + obj.id + '-age">' + obj.age + '</td>'); tr.append('<td id="row-' + obj.id + '-dept">' + obj.dept + '</td>'); tr.append('<td><button type="button" class="btn btn-outline-primary btn-sm" onclick="update(\'' + obj.id + '\')">编辑</button><button type="button" class="btn btn-outline-danger btn-sm" onclick="del(\'' + obj.id + '\')">删除</button></td>'); $('#objTableBody').append(tr); } /* * 删除 */ function del(id) { $.ajax({ url: "/demo/Student/delete", type: "POST", contentType: "application/json", data: JSON.stringify([id]), success: function (response) { showError(response.message); if (response.code == 0 && response.data > 0) { $("#row-" + id).remove(); } }, error: function (xhr, status, error) { showError(error.responseJSON.message); } }); } function showError(message) { $('#errorModalBody').text(message); $('#errorModal').modal("show"); } </script> </body> </html>
-
在浏览器中打开
http://localhost:8080/demo/Student/list-bootstrap
拓展练习
- 实现课程表的增、删、改、查操作