AJAX基础+Axios快速入门+JSON使用+综合案例
1、 AJAX
1.1 概述
AJAX
(Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。
1.1.1 作用
与服务器进行数据交换
使用JSP
- 浏览器发送请求
Servlet
Servlet
调用完业务逻辑层之后,将数据存储到Request域对象
中- 转发到对应
JSP
进行展示(将JSP
作为视图)
- 浏览器发送请求
使用AJAX:AJAX可以给服务器发送请求,并获取服务器响应的数据
使用AJAX+HTML替换JSP
- 浏览器发送请求
Servlet
Servlet
调用完业务逻辑层后将数据通过AJAX
直接响应回给浏览器页面- 页面使用
HTML
来进行数据展示
- 浏览器发送请求
异步交互
- 可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验,点击关注,点击收藏,等等…
1.1.2 同步和异步
同步发送请求的过程
- 客户端访问服务器
- 服务器处理客户端请求
- 服务器返回处理结果到客户端
- 客户端进行其他请求
异步发送请求的过程:不用等待服务器端
- 客户端访问服务器
- 服务器处理客户端请求(期间客户端可进行其他操作)
- 服务器返回处理结果到客户端
- 客户端进行其他请求
1.2 快速入门
1.2.1 服务端实现
编写Servlet
package priv.dandelion.controller.servlet; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet("/ajaxDemo")
public class AjaxDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 响应数据
resp.getWriter().write("hello ajax~");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
1.2.2 客户端实现
步骤说明
- 创建
xhttp
核心对象 - 建立连接
- 发送请求
- 获取响应
- 创建
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AJAX-demo1</title>
</head>
<body> <script> // 创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
} // 建立连接(包含第三个参数,为true是异步,默认异步,此处省略)
xhttp.open("GET", "http://localhost:8080/ajax-demo/ajaxDemo"); // 发送请求
xhttp.send(); // 获取响应,监听到onreadystatechange就绪状态事件,事件发生变化时执行函数
xhttp.onreadystatechange = function() {
// this.readyState == 4 表示请求发送结束且响应就绪,this.status == 200表示成功收到响应
if (this.readyState == 4 && this.status == 200) {
// 通过 this.responseText 可以获取到服务端响应的数据
alert(this.responseText);
}
}; </script> </body>
</html>
1.3 案例
1.3.1 需求
用户注册功能
在用户名输入框失去焦点时,校验该用户名是否存在,并在页面中给出提示
1.3.2 分析
前端
- 给用户名输入框绑定光标失去焦点事件
onblur
- 发送ajax请求,携带
username
参数
- 给用户名输入框绑定光标失去焦点事件
后端
- 接收用户名
- 调用
service
查询User
- 返回标记
1.3.2 后端实现
环境准备
依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>priv.dandelion</groupId>
<artifactId>ajax-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging> <properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties> <dependencies>
<!-- junit单元测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--mybatis 依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--mysql 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- 添加slf4j日志api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!-- 添加logback-classic依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 添加logback-core依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!-- servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- JSP依赖 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!-- JSTL依赖 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- JSTL标准标签库依赖 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<!-- tomcat插件 -->
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</build> </project>SQL
-- 删除tb_user表
drop table if exists tb_user;
-- 创建用户表
CREATE TABLE tb_user(
id int primary key auto_increment,
username varchar(20) unique,
password varchar(32)
); -- 添加数据
INSERT INTO tb_user(username,password) values('zhangsan','123'),('lisi','234'); SELECT * FROM tb_user;静态页面
CSS
* {
margin: 0;
padding: 0;
list-style-type: none;
}
.reg-content{
padding: 30px;
margin: 3px;
}
a, img {
border: 0;
} body {
background-image: url("../imgs/reg_bg_min.jpg") ;
text-align: center;
} table {
border-collapse: collapse;
border-spacing: 0;
} td, th {
padding: 0;
height: 90px; }
.inputs{
vertical-align: top;
} .clear {
clear: both;
} .clear:before, .clear:after {
content: "";
display: table;
} .clear:after {
clear: both;
} .form-div {
background-color: rgba(255, 255, 255, 0.27);
border-radius: 10px;
border: 1px solid #aaa;
width: 424px;
margin-top: 150px;
margin-left:1050px;
padding: 30px 0 20px 0px;
font-size: 16px;
box-shadow: inset 0px 0px 10px rgba(255, 255, 255, 0.5), 0px 0px 15px rgba(75, 75, 75, 0.3);
text-align: left;
} .form-div input[type="text"], .form-div input[type="password"], .form-div input[type="email"] {
width: 268px;
margin: 10px;
line-height: 20px;
font-size: 16px;
} .form-div input[type="checkbox"] {
margin: 20px 0 20px 10px;
} .form-div input[type="button"], .form-div input[type="submit"] {
margin: 10px 20px 0 0;
} .form-div table {
margin: 0 auto;
text-align: right;
color: rgba(64, 64, 64, 1.00);
} .form-div table img {
vertical-align: middle;
margin: 0 0 5px 0;
} .footer {
color: rgba(64, 64, 64, 1.00);
font-size: 12px;
margin-top: 30px;
} .form-div .buttons {
float: right;
} input[type="text"], input[type="password"], input[type="email"] {
border-radius: 8px;
box-shadow: inset 0 2px 5px #eee;
padding: 10px;
border: 1px solid #D4D4D4;
color: #333333;
margin-top: 5px;
} input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus {
border: 1px solid #50afeb;
outline: none;
} input[type="button"], input[type="submit"] {
padding: 7px 15px;
background-color: #3c6db0;
text-align: center;
border-radius: 5px;
overflow: hidden;
min-width: 80px;
border: none;
color: #FFF;
box-shadow: 1px 1px 1px rgba(75, 75, 75, 0.3);
} input[type="button"]:hover, input[type="submit"]:hover {
background-color: #5a88c8;
} input[type="button"]:active, input[type="submit"]:active {
background-color: #5a88c8;
}
.err_msg{
color: red;
padding-right: 170px;
}
#password_err,#tel_err{
padding-right: 195px;
} #reg_btn{
margin-right:50px; width: 285px; height: 45px; margin-top:20px;
} #checkCode{
width: 100px;
} #changeImg{
color: aqua;
}
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>欢迎注册</title>
<link href="css/register.css" rel="stylesheet">
</head>
<body> <div class="form-div">
<div class="reg-content">
<h1>欢迎注册</h1>
<span>已有帐号?</span> <a href="login.html">登录</a>
</div>
<form id="reg-form" action="#" method="get"> <table> <tr>
<td>用户名</td>
<td class="inputs">
<input name="username" type="text" id="username">
<br>
<span id="username_err" class="err_msg" style="display: none">用户名不太受欢迎</span>
</td> </tr> <tr>
<td>密码</td>
<td class="inputs">
<input name="password" type="password" id="password">
<br>
<span id="password_err" class="err_msg" style="display: none">密码格式有误</span>
</td>
</tr> <tr>
<td>验证码</td>
<td class="inputs">
<input name="checkCode" type="text" id="checkCode">
<img src="imgs/a.jpg">
<a href="#" id="changeImg">看不清?</a>
</td>
</tr> </table> <div class="buttons">
<input value="注 册" type="submit" id="reg_btn">
</div>
<br class="clear">
</form> </div>
</body>
</html>
数据库
核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--起别名-->
<typeAliases>
<package name="priv.dandelion.entity"/>
</typeAliases> <environments default="development">
<environment id="development">
<!-- 采用JDBC的事务管理方式 -->
<transactionManager type="JDBC"/>
<!-- 数据库连接信息 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- value的值一定不能换行,一定!一定!不能换行 -->
<property name="url" value="jdbc:mysql:///db1?useSSL=false&useUnicode=true&characterEncoding=utf-8&useServerPrepStmts=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 扫描mapper,加载SQL映射文件 -->
<mappers>
<package name="priv.dandelion.dao"/>
</mappers>
</configuration>
Mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="priv.dandelion.dao.UserMapper">
</mapper>
工具类
获取SqlSessionFactory
package priv.dandelion.utils; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException;
import java.io.InputStream; public class SqlSessionFactoryUtils { // 提升作用域,用于再方法内进行返回
private static SqlSessionFactory sqlSessionFactory; // 静态代码块会随着类的加载自动执行且只执行一次
static {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
} }
重编码ISO-8859-1为UTF-8
package priv.dandelion.utils; import java.nio.charset.StandardCharsets; public class ReEncoding { public static String reEncodingToUtf8(String str) {
// 使用ISO-8859-1编码将乱码字符编回二进制码,得到其字节数组
byte[] bytes = str.getBytes(StandardCharsets.ISO_8859_1);
// 将字节数组使用UTF-8重新编码
return new String(bytes, StandardCharsets.UTF_8);
}
}
验证码生成
package priv.dandelion.utils; import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random; /**
* 生成验证码工具类
*/
public class CheckCodeUtil { public static final String VERIFY_CODES = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static Random random = new Random(); /**
* 输出随机验证码图片流,并返回验证码值(一般传入输出流,响应response页面端,Web项目用的较多)
*
* @param width 图片宽度
* @param height 图片高度
* @param os 输出流
* @param verifySize 验证码长度
* @return String
* @throws IOException
*/
public static String outputVerifyImage(int width, int height, OutputStream os, int verifySize) throws IOException {
String verifyCode = generateVerifyCode(verifySize);
outputImage(width, height, os, verifyCode);
return verifyCode;
} /**
* 使用系统默认字符源生成验证码
*
* @param verifySize 验证码长度
* @return
*/
public static String generateVerifyCode(int verifySize) {
return generateVerifyCode(verifySize, VERIFY_CODES);
} /**
* 使用指定源生成验证码
*
* @param verifySize 验证码长度
* @param sources 验证码字符源
* @return
*/
public static String generateVerifyCode(int verifySize, String sources) {
// 未设定展示源的字码,赋默认值大写字母+数字
if (sources == null || sources.length() == 0) {
sources = VERIFY_CODES;
}
int codesLen = sources.length();
Random rand = new Random(System.currentTimeMillis());
StringBuilder verifyCode = new StringBuilder(verifySize);
for (int i = 0; i < verifySize; i++) {
verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
}
return verifyCode.toString();
} /**
* 生成随机验证码文件,并返回验证码值 (生成图片形式,用的较少)
*
* @param w
* @param h
* @param outputFile
* @param verifySize
* @return
* @throws IOException
*/
public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {
String verifyCode = generateVerifyCode(verifySize);
outputImage(w, h, outputFile, verifyCode);
return verifyCode;
} /**
* 生成指定验证码图像文件
*
* @param w
* @param h
* @param outputFile
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, File outputFile, String code) throws IOException {
if (outputFile == null) {
return;
}
File dir = outputFile.getParentFile();
//文件不存在
if (!dir.exists()) {
//创建
dir.mkdirs();
}
try {
outputFile.createNewFile();
FileOutputStream fos = new FileOutputStream(outputFile);
outputImage(w, h, fos, code);
fos.close();
} catch (IOException e) {
throw e;
}
} /**
* 输出指定验证码图片流
*
* @param w
* @param h
* @param os
* @param code
* @throws IOException
*/
public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {
int verifySize = code.length();
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Random rand = new Random();
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 创建颜色集合,使用java.awt包下的类
Color[] colors = new Color[5];
Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN,
Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
Color.PINK, Color.YELLOW};
float[] fractions = new float[colors.length];
for (int i = 0; i < colors.length; i++) {
colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
fractions[i] = rand.nextFloat();
}
Arrays.sort(fractions);
// 设置边框色
g2.setColor(Color.GRAY);
g2.fillRect(0, 0, w, h); Color c = getRandColor(200, 250);
// 设置背景色
g2.setColor(c);
g2.fillRect(0, 2, w, h - 4); // 绘制干扰线
Random random = new Random();
// 设置线条的颜色
g2.setColor(getRandColor(160, 200));
for (int i = 0; i < 20; i++) {
int x = random.nextInt(w - 1);
int y = random.nextInt(h - 1);
int xl = random.nextInt(6) + 1;
int yl = random.nextInt(12) + 1;
g2.drawLine(x, y, x + xl + 40, y + yl + 20);
} // 添加噪点
// 噪声率
float yawpRate = 0.05f;
int area = (int) (yawpRate * w * h);
for (int i = 0; i < area; i++) {
int x = random.nextInt(w);
int y = random.nextInt(h);
// 获取随机颜色
int rgb = getRandomIntColor();
image.setRGB(x, y, rgb);
}
// 添加图片扭曲
shear(g2, w, h, c); g2.setColor(getRandColor(100, 160));
int fontSize = h - 4;
Font font = new Font("Algerian", Font.ITALIC, fontSize);
g2.setFont(font);
char[] chars = code.toCharArray();
for (int i = 0; i < verifySize; i++) {
AffineTransform affine = new AffineTransform();
affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);
g2.setTransform(affine);
g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
} g2.dispose();
ImageIO.write(image, "jpg", os);
} /**
* 随机颜色
*
* @param fc
* @param bc
* @return
*/
private static Color getRandColor(int fc, int bc) {
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
} private static int getRandomIntColor() {
int[] rgb = getRandomRgb();
int color = 0;
for (int c : rgb) {
color = color << 8;
color = color | c;
}
return color;
} private static int[] getRandomRgb() {
int[] rgb = new int[3];
for (int i = 0; i < 3; i++) {
rgb[i] = random.nextInt(255);
}
return rgb;
} private static void shear(Graphics g, int w1, int h1, Color color) {
shearX(g, w1, h1, color);
shearY(g, w1, h1, color);
} private static void shearX(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(2); boolean borderGap = true;
int frames = 1;
int phase = random.nextInt(2); for (int i = 0; i < h1; i++) {
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period
+ (6.2831853071795862D * (double) phase)
/ (double) frames);
g.copyArea(0, i, w1, 1, (int) d, 0);
if (borderGap) {
g.setColor(color);
g.drawLine((int) d, i, 0, i);
g.drawLine((int) d + w1, i, w1, i);
}
} } private static void shearY(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(40) + 10; // 50; boolean borderGap = true;
int frames = 20;
int phase = 7;
for (int i = 0; i < w1; i++) {
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period
+ (6.2831853071795862D * (double) phase)
/ (double) frames);
g.copyArea(i, 0, 1, h1, 0, (int) d);
if (borderGap) {
g.setColor(color);
g.drawLine(i, (int) d, i, 0);
g.drawLine(i, (int) d + h1, i, h1);
} } }
}
实体类
User
package priv.dandelion.entity; public class User {
private Integer id;
private String username;
private String password; public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
} public User() {
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} 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;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
编码
Dao
UserMapper
package priv.dandelion.dao; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import priv.dandelion.entity.User; import java.util.List; public interface UserMapper {
@Select("select * from tb_user where username = #{name}")
public User selectByName(@Param("name") String name);
}
Service
UserService
package priv.dandelion.service; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import priv.dandelion.dao.UserMapper;
import priv.dandelion.entity.User;
import priv.dandelion.utils.SqlSessionFactoryUtils; public class UserService { private SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory(); public boolean selectUsername(String username) {
// 获取SqlSession
SqlSession sqlSession = factory.openSession(true);
// 获取UserMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 调用dao
User user = mapper.selectByName(username);
// 释放资源
sqlSession.close();
return user != null;
} }
Controller - Servlet
用户名是否存在
package priv.dandelion.controller.servlet; import priv.dandelion.service.UserService;
import priv.dandelion.utils.ReEncoding; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet("/selectUsername")
public class SelectUsernameServlet extends HttpServlet { UserService service = new UserService(); @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 接收用户名
String username = req.getParameter("username");
// 调用Service查询User
boolean flag = service.selectUsername(username);
// 响应标记
resp.getWriter().write("" + flag);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}展示验证码
package priv.dandelion.controller.servlet; import priv.dandelion.utils.CheckCodeUtil; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException; /**
* 验证码展示,并存储到Session
*/
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 存储验证码图片到本地
// OutputStream fos = new FileOutputStream("d://check-code.jpg"); // 使用Response字节输出流获取验证码
ServletOutputStream outputStream = resp.getOutputStream();
String checkCode = CheckCodeUtil.outputVerifyImage(100, 50, outputStream, 4); // 将验证码存储到Session中
HttpSession session = req.getSession();
session.setAttribute("checkCodeGenerate", checkCode);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
1.3.3 前端实现
步骤说明
- 给用户名输入框绑定光标失去事件
onblur
- 发送
Ajax
请求,携带username
参数 - 处理响应
- 给用户名输入框绑定光标失去事件
JS代码
检验用户名是否存在
// 给用户名输入框绑定发失去焦点事件
document.getElementById("username").onblur = function () {
// 发送ajax请求
// 获取用户名的值
var username = this.value; // 创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
// 建立连接
xhttp.open("GET", "http://localhost:8080/ajax-demo/selectUsername?username="+username);
// 发送请求
xhttp.send(); // 获取响应
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//判断
if(this.responseText == "true"){
//用户名存在,显示提示信息,清除style中的display的none
document.getElementById("username_err").style.display = '';
}else {
//用户名不存在,清除提示信息,设置style中的display为none,不显示
document.getElementById("username_err").style.display = 'none';
}
}
};
}
验证码刷新
// 验证码刷新
document.getElementById("changeImg").onclick = function () {
// 图片路径已经被缓存,需要在后面加参数进行刷新,为保证多次刷新,可以以时间毫秒数作为参数
document.getElementById("checkCodeImg").src = "/filter_demo/checkCode?"+new Date().getMilliseconds();
}
2、 Axios异步框架
Axios 对原生的AJAX进行封装,简化书写。
Axios官网是:
https://www.axios-http.cn
2.1 基本使用
引入Axios 的JavaScript文件
<script src="js/axios-0.18.0.js"></script>
发送请求并获取响应
axios({})
为发送请求部分,.then(function (resp){});
为回调函数,使用resp.data
可以获取到返回的结果get
axios({
method:"get",
url:"http://localhost:8080/ajax-demo1/aJAXDemo1?username=zhangsan"
}).then(function (resp){
alert(resp.data);
})
post
axios({
method:"post",
url:"http://localhost:8080/ajax-demo1/aJAXDemo1",
data:"username=zhangsan"
}).then(function (resp){
alert(resp.data);
});
2.2 快速入门
2.2.1 后端实现
package priv.dandelion.controller.servlet;
import priv.dandelion.utils.ReEncoding;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/axiosDemo")
public class AxiosDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 响应数据
String username = req.getParameter("username");
resp.getWriter().write("hello "+ username + " axios get~");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
resp.getWriter().write("hello "+ username + " axios post~");
}
}
2.2.2 前端实现
<script src="js/axios-0.18.0.js"></script>
<script>
// // get
// axios({
// method: "get",
// url: "http://localhost:8080/ajax-demo/axiosDemo?username=zhangsan"
// }).then(function (resp) {
// alert(resp.data);
// })
// post
axios({
method: "post",
url: "http://localhost:8080/ajax-demo/axiosDemo",
data:"username=zhangsan"
}).then(function (resp) {
alert(resp.data);
})
</script>
2.3 请求方法别名
为了方便起见, Axios 已经为所有支持的请求方法提供了别名。如下:
get
请求 :axios.get(url[,config])
delete
请求 :axios.delete(url[,config])
head
请求 :axios.head(url[,config])
options
请求 :axios.option(url[,config])
post
请求:axios.post(url[,data[,config])
put
请求:axios.put(url[,data[,config])
patch
请求:axios.patch(url[,data[,config])
get举例
axios.get("http://localhost:8080/ajax-demo/axiosServlet?username=zhangsan").then(function (resp) {
alert(resp.data);
})
post举例
axios.post("http://localhost:8080/ajax-demo/axiosServlet","username=zhangsan").then(function (resp) {
alert(resp.data);
})
3、 JSON
概念:
JavaScript Object Notation
。JavaScript 对象表示法
3.1 概述
JSON和JS定义对象格式的区别
JavaScript
{
name:"zhangsan",
age:23,
city:"北京"
}
JSON
{
"name":"zhangsan",
"age":23,
"city":"北京"
}
3.2 JSON基础语法
3.2.1 定义格式
基本定义格式
var 变量名 = '{"key":value,"key":value,...}';
value的数据类型
- 数字(整数或浮点数)
- 字符串(使用双引号括起来)
- 逻辑值(true或者false)
- 数组(在方括号中)
- 对象(在花括号中)
- null
value的数据类型示例
var jsonStr = '{"name":"zhangsan","age":23,"addr":["北京","上海","西安"]}'
3.2.2 代码格式
将JSON和JavaScript对象的相互转化
parse(str)
:将 JSON串转换为 js 对象。使用方式是:var jsObject = JSON.parse(jsonStr);
stringify(obj)
:将 js 对象转换为 JSON 串。使用方式是:var jsonStr = JSON.stringify(jsObject)
代码演示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSON-demo</title>
</head>
<body>
<script>
// 定义JSON字符串
var jsonStr = '{"name":"zhangsan","age":23,"addr":["北京","上海","西安"]}'
alert(jsonStr); // 将 JSON 字符串转为 JS 对象
let jsObject = JSON.parse(jsonStr);
alert(jsObject)
alert(jsObject.name)
// 将 JS 对象转换为 JSON 字符串
let jsonStr2 = JSON.stringify(jsObject);
alert(jsonStr2)
</script>
</body>
</html>
3.2.3 发送异步请求携带数据
- js 提供的
JSON
对象我们只需要了解一下即可。因为axios
会自动对 js 对象和JSON
串进行想换转换。- 发送异步请求时,如果请求参数是
JSON
格式,那请求方式必须是POST
。因为JSON
串需要放在请求体中。
使用
axios
发送请求时,如果要携带复杂的数据时都会以JSON
格式进行传递提前定义一个 js 对象,用来封装需要提交的参数,然后使用
JSON.stringify(js对象)
转换为JSON
串,再将该JSON
串作为axios
的data
属性值进行请求参数的提交var jsObject = {name:"张三"}; axios({
method:"post",
url:"http://localhost:8080/ajax-demo/axiosServlet",
data: JSON.stringify(jsObject)
}).then(function (resp) {
alert(resp.data);
})
axios
会自动将 js 对象转换为JSON
串进行提交
var jsObject = {name:"张三"};
axios({
method:"post",
url:"http://localhost:8080/ajax-demo/axiosServlet",
data:jsObject //这里 axios 会将该js对象转换为 json 串的
}).then(function (resp) {
alert(resp.data);
})
3.3 JSON串和Java对象的相互转换
Fastjson
是阿里巴巴提供的一个Java语言编写的高性能功能完善的JSON
库,是目前Java语言中最快的JSON
库,可以实现Java
对象和JSON
字符串的相互转换。
3.3.1 Fastjson 使用
依赖
<!-- JSON串和Java对象的相互转换 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
Java对象转JSON
String jsonStr = JSON.toJSONString(obj);
JSON转Java对象
User user = JSON.parseObject(jsonStr, User.class);
3.3.2 代码演示
public class FastJsonDemo {
public static void main(String[] args) {
// 将Java对象转为JSON字符串
User user = new User();
user.setId(1);
user.setUsername("zhangsan");
user.setPassword("123");
String jsonString = JSON.toJSONString(user);
System.out.println(jsonString);//{"id":1,"password":"123","username":"zhangsan"}
// 将JSON字符串转为Java对象
User u = JSON.parseObject("{\"id\":1,\"password\":\"123\",\"username\":\"zhangsan\"}", User.class);
System.out.println(u);
}
}
4、 案例
4.1 需求和方案
需求
- 使用AJAX+JSON完成品牌数据的查询和添加
方案
查询所有
- 页面加载完成后发送异步请求,获取数据列表
- controller调用service进行查询
- service查询到List集合,返回给controller
- controller将List转换为JSON
- 将JSON串使用Response写回页面
- 遍历字符串数据,展示表格
添加数据
点击添加按钮跳转到添加信息页面
输入内容点击提交,将数据封装为JSON格式,使用AJAX发送异步请求到后端
后端接收数据后反序列化JSON数据
由于前端提交的是 json 格式的数据,所以我们不能使用
request.getParameter()
方法获取请求参数- 如果提交的数据格式是
username=zhangsan&age=23
,后端就可以使用request.getParameter()
方法获取 - 如果提交的数据格式是 json,后端就需要通过 request 对象获取输入流,再通过输入流读取数据
- 如果提交的数据格式是
将获取到的JSON对象转换为Brand对象
调用Service的add()发明合法添加数据
将JSON数据返回给浏览器
4.2 查询所有功能
4.2.1 环境准备
SQL
-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
-- id 主键
id int primary key auto_increment,
-- 品牌名称
brand_name varchar(20),
-- 企业名称
company_name varchar(20),
-- 排序字段
ordered int,
-- 描述信息
description varchar(100),
-- 状态:0:禁用 1:启用
status int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
('小米', '小米科技有限公司', 50, 'are you ok', 1);
实体类
package priv.dandelion.entity; public class Brand {
// id 主键
private Integer id;
// 品牌名称
private String brandName;
// 企业名称
private String companyName;
// 排序字段
private Integer ordered;
// 描述信息
private String description;
// 状态:0:禁用 1:启用
private Integer status; public Brand() {
} public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
this.id = id;
this.brandName = brandName;
this.companyName = companyName;
this.ordered = ordered;
this.description = description;
this.status = status;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getBrandName() {
return brandName;
} public void setBrandName(String brandName) {
this.brandName = brandName;
} public String getCompanyName() {
return companyName;
} public void setCompanyName(String companyName) {
this.companyName = companyName;
} public Integer getOrdered() {
return ordered;
} public void setOrdered(Integer ordered) {
this.ordered = ordered;
} public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
} public Integer getStatus() {
return status;
} public void setStatus(Integer status) {
this.status = status;
} @Override
public String toString() {
return "Brand{" +
"id=" + id +
", brand_name='" + brandName + '\'' +
", company_name='" + companyName + '\'' +
", ordered=" + ordered +
", description='" + description + '\'' +
", status=" + status +
'}';
}
}
MyBatis核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--起别名-->
<typeAliases>
<package name="priv.dandelion.entity"/>
</typeAliases> <environments default="development">
<environment id="development">
<!-- 采用JDBC的事务管理方式 -->
<transactionManager type="JDBC"/>
<!-- 数据库连接信息 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- value的值一定不能换行,一定!一定!不能换行 -->
<property name="url" value="jdbc:mysql:///db1?useSSL=false&useUnicode=true&characterEncoding=utf-8&useServerPrepStmts=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 扫描mapper,加载SQL映射文件 -->
<mappers>
<package name="priv.dandelion.dao"/>
</mappers>
</configuration>
Mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="priv.dandelion.dao.BrandMapper"> <!-- 解决数据库与实体类命名不一致问题 -->
<resultMap id="brandResultMap" type="brand">
<result column="brand_name" property="brandName"></result>
<result column="company_name" property="companyName"></result>
</resultMap> </mapper>
Mapper接口
package priv.dandelion.dao; import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;
import priv.dandelion.entity.Brand; import java.util.List; public interface BrandMapper { @ResultMap("brandResultMap")
@Select("select * from tb_brand")
List<Brand> selectAll(); @Insert("insert into tb_brand " +
"values(null, #{brandName}, #{companyName}, " +
"#{ordered}, #{description}, #{status})")
void addBrand(Brand brand);
}工具类 - 获取SqlSession工厂
package priv.dandelion.utils; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException;
import java.io.InputStream; public class SqlSessionFactoryUtils { // 提升作用域,用于再方法内进行返回
private static SqlSessionFactory sqlSessionFactory; // 静态代码块会随着类的加载自动执行且只执行一次
static {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} public static SqlSessionFactory getSqlSessionFactory() {
return sqlSessionFactory;
} }
Service
package priv.dandelion.service; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import priv.dandelion.dao.BrandMapper;
import priv.dandelion.entity.Brand;
import priv.dandelion.utils.SqlSessionFactoryUtils; import java.util.List; public class BrandService {
SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory(); public List<Brand> selectAll() {
SqlSession sqlSession = sqlSessionFactory.openSession();
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
List<Brand> brands = mapper.selectAll();
sqlSession.close();
return brands;
} public void addBrand(Brand brand) {
SqlSession sqlSession = sqlSessionFactory.openSession(true);
BrandMapper mapper = sqlSession.getMapper(BrandMapper.class);
mapper.addBrand(brand);
sqlSession.close();
}
}
4.2.2 后端实现
Servlet
package priv.dandelion.controller.servlet; import com.alibaba.fastjson.JSON;
import priv.dandelion.entity.Brand;
import priv.dandelion.service.BrandService; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List; @WebServlet("/selectAll")
public class SelectAllServlet extends HttpServlet { BrandService service = new BrandService(); @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 调用service 查询
List<Brand> brands = service.selectAll();
// 将集合序列化为JSON数据
String jsonString = JSON.toJSONString(brands);
// 响应数据
// 处理中文数据
resp.setContentType("text/json;charset=utf-8");
resp.getWriter().write(jsonString);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
4.2.3 前端实现
引入JS文件
<script src="js/axios-0.18.0.js"></script>
监听监听页面加载完成事件,在页面加载完成后发送AJAX异步请求
// 当页面加载完成后发送AJAX请求
window.onload = function () {
// 发送AJAX请求
axios({
method:"get",
url:"http://localhost:8080//brand-demo-ajax/selectAll"
}).then(function (resp) {
// 获取数据
let brands = resp.data; // 表格数据
let tableData = "<tr>\n" +
" <th>序号</th>\n" +
" <th>品牌名称</th>\n" +
" <th>企业名称</th>\n" +
" <th>排序</th>\n" +
" <th>品牌介绍</th>\n" +
" <th>状态</th>\n" +
" <th>操作</th>\n" +
" </tr>"; for (let i = 0; i < brands.length; i++) {
let brand = brands[i];
// 对表格数据进行拼接
tableData += "<tr align=\"center\">\n" +
" <td>" + (i + 1) + "</td>\n" +
" <td>" + brand.brandName + "</td>\n" +
" <td>" + brand.companyName + "</td>\n" +
" <td>" + brand.ordered + "</td>\n" +
" <td>" + brand.destination + "</td>\n" +
" <td>" + brand.status + "</td>\n" +
"\n" +
" <td><a href=\"#\">修改</a> <a href=\"#\">删除</a></td>\n" +
" </tr>"
} // 设置表格对象
document.getElementById("brandTable").innerHTML = tableData;
})
}
整体页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="addBrand.html"><input type="button" value="新增"></a><br>
<hr>
<table id="brandTable" border="1" cellspacing="0" width="100%"> </table> <script src="js/axios-0.18.0.js"></script> <script>
// 当页面加载完成后发送AJAX请求
window.onload = function () {
// 发送AJAX请求
axios({
method:"get",
url:"http://localhost:8080//brand-demo-ajax/selectAll"
}).then(function (resp) {
// 获取数据
let brands = resp.data; // 表格数据
let tableData = "<tr>\n" +
" <th>序号</th>\n" +
" <th>品牌名称</th>\n" +
" <th>企业名称</th>\n" +
" <th>排序</th>\n" +
" <th>品牌介绍</th>\n" +
" <th>状态</th>\n" +
" <th>操作</th>\n" +
" </tr>"; for (let i = 0; i < brands.length; i++) {
let brand = brands[i];
// 对表格数据进行拼接
tableData += "<tr align=\"center\">\n" +
" <td>" + (i + 1) + "</td>\n" +
" <td>" + brand.brandName + "</td>\n" +
" <td>" + brand.companyName + "</td>\n" +
" <td>" + brand.ordered + "</td>\n" +
" <td>" + brand.destination + "</td>\n" +
" <td>" + brand.status + "</td>\n" +
"\n" +
" <td><a href=\"#\">修改</a> <a href=\"#\">删除</a></td>\n" +
" </tr>"
} // 设置表格对象
document.getElementById("brandTable").innerHTML = tableData;
})
}
</script> </body>
</html>
4.3 添加品牌功能
4.3.1 后端实现
Servlet部分
package priv.dandelion.controller.servlet; import com.alibaba.fastjson.JSON;
import priv.dandelion.entity.Brand;
import priv.dandelion.service.BrandService; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException; @WebServlet("/add")
public class AddBrandServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { BrandService service = new BrandService(); // 前端发送为JSON数据,不能使用request.getParameter接收数据 // 接收前端发送的JSON数据
BufferedReader reader = req.getReader();
String params = reader.readLine(); // 将JSON字符串反序列化为Java对象
Brand brand = JSON.parseObject(params, Brand.class); // 调用Service进行添加
service.addBrand(brand); // 响应成功标识
resp.getWriter().write("success");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
4.3.2 前端实现
导入JS
<script src="js/axios-0.18.0.js"></script>
给提交按钮绑定单击事件,并发送AJAX异步请求到服务器
// 给按钮绑定单击事件
document.getElementById("btn").onclick = function () {
// 将表单转换为JSON串
var formData = {
brandName:"",
companyName:"",
ordered:"",
description:"",
status:"",
}; // 获取表单数据
formData.brandName = document.getElementById("brandName").value;
formData.companyName = document.getElementById("companyName").value;
formData.description = document.getElementById("description").value;
formData.ordered = document.getElementById("ordered").value; // 获取单选的较为特殊,和单选的性质有关
let status = document.getElementsByName("status");
for (let i = 0;i < status.length; i++) {
if (status[i].checked) {
formData = status[i].value;
}
}
alert(formData); // 发送AJAX请求
axios({
method:"post",
url:"http://localhost:8080//brand-demo-ajax/add",
data:formData
}).then(function (resp) {
alert(resp.data);
// 判断响应数据是否为success
if (resp.data == "success") {
// 重定向到查询所有页面
location.href = "http://localhost:8080//brand-demo-ajax/brand.html";
}
})
}
完整代码
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>添加品牌</title>
</head>
<body>
<h3>添加品牌</h3>
<form action="" method="post">
品牌名称:<input id="brandName" name="brandName"><br>
企业名称:<input id="companyName" name="companyName"><br>
排序:<input id="ordered" name="ordered"><br>
描述信息:<textarea rows="5" cols="20" id="description" name="description"></textarea><br>
状态:
<input type="radio" name="status" value="0">禁用
<input type="radio" name="status" value="1">启用<br> <input type="button" id="btn" value="提交">
</form> <script src="js/axios-0.18.0.js"></script> <script>
// 给按钮绑定单击事件
document.getElementById("btn").onclick = function () {
// 将表单转换为JSON串
var formData = {
brandName:"",
companyName:"",
ordered:"",
description:"",
status:"",
}; // 获取表单数据
formData.brandName = document.getElementById("brandName").value;
formData.companyName = document.getElementById("companyName").value;
formData.description = document.getElementById("description").value;
formData.ordered = document.getElementById("ordered").value; // 获取单选的较为特殊,和单选的性质有关
let status = document.getElementsByName("status");
for (let i = 0;i < status.length; i++) {
if (status[i].checked) {
formData = status[i].value;
}
}
alert(formData); // 发送AJAX请求
axios({
method:"post",
url:"http://localhost:8080//brand-demo-ajax/add",
data:formData
}).then(function (resp) {
alert(resp.data);
// 判断响应数据是否为success
if (resp.data == "success") {
// 重定向到查询所有页面
location.href = "http://localhost:8080//brand-demo-ajax/brand.html";
}
})
}
</script> </body>
</html>
额外说明:
该部分代码略显臃肿,但是该示例的目的主要是对AJAX、Axios以及JSON相关知识点的整理和演示,后续通过前端框架可以大大简化该部分代码。
AJAX基础+Axios快速入门+JSON使用+综合案例的更多相关文章
- Objective-C基础语法快速入门
Objective-C基础语法快速入门 2010-11-04 16:32 折酷吧 zheku8 字号:T | T 假如我们对面向对象的思维已经C语言都很熟悉的话,对于我们学习Objective-C将会 ...
- 【个人笔记】003-PHP基础-01-PHP快速入门-03-PHP环境搭建
003-PHP基础-01-PHP快速入门 03-PHP环境搭建 1.客户端(浏览器) IE FireFox CHROME Opera Safari 2.服务器 是运行网站的基本 是放置程序代码的地方 ...
- 【个人笔记】002-PHP基础-01-PHP快速入门-02-PHP语言相关介绍输
002-PHP基础-01-PHP快速入门 02-PHP语言相关介绍 1.PHP是什么 Hypertext Preprocessor超文本预处理器 是一种通用开源脚本语言 Personal Home P ...
- 【个人笔记】001-PHP基础-01-PHP快速入门-01-PHP职业路线及PHP前景
001-PHP基础-01-PHP快速入门 01-PHP职业路线及PHP前景 PHP职业路线 PHP初级工程师 1年以下 3k-6k PHP中级工程师 1-3年6k-10k PHP高级工程师 3年以上 ...
- webpack快速入门——Json配置文件使用
在实际工作中,我们的项目都会配置一个Json的文件或者说API文件,作为项目的配置文件. 有时候你也会从后台读取到一个json的文件,这节课就学习如何在webpack环境中使用Json. 如果你会we ...
- 40、JSON数据源综合案例实战
一.JSON数据源综合案例实战 1.概述 Spark SQL可以自动推断JSON文件的元数据,并且加载其数据,创建一个DataFrame.可以使用SQLContext.read.json()方法,针对 ...
- php编程零基础如何快速入门。门头沟编程
昨天遇到一个人,说知道thinktphp,不过几年前的事了. 我先跟他讲了下,xyhcms后台功能,各个版块,以及数据库都介绍了一下. 跟他说了一个功能现场实现,说了实现方法. 然后上机操作,发现他表 ...
- ajax和axios请求本地json数据对比
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术,通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进 ...
- JDBC基础:JDBC快速入门,JDBC工具类,SQL注入攻击,JDBC管理事务
JDBC基础 重难点梳理 一.JDBC快速入门 1.jdbc的概念 JDBC(Java DataBase Connectivity:java数据库连接)是一种用于执行SQL语句的Java API,可以 ...
- Kettle基础及快速入门
(一)概述 1.ETL ETL(Extract-Transform-Load的缩写,即数据抽取.转换.装载的过程) ETL工具:Sqoop,DataX,Kettle,Talend等 2.Kettle介 ...
随机推荐
- web页面打开直接调用vlc播放视频
简介 大家都知道现在我们在网页所播放的视频都是h264编码格式,可以供所有设备正常播放.然而,相比h265它的体积更大.质量更差.目前h265大多应用于安防,体积小可以更好的存储,不过它也有着缺点,成 ...
- Prompt提示词助力AI写作
AI以极高的效率和还可以的输出质量,得到了许多写作人的青睐,Prompt作为AI写作的核心,通过简短的提示来引导AI生成文本,让写作新手也能轻松自如. 1. 看不下去的行业乱状 让人不禁遗憾的是,国外 ...
- 统计学习:EM算法及其在高斯混合模型(GMM)中的应用
1. EM算法的基本思想 我们在应用中所面对的数据有时是缺损的/观测不完全的[1][2].我们将数据分为: 可观测数据,用\(Y\)表示: 缺失数据,用\(Z\)表示; 完全数据,用\(X=(Y, Z ...
- C# 使用 运算符重载 隐式转换 对Point进行加减计算
运算符重载方便了我们对自定义类型(自定义的类或者结构体)的计算. 运算符重载关键字 operator. 除了这些运算符不支持:x.y.f(x).new.typeof.default.checked.u ...
- KPM算法求字符串的最小周期证明
先给出公式 ans = n - LPS[n-1] 其中ans为最小周期,n为给出的由假设的周期字符串中提取出的子串长度,LPS为前缀函数,n-1为字符串最后的位置下标 证明如下 证明ans = n - ...
- JDK8之前,匿名内部类访问的局部变量为什么必须要用final修饰
更多博文请关注:https://blog.bigcoder.cn 前不久在学习中意外发现了自己原来忽略的一个小知识点,挺有意思的,现在我来给大家分享一下! 我们先来看一段代码 public class ...
- CSS——基本选择器
例子: <head> <meta charset="UTF-8"> <title>Title</title> <style&g ...
- C#WPF的多屏显示问题
如果想让窗口在第二个屏幕中显示 public MainWindow() { InitializeComponent(); Screen[] _screens = Screen.AllScreens; ...
- Docker环境如何配置?使用阿里云OOS一步搞定!
背景介绍 系统运维管理OOS及扩展程序 系统运维管理OOS(CloudOps Orchestration Service)针对在阿里云ECS实例上部署应用和驱动的复杂性,特别设计了扩展程序,旨在简化用 ...
- vue3 函数式组件
今天看vue3中文文档 看到函数式组件不太理解上面写的 然后自己写了一下才理解上面的自己记录一下 先在子组件里面写上 <script> // dynameic 组件 import { h ...