持续学习&持续更新中…
学习态度:守破离
JavaScript_jQuery_Bootstrap
整合该项目的添加客户和更新客户数据业务
为什么要整合这两个业务
该项目的edit.jsp和save.html中的内容结构大体相似,只有几处略微不同的地方。
CustomerServlet代码中这两处业务也有很多相似之处。
实现
CustomerServlet
只留一个save方法,统一处理添加客户和更新客户数据操作。
@WebServlet("/customer/*")
public class CustomerServlet extends HttpServlet {
private CustomerDao customerDao;
@Override
public void init() {
customerDao = new CustomerDao();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.setCharacterEncoding("utf-8");
final String[] split = request.getRequestURI().split("/");
final String methodName = split[split.length - 1];
try {
Method method = CustomerServlet.class.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, request, response);
} catch (Exception e) {
try {
Method method = CustomerServlet.class.getMethod("error", String.class, HttpServletRequest.class, HttpServletResponse.class);
method.invoke(this, "不存在该页面", request, response);
} catch (Exception exception) {
exception.printStackTrace();
}
e.printStackTrace();
}
}
public void list(HttpServletRequest request, HttpServletResponse response) {
try {
final List<Customer> list = customerDao.list();
request.setAttribute("customerSize", list.size());
request.setAttribute("customers", list);
request.getRequestDispatcher("../pages/list.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
public void save(HttpServletRequest request, HttpServletResponse response) {
try {
Customer customer = newCustomer(request);
if (null != customer) {
if (customer.getId() != null) {
// update
if (customerDao.update(customer)) {
response.sendRedirect("/eight_javascript/customer/list");
} else {
error("数据更新失败", request, response);
}
} else {
// save
if (customerDao.save(customer)) {
response.sendRedirect("/eight_javascript/customer/list");
} else {
error("客户添加失败", request, response);
}
}
} else {
error("用户非法输入", request, response);
}
} catch (Exception e) {
error("数据保存失败", request, response);
e.printStackTrace();
}
}
public void edit(HttpServletRequest request, HttpServletResponse response) {
try {
String customerId = request.getParameter("id");
if (customerId != null && !"".equals(customerId)) {
final Integer id = Integer.valueOf(customerId);
final Customer customer = customerDao.edit(id);
try {
request.setAttribute("customer", customer);
request.getRequestDispatcher("../pages/save.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
error("数据编辑失败", request, response);
}
}
} catch (Exception e) {
error("数据编辑失败", request, response);
e.printStackTrace();
}
}
public void remove(HttpServletRequest request, HttpServletResponse response) {
try {
String customerId = request.getParameter("id");
if (customerId != null && !"".equals(customerId)) {
final Integer id = Integer.valueOf(customerId);
if (customerDao.remove(id)) {
response.sendRedirect("/eight_javascript/customer/list");
} else {
error("数据删除失败", request, response);
}
}
} catch (Exception e) {
error("数据删除失败", request, response);
e.printStackTrace();
}
}
private void error(String error, HttpServletRequest request, HttpServletResponse response) {
try {
request.setAttribute("error", error);
request.getRequestDispatcher("../pages/error.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
private Customer newCustomer(HttpServletRequest request) {
String customerName = request.getParameter("customer_name");
String customerAge = request.getParameter("customer_age");
String customerHeight = request.getParameter("customer_height");
String customerId = request.getParameter("customer_id");
if (
customerName != null && customerAge != null && customerHeight != null &&
!"".equals(customerName) && !"".equals(customerAge) && !"".equals(customerHeight)
) {
Customer customer = new Customer(
customerName, Integer.valueOf(customerAge), Double.valueOf(customerHeight)
);
if (customerId != null && !customerId.equals("")) {
customer.setId(Integer.valueOf(customerId));
}
return customer;
}
return null;
}
}
list.jsp
修改a
标签让其直接跳转到save.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>list</title>
<style>
table, tr, th, td {
border: 1px solid black;
width: 500px;
text-align: center;
}
</style>
</head>
<body>
<h1 style="color: green">总共有${customerSize}个客户</h1>
<table>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>身高</th>
</tr>
<c:forEach items="${customers}" var="customer">
<tr>
<td>${customer.name}</td>
<td>${customer.age}</td>
<td>${customer.height}</td>
<td><a href="/eight_javascript/customer/edit?id=${customer.id}">编辑</a></td>
<td><a href="/eight_javascript/customer/remove?id=${customer.id}">删除</a></td>
</tr>
</c:forEach>
</table>
<br>
<a href="/eight_javascript/pages/save.jsp">添加客户</a>
</body>
</html>
save.jsp
使用JSTL和EL表达式来重构该页面,使得无论是更新客户数据还是添加客户,都使用该页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta charset="UTF-8">
<title>
<c:choose>
<c:when test="${empty customer}">
add-customer
</c:when>
<c:otherwise>
edit-customer
</c:otherwise>
</c:choose>
</title>
</head>
<body>
<form action="/eight_javascript/customer/save" method="post">
<c:if test="${not empty customer}">
<div><input type="hidden" name="customer_id" value="${customer.id}"></div>
</c:if>
<div>姓名:<input type="text" name="customer_name" value="${customer.name}"></div>
<div>年龄:<input type="number" name="customer_age" value="${customer.age}"></div>
<div>身高:<input type="text" name="customer_height" value="${customer.height}"></div>
<div>
<button type="submit">
<c:if test="${empty customer}">
添加
</c:if>
<c:if test="${not empty customer}">
更新
</c:if>
</button>
</div>
</form>
</body>
</html>
修改之后的项目结构图
JavaScript
为什么需要JavaScript
-
CustomerServlet中,有很多判断用户输入的代码(表单验证),这些操作不应该在服务器进行。
-
应该在前端页面(浏览器/客户端)来判断用户是否有非法输入等问题(专业术语:客户端的表单验证),不应该提交到服务器让服务器先去进行表单验证然后再去执行业务代码。
-
如果客户端的表单验证通过,才应该发请求给服务器。
-
这时就需要使用JavaScript在前端进行表单验证了。
什么是JavaScript
JS常见用途
JS参考资料
https://zh.javascript.info/
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
JS编码规范
-
不写分号
;
-
字符串使用单引号
''
-
使用
let
定义变量const
定义常量
JS——基本知识
Script标签
JS基础语法
typeof运算符
JS——数据类型
- function、数组、null是object类型
console.log(typeof 5) // number
console.log(typeof '') // string
console.log(typeof 2n) // bigint
console.log(typeof undefined) // undefined
console.log(typeof null) // object
console.log(typeof {
}) // object
console.log(typeof []) // object
console.log(typeof function(){
}) // function 是 object ;typeof这块不对 ;JS规定中没有function类型
- 判断某个变量是否是function类型
// 判断某个变量是否是function
let v = function() {
}
if((typeof v) == 'function') {
console.log('v是function')
}else {
console.log('v不是function')
}
数字类型
数字类型:https://zh.javascript.info/number
字符串
https://zh.javascript.info/string
没有字符类型
在 JavaScript 中,文本数据被以字符串形式存储,单个字符没有单独的类型。
三种引号
""
(双引号)
let double = "double-quoted"
''
(单引号)
let single = 'single-quoted'
``
(反引号)
let backticks = `backticks`
三种引号的区别:
let vs = 'liupeng'
let vi = 100
console.log("my name is ${vs}, my age is ${vi}") // my name is ${vs}, my age is ${vi}
console.log('my name is ${vs}, my age is ${vi}') // my name is ${vs}, my age is ${vi}
console.log(`my name is ${
vs}, my age is ${
vi}`) // my name is liupeng, my age is 100
拼接
遍历
JS中没有字符类型,所以遍历出的结果 c a t
都是一个个的字符串子串。
数组的遍历
数组:https://zh.javascript.info/array
数组方法:https://zh.javascript.info/array-methods
对象的遍历
JS——函数
函数的常见用法
监听标签的点击事件
onclick的属性值是JS代码
JS——DOM操作
https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model
jQuery
https://jquery.com
https://api.jquery.com
https://www.jquery123.com/
什么是jQuery
jQuery如何使用
jQuery的强大之处
-
利用jQuery找到的节点,是jQuery包装后的节点,并非JS原生的节点。原因是DOM操作,在有些时候,不同浏览器有不同的规范。原因是DOM操作,有很多浏览器兼容问题。
-
在使用某个jQuery的API时,jQuery内部会帮助我们在不同的浏览器上执行不同的代码,以此达到我们想要的效果。
-
jQuery内部帮助我们处理了这些代码适配,兼容解决,统一了所有的操作。
$(function(){
// $("ul>li:nth-child(2)").remove()
// document.querySelector("ul>li:nth-child(2)").remove()
console.log($("ul>li:nth-child(2)") == document.querySelector("ul>li:nth-child(2)"))
})
绑定点击事件
$(function () {
$("ul>li").click(function () {
console.log(this)
})
})
jQuery的一些细节
- 使用append方法,jQuery会将传入的字符串转成一个dom对象添加至调用节点上。
$("ul>li").append('<a href="https://www.baidu.com">百度</a>')
基于jQuery的几个插件
网上有很多基于jQuery的框架,这儿只举几个例子。
- jQuery UI
https://jqueryui.com/
https://www.jqueryui.org.cn/
- jQuery Validation(表单验证)
https://jqueryvalidation.org
jQuery-UI的一个demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery-UI</title>
<style>
*{
margin: 0;
padding: 0;
}
#draggable {
width: 200px;
height: 200px;
border: 10px solid red;
text-align: center;
line-height: 200px;
font-size: 20px;
}
</style>
<script src="../js/jquery-3.5.1.min.js"></script>
<script src="../js/jquery-ui.min.js"></script>
<script>
$(function(){
$("#draggable").draggable()
})
</script>
</head>
<body>
<div id="draggable">
<strong>I am draggable.</strong>
</div>
</body>
</html>
jQuery Validation的一个demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery-Validation</title>
<style>
* {
margin: 0;
padding: 0;
}
</style>
<script src="../js/jquery-3.5.1.min.js"></script>
<script src="../js/jquery.validate.min.js"></script>
<script>
$(function () {
$("#login_form").validate()
})
</script>
</head>
<body>
<form id="login_form" action="">
<div>用户名<input type="text" required></div>
<div>密码<input type="password"></div>
<div><button type="submit">登录</button></div>
</form>
</body>
</html>
但是直接这样,提示信息是英文,需要再引入一个script:
引入messages_zh.js文件后,提示信息就会是中文。
可以自己更改messages_zh.js中的提示信息:
{
required: "这是必填字段",
remote: "请修正此字段",
email: "请输入有效的电子邮件地址",
url: "请输入有效的网址",
date: "请输入有效的日期",
dateISO: "请输入有效的日期 (YYYY-MM-DD)",
number: "请输入有效的数字",
digits: "只能输入数字",
creditcard: "请输入有效的信用卡号码",
equalTo: "你的输入不相同",
extension: "请输入有效的后缀",
maxlength: $.validator.format( "最多可以输入 {0} 个字符" ),
minlength: $.validator.format( "最少要输入 {0} 个字符" ),
rangelength: $.validator.format( "请输入长度在 {0} 到 {1} 之间的字符串" ),
range: $.validator.format( "请输入范围在 {0} 到 {1} 之间的数值" ),
step: $.validator.format( "请输入 {0} 的整数倍值" ),
max: $.validator.format( "请输入不大于 {0} 的数值" ),
min: $.validator.format( "请输入不小于 {0} 的数值" )
}
Bootstrap
https://www.bootcss.com/
https://getbootstrap.com
栅格系统例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>bootstrap</title>
<link rel="stylesheet" href="../css/bootstrap.min.css">
<style>
html,
body {
margin: 0;
padding: 0;
}
div {
border: 1px solid black;
height: 80px;
line-height: 80px;
text-align: center;
}
</style>
</head>
<body>
<!-- Bootstrap响应式代码 -->
<!-- Bootstrap的栅格系统会将屏幕分为12等份 -->
<!-- col-lg-3 表示在大屏幕下,该div占据3份(3/12 = 1/4) 屏幕的1/4-->
<!-- col-md-6 表示在中等屏幕下,该div占据6份(6/12 = 1/2) 屏幕的1/2-->
<!-- col-sm-12 表示在小屏幕下,该div占据12份(12/12 = 1/1) 整个屏幕-->
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-12">div1</div>
<div class="col-lg-3 col-md-6 col-sm-12">div2</div>
<div class="col-lg-3 col-md-6 col-sm-12">div3</div>
<div class="col-lg-3 col-md-6 col-sm-12">div4</div>
</div>
</body>
</html>
Bootstrap js的引入
Bootstrap依赖jQuery、Popper这两个js文件
-
引入方式一:首先需要引入jQuery,其次是 Popper(如果你使用工具提示和弹出框的话),最后是bootstrap的js文件。
-
引入方式二:首先引入jQuery,然后引入Bootstrap JavaScript bundle.(bundle中整合了Popper)
可以看到,上述代码也引入了bootstrap.min.css
文件。
参考
李明杰: Java从0到架构师②JavaEE技术基石.
本文完,感谢您的关注支持!