项目名称:希望小学学生管理系统
项目需求:
1、学生信息的添加,删除,修改和编辑
2、需要管理的信息:
学生:学生学号,姓名,性别,班级,住址,出生日期
成绩:课程编号,学生学号,成绩
课程:课程编号,课程名称
教师:教师编号,姓名,性别,住址,出生日期
前端:html+css+js
后端:mysql+后台系统(springboot)
主表:
学生表——stu
名称 | 字段名 | 类型和长度 |
---|---|---|
id | id | int(11) |
学号 | stu_no | varchar(255) |
姓名 | stu_name | varchar(255) |
性别 | gender | int(11) |
班级 | stu_class | varchar(255) |
住址 | stu_address | varchar(255) |
出生日期 | stu_birthday | datetime(0) |
成绩表——grade
名称 | 字段名 | 类型和长度 |
---|---|---|
id | id | int(11) |
课程id | cou_id | int(11) |
学生id | stu_id | int(11) |
分数 | score | int(11) |
课程表——course
名称 | 字段名 | 类型和长度 |
---|---|---|
id | id | int(11) |
课程编号 | course_no | varchar(255) |
课程名称 | course_name | varchar(255) |
教师表——teacher
名称 | 字段名 | 类型和长度 |
---|---|---|
id | id | int(11) |
教师编号 | tea_no | varchar(255) |
姓名 | tea_name | varchar(255) |
性别 | gender | int(11) |
住址 | tea_address | varchar(255) |
出生日期 | tea_birthday | datetime(0) |
关联表:
学生课程关联表
名称 | 字段名 | 类型和长度 |
---|---|---|
id | id | int(11) |
学生id | stu_id | int(11) |
课程id | cou_id | int(11) |
教师课程关联表
名称 | 字段名 | 类型和长度 |
---|---|---|
id | id | int(11) |
教师id | tea_id | int(11) |
课程id | cou_id | int(11) |
目录介绍:
css:样式修饰文件
js:这个也不知道咋个介绍法,大名叫javaScript
static:放静态资源的文件夹,图片啥的
view:放页面的文件夹
很丑,不过不慌,以后慢慢修饰呗,功能先整上去
首页
添加/编辑页面
index.html
<html>
<head>
<meta charset="utf-8">
<title>学生管理系统title>
<link rel="stylesheet" type="text/css" href="../css/index.css">
<script src="../js/base.js">script>
<script src="../js/jquery.js">script>
<script src="../js/index.js">script>
head>
<body>
<div class="main">
<table class="table" border="1">
<tr class="tr">
<th>序号th>
<th>学号th>
<th>姓名th>
<th>性别th>
<th>班级th>
<th>住址th>
<th>生日th>
<th>操作th>
tr>
table>
div>
<div class="goAdd">
<button type="button">添加button>
div>
body>
html>
add.html
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="../css/add.css" />
<script src="../js/base.js">script>
<script src="../js/jquery.js">script>
<script src="../js/add.js">script>
<title>添加title>
head>
<body>
<div class="add">
<ul>
<li><span>学号:span>li>
<li><span>姓名:span>li>
<li>
<span>性别:span>
<div>
<input type="radio" name="gender" value="0"/><span>男span>
<span>女span>
div>
li>
<li><span>班级:span>li>
<li><span>地址:span>li>
<li><span>生日:span>li>
ul>
<ul>
<li><button id="submit" type="button">提交button>li>
ul>
div>
<div class="backIndex">
<button id="back" type="button">返回button>
div>
body>
html>
index.js
addLoadEvent(goAdd)//这个方法再base.js,相当于jq的$(document).ready(function(){ your code })
//跳转添加页面(古董方法,留着做个纪念)
function goAdd(){
//getElementByXpath()也在base.js中,用的是xpath定位方法(花里胡哨)
getElementByXpath("/html/body/div[2]/button").onclick = function(){
window.location.href = "add.html"
}
}
//显示首页数据
/*
思路:
将后台数据用ajax请求到,让后js动态生成tr,将data迭代到页面上
*/
$(document).ready(function(){//页面加载完后执行
//jq的ajax方法,开始想着自己封装Ajax了,最后发现自己菜的一批,还是jq香
$.ajax({
url:"http://127.0.0.1:8081/stu/findAllStu",//后台请求路径
type:"GET",//请求方法,具体看自己后台写的是GetMapping还是PostMapping
dataType:'json',//数据类型是json
contentType:"application/json",//内容类型,传json就得写这个
success:function(data){//成功时候的回调函数,凡间的话就是请求成功了,你前台要干的活儿
data = dataChange(data);//将后台的数据处理一下(有些格式是不对的)
var table = getElementByXpath("/html/body/div[1]/table");//获取table
var newTr = document.createElement("tr");//创建一个tr元素
for(var i = 0;i<data.length;i++){//迭代添加数据
//这里将id绑定到了tr的class中,方便我删除这行tr,addClass在base.js中
addClass(newTr,"tr del_"+data[i].id);
//给这个tr加内容
newTr.innerHTML =
''+(i+1)+' '+
''+data[i].stuNo+' '+
''+data[i].stuName+' '+
''+data[i].gender+' '+
''+data[i].stuClass+' '+
''+data[i].stuAddress+' '+
''+data[i].stuBirthday+' '+
'+data[i].id+')">删除 +data[i].id+')">编辑 ';
table.appendChild(newTr);//把这个tr添加到table中
newTr = document.createElement("tr");//重新赋值
}
},
//异常处理
error:function(e){
console.log(e);
}
});
});
// 数据转换(将后台数据转换一哈)
function dataChange(data){
//创建一个新的模板
var newData = [];
for(var i = 0;i<data.length;i++){
newData.push(
{
"id":data[i].id,
"stuName":data[i].stuName,
"gender":(data[i].gender == 0)?'男':'女',
"stuNo":data[i].stuNo,
"stuClass":data[i].stuClass,
"stuAddress":data[i].stuAddress,
"stuBirthday":data[i].stuBirthday.substring(0,10)//原来的日期不是很好看,这里截取一段,也可以进行转换一下
}
)
}
return newData;
}
//删除学生信息
/*
思路:
点击删除按钮,将id值传到函数里面
用ajax将id传到后台
后台根据id查出对应学生,并将学生删除标志变为1,删除时间赋值当前系统时间
*/
function delStu(stuId){
$.ajax({
url:"http://127.0.0.1:8081/stu/delStu",
type:"GET",
data:{
"id":stuId
},
dataType:'json',
timeout:10000,
contentType:"application/json",
success:function(data){
//不知道是什么鬼,也不报错,但是就是不走success
},
error:function(e){
$("."+"del_"+stuId).remove()
}
})
}
//显示编辑页面
/*
思路:首页将id传给add.html页面,
然后add.html将id截取出来传到后台获取对应学生信息显示在add.html页面上
*/
function goModify(id){
window.location.href = "add.html?"+id;
}
add.js
//提交学生
$(document).ready(function(){//页面加载完后执行
$("#submit").click(function(){
//获取学生信息
var stuNo,stuName,stuClass,stuAddress,stuBirthday,gender;
var id = window.location.href.split("?")[1];//截取链接中的id值
stuNo = document.getElementById("stuNo").value;//获取学号
stuName = document.getElementById("stuName").value;//获取名字
stuClass = document.getElementById("stuClass").value;//获取班级
stuAddress = document.getElementById("stuAddress").value;//获取地址
stuBirthday = document.getElementById("stuBirthday").value;//获取生日
gender = getElementByXpath("/html/body/div[1]/ul[1]/li[3]/div/input[1]").checked?0:1;//获取单选框值
//组装json
var data = {};
data["id"] = id;
data["stuNo"] = stuNo;
data["stuName"] = stuName;
data["stuClass"] = stuClass;
data["stuAddress"] = stuAddress;
data["stuBirthday"] = stuBirthday;
data["gender"] = gender;
console.log(JSON.stringify(data))
//ajax上传学生信息
$.ajax({
url:"http://127.0.0.1:8081/stu/saveStu",//请求地址
type:"POST",//请求方法
data:JSON.stringify(data),//将数据转换成json格式
dataType:'json',//数据类型:json
contentType:"application/json",//内容:json
success:function(data){
//不知道是什么鬼,也不报错,但是就是不走success
},
error:function(e){
if(id == "undefined"){//如果没有id说明时添加
console.log("添加成功")
}else{//有id说明时编辑
console.log("编辑成功")
}
}
})
});
});
//显示编辑页面学生信息
$(document).ready(function(){
//获取学生id
var id = window.location.href.split("?")[1];
//显示学生
$.ajax({
url:"http://127.0.0.1:8081/stu/findStu",//不说了,看上面
type:"get",
data:{id:id},
dataType:'json',
contentType:"application/json",
success:function(data){
//为页面赋值
$("#stuNo").val(data.stuNo)
$("#stuName").val(data.stuName)
$("#stuClass").val(data.stuClass)
$("#stuAddress").val(data.stuAddress)
$("#stuBirthday").val((data.stuBirthday).substring(0,10))
if(data.gender == 0){//这里用了”高级“一点的选择器,字面意思可以读懂,就不比比了
$("input[name = 'gender'][value=0]").attr("checked",true);
}else{
$("input[name = 'gender'][value=1]").attr("checked",true);
}
},
error:function(e){
console.log(e);
}
});
//提交
})
//跳转首页页面
$(document).ready(function(){
$("#back").click(function(){
window.location.href = "index.html";
});
});
这部分就不解释了,和咱项目关系比较远了,都是些前端知识,可以看看
base.js
//文档加载函数
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
//封装xpath
function getElementByXpath(xpath){
var element = document.evaluate(xpath,document).iterateNext();
return element;
}
//追加元素
function insertAfter(newElement,targetElement){
var parent = targetElement.parentNode;//获取目标元素的父节点
if(parent.lastChild == targetElement){
parent.appendChid(newElement);
}else{
parent.insertBefore(newElement,targetElement.nextSibling);
//nextSibling是表示下一个兄弟元素节点
}
}
//追加新的class
function addClass(element,value){
if(!element.className){
element.className = value;
}else{
newClassName = element.className;
newClassName += " ";
newClassName += value;
element.className += newClassName;
}
}
index.css
*{margin: 0;padding: 0;list-style: none;}
.add{
padding: 50px 40px 0 40px;
background-color: #FAEBD7;
width: 300px;
height: 300px;
position: absolute;
left: 40%;
top: 25%;
}
//清除父元素浮动
.add ul li:after{
margin: 0 0 10px 0;
content:"";
display:block;
clear:both;
}
.add ul li:nth-child(1) input,li:nth-child(2) input,li:nth-child(4) input,li:nth-child(5) input,li:nth-child(6) input{
position: absolute;
right: 10%;
}
.add ul li:nth-child(3) div{
margin: 0;
padding: 0;
width: 160px;
float: right;//使rdio和input对齐
}
.add ul li span{
}
.add ul:nth-child(2) li button{
width: 100px;
background-color: cornflowerblue;
position: absolute;
right: 10%;
}
.backIndex button{
width: 100px;
height: 50px;
background-color: #eee;
position: absolute;
top: 25%;
right: 25%;
}
add.css
*{margin: 0;padding: 0;}
/* 首页 */
.main{
background-color: antiquewhite;
position: absolute;
left: 30%;
top: 20%;
}
.table{
width: 600px;
}
.tr td,th{
text-align: center;
width: 200px;
height: 50px;
}
.goAdd button{
width: 100px;
height: 50px;
background-color: #eee;
position: absolute;
top: 20%;
right: 20%;
}
配置文件位于resources中,这里创建的了三个配置文件
源码及解析(以下有些配置可能前期开发阶段不需要)
application.yml
#配置spring
spring:
profiles:
active: dev #激活开发模式配置文件
#配置服务server
server:
#配置tomcat服务
tomcat:
uri-encoding: utf-8 #使tomcat在解析参数的时候采用utf-8编码格式,如果未指定则采用ISO-8859-1编码解析
max-connections: 3000 #最大连接数
max-http-form-post-size: 1048576 #(1Mb)最大的post请求数,tomcat7之后,-1代表不限制请求,7之前0代表不限制请求
max-http-header-size: 1048576 #请求头部最大值(1Mb)
c3p0:
jdbcUrl: jdbc:mysql://127.0.0.1:3306/stumanger?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
user: root
password: 123456
driverClass: com.mysql.jdbc.Driver #数据库连接驱动类
minPoolSize: 2 #最小连接数
maxPoolSize: 100 #最大的连接数
maxIdleTime: 1800000 #创建过的链接并使用后闲置下来的闲置时间,如果超过这个时间就会自动断开这个连接
acquireIncrement: 3 #当连接池中的连接耗尽的时候c3p0一次同时获取的连接数
maxStatements: 1000 #JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭
initialPoolSize: 3 #初始化时获取连接数
idleConnectionTestPeriod: 60 #每60秒检查所有连接池中的空闲连接
acquireRetryAttempts: 30 #定义在从数据库获取新连接失败后重复尝试的次数
acquireRetryDelay: 1000 #两次连接中间隔时间,单位毫秒
breakAfterAcquireFailure: false #获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default: false
testConnectionOnCheckout: false #因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable等方法来提升连接测试的性能
application-dev.yml
server:
port: 8081 #服务端口为8081
servlet:
session:
timeout: -1 #设置session用不过期
spring:
jpa:
hibernate:
ddl-auto: update #如果启动时表格式不一致则更新表,原有数据保留
show-sql: true #是否打印生成的sql语句
application-pro.yml
server:
port: 8081
servlet:
session:
timeout: 2h #session保存两个小时
spring:
jpa:
hibernate:
ddl-auto: none
show-sql: false
在写配置文件的时候,我们写过如下一段代码
spring:
jpa:
hibernate:
ddl-auto: update #如果启动时表格式不一致则更新表,原有数据保留
show-sql: true #是否打印生成的sql语句
其中用springboot创建表的核心就是jpa,jpa中的ddl-auto:update就可以在程序运行启动的时候,将实体类映射到数据库中,将数据库中表跟新为当前实体类的格式类型,当然ddl-auto还有其他参数,如下:
1)用Navicat创建一个数据库 stumanger
2)在entity中构建自己的实体类
用其中学生表 Stu 举例:
package com.fjh.bigproduct.model.entity;
import javax.persistence.*;
import java.util.Date;
/**
*@autho antg
*@date 2020-08-05 20:48
*/
@Entity
@Table(name = "stu")
class Stu {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
//学号
@Column(name="stu_no",columnDefinition = "varchar(255) comment'学号:2020+年级+班级 例如:20200101代表一年级一班,前4位表示入学年份'")
private String stuNo;
//学生姓名
@Column(name="stu_name",columnDefinition="varchar(255) comment'学生姓名'")
private String stuName;
//性别
@Column(name = "gender",columnDefinition = "int(11) comment'0:男,1:女'")
private int gender;
//班级
@Column(name = "stu_class",columnDefinition = "varchar(255) comment'班级'")
private String stuClass;
//住址
@Column(name = "stu_address",columnDefinition = "varchar(255) comment'住址'")
private String stuAddress;
//出生日期
@Column(name = "stu_birthday",columnDefinition = "datetime comment'出生年月日'")
private Date stuBirthday;
}
指定表名
@Entity
@Table(name=“表名”)
指定字段及属性
@Column(name=“字段名”,columnDefinition = “类型(长度) comment’注释’”)
3)启动springboot生成表
数据访问层相当于ssh项目中的dao,写操作数据库数据的方法
由于之前搭建的时候引入了jpa,所以在编写该层的时候可以继承数据访问的超级接口JpaRepository,然后就可以调用这个接口里面的方法就可以实现对数据库数据的crud。
先上代码,再逐个解释
package com.fjh.bigproduct.repository;
import com.fjh.bigproduct.model.entity.Stu;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import javax.transaction.Transactional;
import java.util.List;
/**
*@autho antg
*@Description 操作学生增删改查
*@date 2020-08-17 17:16
*/
@Repository
public interface StuRepository extends JpaRepository<Stu,Integer> {
//查询出所有未删除的学生
@Query("from Stu where delState = 0")
List<Stu> findAll();
//根据id查询学生
Stu findStuById(int id);
//保存编辑一个学生信息
//直接使用jpa封装好的save方法就行
}
1、注解:@Repository
这个注解用来标识这是一个数据访问层的类或者接口,并且在spring扫描的时候会将其加入到bean中
2、public interface StuRepository extends JpaRepository
这个StuRepository接口继承了jpa提供的超级数据访问接口JpaRepository
那么StuRepository就可以使用jpa提供的所有数据访问方法。(这里的JpaRepository
3、查询出所有未删除的学生
这里使用了一个注解@Query,这个注解可以让我们使用自己定义的方法就例如下面这一段代码
@Query("from Stu where delState = 0")
List<Stu> findAll();
我想要找到数据库中所有删除标志为0的数据,那么使用jpa自带的几个方法可能就不够用了,那就需要自己定义方法。
里面的语句可能写习惯sql语句的同学会看不懂,这里其实使用的叫HQL语句,是一种面向对象的查询语句,可以百度一下,语法比较简单,但是如果有同学就想写sql语句这么办呢?不慌,可以使用下面的写法
@Query("select * from stu where del_state = 0",nativeQuery = true)
List<Stu> findAll();
nativeQuery属性默认是false的,若变为true就可以使用原生的sql语句
4、根据id查询学生
Stu findStuById(int id);
这里使用的是jpa提供的接口,么的说,直接写就行
5、保存编辑一个学生信息
一般像4中那些方法都不写的,能简单就简单,除非要自定义写sql语句,否则不在这一层写那么重复的代码
目录结构:
根据面向接口编程的原则,我们这里写了一个接口和一个实现类
这一层我们主要用来写主要的业务逻辑代码,相当于action
1、接口StuService
package com.fjh.bigproduct.service;
import com.fjh.bigproduct.model.dto.StuDto;
import com.fjh.bigproduct.model.entity.Stu;
import java.util.List;
/**
*@autho antg
*@Description 学生管理
*@date 2020-08-17 17:30
*/
public interface StuService {
//查找所有未删除学生
List<Stu> findAllStu();
//删除某一学生
void delStu(int id);
//保存或者编辑一个学生(id不为空则编辑,id为空则新增)
void saveStu(StuDto stuDto);
//根据学生id查找学生
Stu findStu(int id);
}
规定了接口后,我们可以更加直观来展现实现类,也方便了编程
2、实现类StuServiceImpl
package com.fjh.bigproduct.service;
import com.fjh.bigproduct.model.dto.StuDto;
import com.fjh.bigproduct.model.entity.Stu;
import com.fjh.bigproduct.repository.StuRepository;
import com.fjh.bigproduct.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*@autho antg
*@Description 学生管理实现类
*@date 2020-08-17 17:44
*/
@Service //标注这是一个服务层,并在spring扫描的时候加入到bean中
public class StuServiceImpl implements StuService{
//引入数据访问层
@Autowired
private StuRepository stuRepository;
//查询所有未删除的学生
@Override
public List<Stu> findAllStu(){
try{
return stuRepository.findAll();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
//根据id查找学生
@Override
public Stu findStu(int id) {
try {
return stuRepository.findStuById(id);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//根据id删除某一个学生
@Override
@Transactional //加上这个注解后不用保存就可以直接更新
public void delStu(int id) {
try {
Stu stu = stuRepository.findStuById(id);
stu.setDelState(1);
stu.setDelTime(new Date());//这里没有保存,但是执行了方法后数据库就直接跟新了
} catch (Exception e) {
e.printStackTrace();
}
}
//保存或者编辑一个学生(id不为空则编辑,id为空则新增)
@Override
public void saveStu(StuDto stuDto) {
try {
Stu stu = new Stu();
//新增
if(stuDto.getId() == 0){
stu.setStuName(stuDto.getStuName());
stu.setGender(stuDto.getGender());
stu.setStuNo(stuDto.getStuNo());
stu.setStuClass(stuDto.getStuClass());
stu.setStuAddress(stuDto.getStuAddress());
stu.setStuBirthday(DateUtil.parseString2Date(stuDto.getStuBirthday()));
stu.setCreatTime(new Date());
stu.setDelState(0);
stuRepository.save(stu);
//下面可以加操作日志
//mycode
//编辑
}else {
stu.setId(stuDto.getId());
stu.setStuName(stuDto.getStuName());
stu.setGender(stuDto.getGender());
stu.setStuNo(stuDto.getStuNo());
stu.setStuClass(stuDto.getStuClass());
stu.setStuAddress(stuDto.getStuAddress());
stu.setStuBirthday(DateUtil.parseString2Date(stuDto.getStuBirthday()));
stu.setCreatTime(new Date());
stu.setDelState(0);
stuRepository.save(stu);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
总结一下服务层实现的步骤
1、引入注解@Service
2、引入数据访问层并加上注解@Autowired,
//引入数据访问层
@Autowired
private StuRepository stuRepository;//引入了之后就可以用stuRepository调用数据访问层的方法了
@Autowired注解可以对类成员变量、方法、构造函数进行标注,完成自动装配工作,通过@Autowried自动装配,可以实现从IoC容器中去查找bean中存储的对象,并返回。
3、实现接口的方法
里面使用了jpa提供的save方法,这个方法可以同时用在编辑和保存上,如果save的对象的id在数据库中存在,那么就更新,如果不存在就新增
这里的删除方法还使用了一个小技巧,@Transactional
这个注解可以实现不用save就可以自动更新
//根据id删除某一个学生
@Override
@Transactional //加上这个注解后不用保存九可以直接更新
public void delStu(int id) {
try {
Stu stu = stuRepository.findStuById(id);
stu.setDelState(1);
stu.setDelTime(new Date());
//这里只用了set方法就可以直接将数据库中的值更新
} catch (Exception e) {
e.printStackTrace();
}
}
package com.fjh.bigproduct.controller;
import com.fjh.bigproduct.model.dto.StuDto;
import com.fjh.bigproduct.model.entity.Stu;
import com.fjh.bigproduct.service.StuServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*@autho antg
*@Description 前台控制器
*@date 2020-08-19 10:16
*/
@RestController
@RequestMapping("/stu")
@ResponseBody
public class StuController {
//这里加上final可以理解为单例模式,优化程序
private final StuServiceImpl stuService;
//为stuService赋初始值
@Autowired
public StuController(StuServiceImpl stuService) {
this.stuService = stuService;
}
//显示学生列表
@GetMapping("/findAllStu")
public List<Stu> findAllStu(){
try {
List<Stu> list = stuService.findAllStu();
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//根据id查询学生
@GetMapping("/findStu")
public Stu findStu(int id){
try {
return stuService.findStu(id);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//添加学生;编辑学生
@PostMapping("/saveStu")
public void addStu(@RequestBody StuDto stuDto){
stuService.saveStu(stuDto);
}
//删除学生
@GetMapping("/delStu")
public void delStu(@RequestParam int id){
stuService.delStu(id);
}
}
这个前台控制器相当于以前的xml,主要为页面提供访问接口
1、注解
@RestController
这个controller注解可以返回一些对象,为前台提供数据,这个注解还有一个兄弟,叫做@Controller,这个注解返回值是一个页面路径,表示要展示的页面或者跳转到另外一个请求
@RequestMapping("/stu")
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径,这个注解可有可无,不过加在方法上的Mapping必须要有
地址/stu/方法Mapping
@ResponseBody
这个注解可以将后台返回的数据以json格式返回,否则返回的是一个Object对象,加在类上,该类的所有方法都会将数据以json格式返回
2、调用数据服务层StuServiceImpl
//这里加上final可以理解为单例模式,优化程序
private final StuServiceImpl stuService;
//为stuService赋初始值
@Autowired
public StuController(StuServiceImpl stuService) {
this.stuService = stuService;
}
3、向前台传值
//显示学生列表
@GetMapping("/findAllStu")
public List<Stu> findAllStu(){
try {
List<Stu> list = stuService.findAllStu();
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
这是一个显示学生列表的方法,前台使用get方法调接口/stu/findAllStu就可以获取rturn的值,这个值将以json的数据格式发送到前台(因为在使用了注解@@ResponseBody)
4、获取参数
(1)获取get请求中的参数
//删除学生
@GetMapping("/delStu")
public void delStu(@RequestParam int id){
stuService.delStu(id);
}
这里使用了@RequestParam注解, 后面的参数类型名称要和前台传的要一致
(2)获取json对象
//添加学生;编辑学生
@PostMapping("/saveStu")
public void addStu(@RequestBody StuDto stuDto){
stuService.saveStu(stuDto);
}
这里使用了@RequestBody来获取参数 后面跟上一个dto对象用来封装前台的json对象,一般前台提交json对象都用POST方法来响应
这里的dto一般就是用来封装前台传来的json对象
dto源码:
package com.fjh.bigproduct.model.dto;
import java.util.Date;
/**
*@autho antg
*@Description 封装stu对象
*@date 2020-08-20 08:44
*/
public class StuDto {
private int id;
private String stuNo;
private String stuBirthday;
private String stuAddress;
private String stuClass;
private int gender;
private String stuName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
public String getStuBirthday() {
return stuBirthday;
}
public void setStuBirthday(String stuBirthday) {
this.stuBirthday = stuBirthday;
}
public String getStuAddress() {
return stuAddress;
}
public void setStuAddress(String stuAddress) {
this.stuAddress = stuAddress;
}
public String getStuClass() {
return stuClass;
}
public void setStuClass(String stuClass) {
this.stuClass = stuClass;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
}