任何一种框架进入系统的方式都是通过在web.xml中书写某种固件来实现的。spring是通过监听器进来的。springmvc是通过超级servlet 进入系统的。这个servlet能够拦截所有的请求。springmvc将按照dispatcher-servle文件来干活。
使用 restful api,需要按格式书写路径
来到input_student.jsp,修改为:
来到Controller,修改:
这种是Get提交。
springmvc使用的日志是slf4j:
在pom.xml添加:
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
测试:
使用:
动词:GET
网址:students/123
操作:返回学生学号为123的信息记录
淘汰了:students?stuno=123
把原来的参数当做网址的一部分来完成。
修改Controller:
@GetMapping("/students/{stuNo}")//路径变量,如果路径是“/students/123”,那么,路径变量的值就是123
public String preUpdate(@PathVariable int stuNo,Model model) throws Exception{//要写上@PathVariable,表示是一个路径变量。在这里写上stuNo,就会自动的把路径变量“stuNo”的值填到这个stuNo。他就会到路径上找到一个叫做“stuNo”的位置,将其值取出来,转成对应的数据类型
StudentService stuService = new StudentServiceImpl();
Student stu = stuService.getStuByNo(stuNo);
//将学生保存到请求范围
model.addAttribute("stu", stu);
return "update_student";//所有的返回字符串,只要上面没有写@ResponseBody,都认为是视图构成的一部分,就会交给视图解析器。我们安排了一个内部资源视图解析器。
}
原来要取这个路径变量:
设置一个断点,测试一下:
Restart in debug
stuNo已经是106了:
路径变量是可以正常工作的。
返回的界面不存在,所以是404。
实现修改界面:
复制原来的update_student.jsp到views目录下。
测试:
修改updata_student.jsp的bootstrap的连接:
再测试:
接下来,将update_student.jsp连接上list_student.jsp的修改按钮。
测试:
点击修改:
新生注册:
修改:
删除这行:
测试:
报错了:
stu_name不能为空,说明无法自动适配,需修改为与类的属性同名:
测试:
有了。
更新:
按照restful api,更新是put提交,但是浏览器是不能put提交的,浏览器只可以发出get和post提交,手机可以。
修改:
在Controller添加:
@PutMapping("/students/{stuNo}")
public String updateStudent(Student stu,@PathVariable int stuNo) throws Exception{//传回一个修改好的学生对象
StudentService stuService = new StudentServiceImpl();
stuService.updateStudent(stu);
//返回一个重定向
return "redirect:/students";
}
来到update_student.jsp修改action,删除下面一行:
测试:
路径就是这个路径了,现在的提交方式还是post提交:
使用隐藏域,将post提交转成put提交:
<input type="hidden" name="_method" value="PUT"/>
提交时虽然是post提交,但是这个隐藏域会传到springmvc,springmvc会采取相应的措施。
springmvc要提供一个部件来解决这个问题。
要在web.xml提供一个“隐藏Http方法过滤器”,它能将post提交转成PUT提交。这个过滤器也是过滤所有的。
放在编码过滤器后面,
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
定义了一个过滤器,会对所有的请求进行过滤,他的目标是:只要是post提交,同时隐藏了一个叫“_method”的输入参数就会把post提交转成put提交。
这时,我们用post就是put提交了。
修改update_student.jsp
要做相应的改变,不然填充不进去。
测试:
产生乱码:
调换这一块的位置:
测试:
之前:
之后:
完整web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>stuinfo</display-name>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
删除:
根据restful api,删除是DELETE提交。
名叫“/student/123"的网址有3个,但是因为提交方式的不同,调用的是不同的方法:
在Controller添加:
@DeleteMapping("/students/{stuNo}")
public String removeStudent(@PathVariable int stuNo) throws Exception{
StudentService stuService = new StudentServiceImpl();
stuService.removeStu(stuNo);
return "redirect:/students";
}
来到list_student.jsp修改:
但是这样子的话他是get提交。就不能这样做了。
随便在哪偷偷摸摸写个表单:
<form name="removeFrm" action="/stuinfo/students" method="post">
<input type="hidden" name="_method" value="DELETE">
</form>
这个表单是不可见的
发起delete提交,只能通过表单来发起,通过JavaScript编程来把这个表单提交了
首先,找到removeFrm的action这个action是不够的,要再加上“/”+stuNo。把action的位置调一下再提交表单
alter一下,看看值对不对
然后提交表单
JavaScript如下:
function removeStu() {
/* location.href = "/stuinfo/students" + stuNo;/* location是地址栏,href是地址栏上面的文字,location.href即修改地址栏上面的文字。 到这个网址 就实现了删除*/
/* location.href='<c:url value="/stuMgr" />?task=preUpdate&stuno='+stuNo; 效果与上行相同或类似*/ */
document.forms['removeFrm'].action+='/'+stuNo;
alter('document.forms['removeFrm'].action');
document.forms['removeFrm'].submit();
}
记录一些报错:
1·如果报这个:
是标签没有收口。
2·
405是提交的路径不支持。
完整list_student.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet"
href="/stuinfo/resources/vendor/bootstrap-4.5.3-dist/css/bootstrap.min.css">
<script type="text/javascript"
src="/stuinfo/resources/vendor/jquery/jquery-3.3.1.js"></script>
<!--模态窗能不能弹出来就靠它了 -->
<script type="text/javascript"
src="/stuinfo/resources/vendor/popper.js/popper.min.js"></script>
<script type="text/javascript"
src="/stuinfo/resources/vendor/bootstrap-4.5.3-dist/js/bootstrap.min.js"></script>
<title>Insert title here</title>
<script type="text/javascript">
var stuNo;/* 建立全局变量,使“removeStu()”可以使用“showRemoveDlg(stuno, stuname)” */
function showRemoveDlg(stuno, stuname) {
stuNo = stuno;/* 将变量预存到外面的全局变量上 */
$("#msg").text("您确认要删除学生 [ " + stuname + " ]的信息吗?");/* 使用jquery */
$('#removeStuModal').modal('show');/* 在bootstrap的网页上有说明如何用编程来开启模态窗,复制黏贴 */
}
function removeStu() {
document.forms['removeFrm'].action+='/'+stuNo;
/* alert("document.forms['stuFrm'].action"); */
document.forms['removeFrm'].submit();
}
function updateStu(stuNo){/* 传入学生学号 */
location.href="/stuinfo/students/"+stuNo;
/* location.href="/stuinfo/students/"+stuNo; */
/* location.href='<c:url value="/students"/>/'+stuNo; */
}
function updateStuModal(){
document.forms['updateStuFrm'].submit();
$('#updateStuModal').modal('hide');
}
function regStu(){
document.forms['stuFrm'].submit();/* 提交表单 */
$('#regStuModal').modal('hide');/* 关闭模态窗 */
}
function showUpdateDlg(btn){
/* 在模态窗显示之前要进行一些操作 */
/* console.log(btn.parentNode.parentNode.children[0].innerText); */
/* $('#updateStuModal').modal('show'); */
/* 创建变量 */
var elements = btn.parentNode.parentNode.children;
var frm = document.forms['updateStuFrm'];
frm.stuno.value = elements[0].innerText;
frm.stuname.value = elements[1].innerText;
frm.stumark.value = elements[2].innerText;
$("#stuno").text(elements[0].innerText);/* 使用jQuery的方法 */
$('#updateStuModal').modal('show');
}
</script>
</head>
<body>
<form name="removeFrm" action="/stuinfo/students" method="post">
<input type="hidden" name="_method" value="DELETE">
</form>
<div class="container">
<h3 class="my-5 mb-3">学生信息列表</h3>
<!-- 调整与按钮的上下关系 -->
<div class="my-2 text-right">
<!-- 给按钮增加一个行的容器 -->
<!-- 将按钮移到右边 -->
<button class="btn btn-primary mb-2" data-toggle="modal"
data-target="#regStuModal">新生登记</button>
<!-- 不编程的方式打开模态窗,但是要加载Bootstrap的js文件 -->
</div>
<table class="table">
<thead>
<tr>
<th scope="col">学号</th>
<th scope="col">姓名</th>
<th scope="col">成绩</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<c:forEach var="stu" items="${stuList}">
<!-- for循环 ,把这个范围内的数据取下来 -->
<tr>
<th scope="row">${stu.stuNo}</th>
<td>${stu.stuName}</td>
<td>${stu.stuMark}</td>
<td>
<!-- <button class="btn btn-primary btn-sm"
οnclick="showUpdateDlg()">修改</button> -->
<button class="btn btn-primary btn-sm"
onclick="updateStu(${stu.stuNo})">修改</button>
<button class="btn btn-danger btn-sm"
onclick="showRemoveDlg(${stu.stuNo},'${stu.stuName}');">删除</button>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<!-- 删除学生信息模态提示窗口 -->
<div class="modal fade" tabindex="-1" id="removeStuModal">
<!-- 将class="modal"的modal拿掉模态窗就可以显示 -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">操作提示</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p id="msg"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary"
onclick="removeStu();">确认删除</button>
</div>
</div>
</div>
</div>
<!-- 新生注册注册模态窗口 -->
<div class="modal fade" tabindex="-1" id="regStuModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">操作提示</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form name="stuFrm" action="<c:url value="/students"/>"
class="col-12" method="post">
<!-- 给表单设置一个名字 -->
<div class="form-group">
<label>学生学号</label> <input type="text" class="form-control"
name="stuNo">
</div>
<div class="form-group">
<label>学生姓名</label> <input type="text" class="form-control"
name="stuName">
</div>
<div class="form-group">
<label>学生成绩</label> <input type="text" class="form-control"
name="stuMark">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="regStu()">新生注册</button>
</div>
</div>
</div>
</div>
<!-- 新生修改模态窗口 -->
<div class="modal fade" tabindex="-1" id="updateStuModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">学生信息修改</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form name ="updateStuFrm" class="col-6" action="stuMgr" method="post">
<input type="hidden" name="task" value="updateStu" />
<!-- 学生学号也要传上去,单数不能出现在界面上,所以添加隐含域 -->
<input type="hidden" name="stuno" value="" />
<div class="form-group">
<label>学生学号:<span id="stuno"></span></label>
<!-- 学号是不可修改的 -->
</div>
<div class="form-group">
<label>学生姓名:</label> <input type="text" class="form-control"
name="stuname" value="">
<!-- 用EL表达式来回填的 -->
</div>
<div class="form-group">
<label>学生成绩:</label> <input type="text" class="form-control"
name="stumark" value="">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="updateStuModal()">确认修改</button>
</div>
</div>
</div>
</div>
</body>
</html>
类似是接口文档:
同样的网址不同的操作,执行不同的方法。