1. Filter

1.1 概述

Filter:过滤器

Servlet、Filter和Listener称为Web的三大组件

生活中的过滤器:净水器、空气净化器、土匪

web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能

  • 过滤器的作用:

    • 一般用于完成一些通用的操作:登录验证、统一编码处理、敏感字符过滤等等

1.2 快速入门

  • 步骤:

    • 定义一个类,实现接口Filter
    • 复写方法
    • 配置拦截路径
      • web.xml
      • 注解
package com.mark.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException; /**
* @ClassName FilterDemo1
* @Description TODO 过滤器快速入门
* @Author Mark
* @Date 2022/8/17 11:59
* @Version 1.0
*/
@WebFilter("/*")//访问所有资源之前都会执行该过滤器
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("demo1被执行..."); //放行
filterChain.doFilter(servletRequest,servletResponse);
//如果不添加放行,则jsp页面将不会输出
} @Override
public void destroy() { }
}

1.3 过滤器细节

  • web.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1"> <filter>
    <filter-name>demo2</filter-name>
    <filter-class>com.mark.web.filter.FilterDemo2</filter-class>
    </filter> <filter-mapping>
    <filter-name>demo2</filter-name>
    <url-pattern>/*</url-pattern>
    <!--拦截路径-->
    </filter-mapping> </web-app>
  • 过滤器执行流程

    • 执行过滤器
    • 执行放行后的资源
    • 回来执行过滤器放行代码下边的代码
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    //对request对象的请求消息增强
    System.out.println("filterDemo3...执行了");
    //放行
    chain.doFilter(request, response);
    //对response的响应消息进行增强
    System.out.println("filterDemo3...回来了");
    }
    <html>
    <head>
    <title>$Title$</title>
    </head>
    <body>
    index.jsp <%
    System.out.println("index.jsp...");
    %>
    </body>
    </html>
    输出结果:
    filterDemo3...执行了
    index.jsp...
    filterDemo3...回来了
  • 过滤器生命周期方法

    • init():在服务器启动后创建Filter对象,然后调用init方法。一般用于加载资源
    • destroy():在服务器关闭后,Filter对象被销毁 。如果服务器正常关闭后,则会执行destroy方法。一般用于释放资源
    • doFilter():每一次请求被拦截资源时,会执行
  • 过滤器配置详解

    • 拦截路径配置

      • 具体资源路径:/index.jsp 将来只有访问index.jsp资源时,过滤器才会被执行

        • 拦截目录:/user/*访问/user(在Servlet配置路径时配置目录)下的所有资源时,过滤器都会被执行
        • 后缀名拦截: *.jsp访问所有后缀名为.jsp资源时,过滤器都会被执行
      • 拦截所有资源: /*
    • 拦截方式配置:资源被访问的方式

      • 注解配置

        • 设置dispatcherTypes属性

          • REQUEST:默认值,浏览器直接请求资源
          //浏览器直接请求资源时。该过滤器执行
          @WebFilter(value = "/*",dispatcherTypes = DispatcherType.REQUEST)
          • FORWORD:转发访问资源
          //只有转发访问index.jsp时,该过滤器才会被执行
          @WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
          //浏览器直接请求index.jsp或者转发访问index.jsp,该过滤器才会被执行
          @WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
          • INCLUDE:包含访问资源
          • ERROR:错误跳转资源
          • ASYNC:异步访问资源
      • web.xml配置

        设置dispatcher标签即可

      <dispatcher>FORWARD</dispatcher>
      <dispatcher>REQUEST</dispatcher>
  • 过滤器链(配置多个过滤器)

    • 执行顺序:如果有两个过滤器:过滤器1和过滤器2

      • 过滤器1
      • 过滤器2
      • 执行资源
      • 过滤器2
      • 过滤器1
    • 过滤器先后顺序问题

      • 注解配置:按照类名的字符串比较规则比较,值小的县知县

        如 AFilter 和 BFilter ,每一个字符分别比较,则AFilter先执行

      • web.xml配置:<filter-mapping>谁定义在上边,谁先执行

1.4 登录验证案例

  • 需求:

    1. 访问ShowUserAccess案例的资源。验证其是否登录
    2. 如果登录了,则直接放行。
    3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。
  • 分析

  • 代码实现
@WebFilter("/*")
public class LoginFilter implements Filter { @Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//0.强制转换
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//1.获取资源的请求路径
String uri = request.getRequestURI();
//2.判断是否包含相关登录资源路径,要注意排除掉 css/js/图片/验证码等资源
if (uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCodeServlet")) {
//包含,用户就是想登录。放行
chain.doFilter(req, resp);
} else {
//不包含,需要验证用户是否登录
//3.从session中获取user
Object user = request.getSession().getAttribute("user");
if (user != null){
//登陆了,放行
chain.doFilter(req, resp);
}else{
//没用登录,跳转到登陆页面
request.setAttribute("login_msg","您还没有登录,请先登录");
request.getRequestDispatcher("/login.jsp").forward(request,resp);
//这里如果用重定向不能资源共享,提示信息无法传递
}
}
} public void init(FilterConfig config) throws ServletException { } public void destroy() { } }

1.5 设计模式

设计模式:一些通用的解决固定问题的方式

  • 装饰模式

  • 代理模式

    • 概念:

      • 真实对象:被代理的对象
      • 代理对象:
      • 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
    • 实现方式:

      • 静态代理:有一个类文件描述代理模式

      • 动态代理:在内存中来形成代理类

        • 实现步骤

          1. 代理对象和真实对象实现相同的接口
          2. 代理对象 = Proxy.newProxyInstance();
          3. 使用代理对象调用方法
          4. 控制/增强方法
        package com.mark.proxy;
        
        import java.lang.reflect.InvocationHandler;
        import java.lang.reflect.Method;
        import java.lang.reflect.Proxy; /**
        * @ClassName ProxyTest
        * @Description TODO 动态代理实现
        * @Author Mark
        * @Date 2022/8/23 17:50
        * @Version 1.0
        */
        public class ProxyTest {
        public static void main(String[] args) {
        //1.创建真实对象
        Dell dell = new Dell(); //动态代理增强dell对象
        /*三个参数:
        1.类加载器:真实对象.getClass().getClassLoader()
        2.接口数组:真实对象.getClass().getInterfaces()
        3.处理器:new InvocationHandler() 核心业务的处理
        */
        SaleComputer proxy_dell = (SaleComputer) Proxy.newProxyInstance(dell.getClass().getClassLoader(), dell.getClass().getInterfaces(), new InvocationHandler() {
        /**
        * 代理逻辑编写的方法:代理对象调用的所有方法都会出发该方法执行
        * @param proxy 代理对象
        * @param method 代理对象调用的方法,被封装为的对象
        * @param args 代理对象调用的方法时,传递的实际参数
        * @return
        * @throws Throwable
        */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("该方法执行了");
        return null;
        }
        });
        //2.调用方法
        // String computer = proxy_dell.sale(7999);
        // System.out.println(computer);
        proxy_dell.show();
        }
        } //该方法执行了
        //null
        该方法执行了
        • 增强方法实现真实对象的方法
        Dell dell = new Dell();
        SaleComputer proxy_dell = (SaleComputer) Proxy.newProxyInstance(dell.getClass().getClassLoader(), dell.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //使用真实对象调用方法
        Object obj = method.invoke(dell, args);
        return obj;
        }
        }); String computer = proxy_dell.sale(7999);
        System.out.println(computer); 花了7999.0买了一台戴尔电脑...
        戴尔电脑
        • 增强方式

          • 增强参数列表
          Dell dell = new Dell();
          SaleComputer proxy_dell = (SaleComputer) Proxy.newProxyInstance(dell.getClass().getClassLoader(), dell.getClass().getInterfaces(), new InvocationHandler() {
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          //判断是否为sale方法
          if (method.getName().equals("sale")) {
          //增强参数
          double money = (double) args[0];
          money = money * 0.85;
          Object obj = method.invoke(dell, money);
          return obj;
          } else {
          Object obj = method.invoke(dell, args);
          return obj;
          }
          }
          }); //String computer = proxy_dell.sale(7999);
          //System.out.println(computer);
          proxy_dell.show(); //花了6799.15买了一台戴尔电脑...
          //戴尔电脑
          展示电脑
          • 增强返回值类型
          //判断是否为sale方法
          if (method.getName().equals("sale")) {
          //增强参数
          double money = (double) args[0];
          money = money * 0.85;
          String obj = (String) method.invoke(dell, money);
          //增强返回值
          return obj+" 鼠标垫";
          } else {
          Object obj = method.invoke(dell, args);
          return obj;
          } 花了6799.15买了一台戴尔电脑...
          戴尔电脑 鼠标垫
          • 增强方法体执行逻辑
          if (method.getName().equals("sale")) {
          //增强参数
          double money = (double) args[0];
          money = money * 0.85;
          System.out.println("专车接送");
          String obj = (String) method.invoke(dell, money);
          System.out.println("免费送货...");
          //增强返回值
          return obj+" 鼠标垫";
          } else {
          Object obj = method.invoke(dell, args);
          return obj;
          } 专车接送
          花了6799.15买了一台戴尔电脑...
          免费送货...
          戴尔电脑 鼠标垫

1.6 敏感词汇过滤

  • 需求

    1. 对ShowUserAccess案例录入的数据进行敏感词汇过滤
    2. 敏感词汇参考《敏感词汇.txt》
    3. 如果是敏感词汇,替换为 ***
  • 分析

  1. 需要对request对象进行增强。增强获取参数相关方法
  2. 放行。传递代理对象
  • 代码实现
package com.mark.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List; /**
* 敏感词汇过滤器
*/
@WebFilter("/*")
public class SensitiveFilter implements Filter { @Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1.创建代理对象,增强getParameter方法
ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强getParameter方法
//判断是否为getParameter方法
if (method.getName().equals("getParameter")) {
//增强返回值
//获取返回值
String value = (String) method.invoke(req, args);
if (value != null) {
for (String str : list) {
if (value.contains(str)) {
value = value.replaceAll(str, "***");
}
}
}
return value;
} else {
return method.invoke(req, args);
}
}
});
//2.放行
chain.doFilter(proxy_req, resp);
} private List<String> list = new ArrayList<String>();//敏感词汇List集合 public void init(FilterConfig config) throws ServletException {
try {
//1.加载文件
//获取文件真实路径
ServletContext servletContext = config.getServletContext();
String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
//2.读取文件
BufferedReader br = new BufferedReader(new FileReader(realPath));
//3.将文件的每一行数据添加到list中
String line = null;
while ((line = br.readLine()) != null) {
list.add(line);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
} } public void destroy() { } }
package com.mark.web.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException; @WebServlet("/testServlet")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String msg = request.getParameter("msg"); System.out.println(name+":"+msg);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}

登录后访问http://localhost/ShowUserAccess/testServlet?name=张三&msg=你个笨蛋,你个大坏蛋

访问结果:张三:你个***,你个大***

2. Listener

2.1 概述

Listener:监听器

  • 事件的监听机制:

    • 事件:一件事情
    • 事件源:事件发生的地方
    • 监听器:一个对象
    • 注册监听:将事件源、监听器绑定在一起。当事件源上发生某个事件后执行监听器代码
  • 概念:Web的三大组件之一。

  • ServletContextListener:监听ServletContext对象的创建和销毁

    • void contextDestroyed(ServletContextEvent sce):ServletContext对象被销毁前会调用该方法
    • void contextInitialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法

2.2 ServletContextListener的使用

  • 步骤:

    1. 定义一个类来实现ServletContextListener接口

    2. 复写方法

    3. 配置

      • web.xml配置
      <listener>
      <listener-class>com.mark.web.listener.ContextLoaderListener</listener-class>
      </listener>
      • 注解配置
      @WebListener
      public class ContextLoaderListener implements ServletContextListener { }
package com.mark.web.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener; /**
* @ClassName ContextLoaderListener
* @Description TODO
* @Author Mark
* @Date 2022/8/23 22:43
* @Version 1.0
*/
public class ContextLoaderListener implements ServletContextListener {
/**
* 监听ServletContext对象创建的。ServletContext对象服务器启动后自动创建
*
* 在服务器启动后自动调用
* @param servletContextEvent
*/
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象被创建了");
} /**
* 在服务器关闭后,ServletContext对象被销毁。当服务器正常关闭后该方法被调用
* @param servletContextEvent
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext对象被销毁了");
}
}

contextInitialized()一般用于加载资源文件

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//加载资源文件
//1.获取servletContext对象
ServletContext servletContext = servletContextEvent.getServletContext();
//2.加载资源文件
String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");
//3.获取真实路径
String realPath = servletContext.getRealPath(contextConfigLocation);
//4.加载进内存
try {
FileInputStream fis=new FileInputStream(realPath);
System.out.println(fis);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("ServletContext对象被创建了");
}
<listener>
<listener-class>com.mark.web.listener.ContextLoaderListener</listener-class>
</listener> <!--指定初始化参数-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/applicationContext.xml</param-value>
</context-param>

3. AJAX

3.1 概述

  • 概念:AJAX(Asynchronous JavaScript And XML):异步的JavaScript和XML

  • 作用:

    • 与服务器进行数据交换:通过AJAX可以给服务器发送请求,并获取服务器响应数据

      • 使用了AJAX和服务器进行通信,就可以使用HTML+AJAX来替换JSP页面

    • 异步交互:可以在不重新加载整个页面的情况下,与服务器交互数据并更新部分网页的技术,如:搜索联想、用户名是否可以校验,等等...

  • 异步同步详解

3.2 AJAX快速入门

  1. 编写AjaxServlet,并使用response输出字符串

    @WebServlet("/ajaxServlet")
    public class AjaxServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //1.响应数据
    response.getWriter().write("hello ajax");
    } @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doGet(request, response);
    }
    }
  2. 创建XMLHttpRequest对象:用于和服务器交换数据

  3. 向服务器发送请求

  4. 获取服务器响应数据

    <script>
    //1.创建核心对象
    var xhttp;
    if (window.XMLHttpRequest) {
    xhttp = new XMLHttpRequest();
    } else {
    // code for IE6, IE5
    xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //2.发送请求
    xhttp.open("GET", "http://localhost/myAJAX/ajaxServlet");//url写全路径
    xhttp.send();
    //3.获取响应
    xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
    alert(this.responseText);
    }
    };
    </script>

3.3 案例:验证用户名是否存在

  • 需求:在完成用户注册时,当用户名输入框失去焦点时,校验用户名是否在数据库已存在

  • 代码实现:
package com.mark.web;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException; @WebServlet("/selectUserServlet")
public class SelectUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.接收用户名
request.getParameter("username");
//2.调用service查询user对象
boolean flag = true;//模拟数据库操作
//3.响应标记
response.getWriter().write(""+flag);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
<!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> <script>
//1.用户名输入框失去焦点事件
document.getElementById("username").onblur = function () {
//2.发送ajax请求
//2.1 创建核心对象
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.2 发送请求
xhttp.open("GET", "http://localhost/myAJAX/selectUserServlet);//url写全路径
xhttp.send();
//2.3 获取响应
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
//判断
if (this.responseText == "true") {
//用户名存在,显示提示信息
document.getElementById("username_err").style.display = '';
} else {
//用户名不存在,清除提示信息
document.getElementById("username_err").style.display = 'none';
}
}
};
}
</script>
</body>
</html>

3.4 Axios异步框架

  • Axios对原生的AJAX进行封装,简化书写

  • 官网:https://www.axios-http.cn

  • Axios快速入门

    1. 引入axios的js文件

      <script src="js/axios-0.18.0.js"></script>
    2. 使用axios发送请求并获取响应结果

    package com.mark.web;
    
    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("/axiosServlet")
    public class AxiosServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("get...");
    //1.接收请求参数
    String username = request.getParameter("username");
    System.out.println(username);
    //2.响应数据
    response.getWriter().write("hello Axios");
    } @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("post...");
    this.doGet(request, response);
    }
    }
    <script>
    // //1.get
    // axios({
    // method:"get",
    // url:"http://localhost/myAJAX/axiosServlet?username=zhangsan"
    // }).then(function (resp) {
    // alert(resp.data);
    // }) //2.post
    axios({
    method: "post",
    url:"http://localhost/myAJAX/axiosServlet",
    data: "username=zhangsan"
    }).then(function (resp) {
    alert(resp.data);
    })
    </script>
  • Axious请求方式别名

    • 为了方便起见,Axious已经为所有支持的请求方法提供了别名。

      • axious.get(url[,config])
      • axious.post(url[,data[config]])
    //get
    // axios.get("http://localhost/myAJAX/axiosServlet?username=zhangsan").then(function (resp) {
    // alert(resp.data);
    // }) //post
    axios.post("http://localhost/myAJAX/axiosServlet","username=zhangsan").then(function (resp) {
    alert(resp.data);
    })
  • 改造案例:

document.getElementById("username").onblur = function () {
var username = this.value;
axios.post("http://localhost/myAJAX/selectUserServlet","username="+username).then(function (resp) {
if (resp.data == true){
document.getElementById("username_err").style.display = '';
}else {
document.getElementById("username_err").style.display = 'none';
}
})
}

4. JSON

4.1 概述

  • 概念:JavaScript Object Notation JavaScript对象表示法

    Person p = new Person();
    p.setName("zhangsan");
    p.setAge(22);
    p.setGender("male");
    var p = {"name":"zhangsan","age":22,"gender":"male"};
    • JSON现在多用于存储和交换文本信息的语法

      • 进行数据的传输
      • JSON比XML更小、更快、更快解析
  • 语法:

    • 基本规则

      • 数据在名称/值对中:json数据是由键值对构成的

        • 键用引号(单双都可以)引起来,也可以不使用引号
        • 值的取值类型:
          • 字符串:字符串值必须由双引号
          • 数字:整数或浮点数
          • 对象(JSON 对象):在花括号中 {"address":{"province":"陕西",...}...}
          • 数组:在方括号中 {"Person":[{},{},...],...}
          • 布尔
          • null
      • 数据由逗号分隔:多个键值对由逗号分隔
      • 花括号保存对象:使用{}定义json格式
      • 方括号容纳数组:[]
      <script>
      //1.定义基本格式
      var person = {"name": "张三", age: 22, 'gender': true};
      // alert(person);
      //2.嵌套格式 {} ——> []
      var persons = {"persons":[
      {"name":"张三","age":22,"gender":true},
      {"name":"李四","age":19,"gender":false},
      {"name":"王五","age":25,"gender":true}
      ]
      };
      // alert(persons);
      //3.嵌套格式 [] ——> {}
      var ps = [
      {"name":"张三","age":22,"gender":true},
      {"name":"李四","age":19,"gender":false},
      {"name":"王五","age":25,"gender":true}
      ];
      alert(ps);
      </script>

4.2 获取数据

  • 三种获取方式

    • json对象.键名

    • json对象["键名"]

      //获取name的值
      // var name = person.name;
      var name = person["name"];
      alert(name);//张三
    • 数组对象[索引]

      var name1 = persons.persons[2].name;
      alert(name1);//王五
      var name2 = ps[1].name;
      alert(name2);
  • Json的遍历

    • 遍历基本格式:for in循环

      //获取person对象中所有的键和值
      //for in循环
      for (var key in person) {
      // alert(key);//name age gender
      //这样的方式获取不到值,因为相当于 person."name"
      // alert(key+":"+person.key);//name age gender
      alert(key + ":" + person[key]);
      }
    • 遍历数组:双层for循环

      //获取p对象的所有键和值
      for (var i = 0; i < ps.length; i++) {
      var p = ps[i];
      for (var key in p) {
      alert(key + ":" + p[key])
      }
      }

4.3 JSON数据和Java对象的相互转换

JSON解析器

​ 常见的解析器:Jsonlib、Gson、fastjson、jackson

4.3.1 JSON转为Java对象

使用步骤:

  1. 导入jackson的相关jar包
  2. 创建jacason核心对象ObjectMapper
  3. 调用ObjectMapper的相关方法进行转换
    • readValue(json字符串数据,Class类型)
/**
* json字符串转为Java对象
* @throws Exception
*/
@Test
public void test5() throws Exception{
//1.初始化json字符串
String json = "{\"gender\":\"male\",\"name\":\"张三\",\"age\":23}";
//2.创建objectMapper对象
ObjectMapper mapper = new ObjectMapper();
//转换为Java对象
Person person = mapper.readValue(json, Person.class);
System.out.println(person);
//Person{name='张三', age=23, gender='male', birthday=null}
}

4.3.2 Java对象转为JSON

  • jackson使用步骤

    1. 导入jackson的相关jar包
    2. 创建jacason核心对象ObjectMapper
    3. 调用ObjectMapper的相关方法进行转换
      • writeValue(参数1,obj)方法
      • writeValueAsString(obj):将对象转为json字符串
    //Java对象转为Json字符串
    @Test
    public void test1() throws Exception {
    //1.创建Person对象
    Person p = new Person();
    p.setName("张三");
    p.setAge(22);
    p.setGender("male"); //2.创建Jackson的核心对象ObjectMapper
    ObjectMapper mapper = new ObjectMapper();
    //3.转换
    /*
    转换方法:
    writeValue(参数1,obj)方法
    参数1:
    File:将obj对象转换为JSON字符串并保存到指定的文件中
    Writer:将obj对象转换为JSON字符串并将json数据填充到字符输出流中
    OutputStream:将obj对象转换为JSON字符串并将json数据填充到字节输出流中
    writeValueAsString(obj):将对象转为json字符串
    */
    String json = mapper.writeValueAsString(p);
    //System.out.println(json);
    //{"name":"张三","age":22,"gender":"male"} //writeValue(),将数据写到d://a.txt文件中
    mapper.writeValue(new File("d://a.txt"),p); //writeValue(),将数据关联到字符输出流
    mapper.writeValue(new FileWriter("d://b.txt"),p);
    }
  • 注解

    • @JsonIgnore:排除属性
    • @JsonFormat:属性值的格式化
    //@JsonIgnore//转换Json字符串忽略该属性
    @JsonFormat(pattern = "yyyy-MM-dd")//设置属性的格式
    private Date birthday;
  • 复杂的Java对象转换

    • List:数组

      @Test
      public void test3() throws Exception{
      //1.创建Person对象
      Person p1 = new Person();
      p1.setName("张三");
      p1.setAge(22);
      p1.setGender("male");
      p1.setBirthday(new Date()); Person p2 = new Person();
      p2.setName("李四");
      p2.setAge(18);
      p2.setGender("female");
      p2.setBirthday(new Date()); Person p3 = new Person();
      p3.setName("王五");
      p3.setAge(25);
      p3.setGender("male");
      p3.setBirthday(new Date()); //创建List集合
      List<Person> ps = new ArrayList<Person>(); ps.add(p1);
      ps.add(p2);
      ps.add(p3); //2.转换
      ObjectMapper mapper = new ObjectMapper();
      String json = mapper.writeValueAsString(ps);
      System.out.println(json);
      //[{"name":"张三","age":22,"gender":"male","birthday":"2022-08-24"},{"name":"李四","age":18,"gender":"female","birthday":"2022-08-24"},{"name":"王五","age":25,"gender":"male","birthday":"2022-08-24"}]
      }
    • Map:对象格式一致

      @Test
      public void test4() throws Exception{
      //创建map对象
      Map<String,Object> map = new HashMap<String,Object>();
      map.put("name","张三");
      map.put("age",23);
      map.put("gender","male"); //2.转换
      ObjectMapper mapper = new ObjectMapper();
      String json = mapper.writeValueAsString(map);
      System.out.println(json);
      //{"gender":"male","name":"张三","age":23}
      }

5. Redis

5.1 概述

  • 概念:redis是一款高性能的NoSQL系列的非关系型数据库

  • 关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,让NoSQL数据库对关系型数据库的不足进行弥补。一般会将数据存储在关系型数据库中,在nosql数据库中备份存储关系型数据库的数据

  • Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库。目前为止Redis支持的键值数据类型如下:

    • 字符串类型 string
    • 哈希类型 hash
    • 列表类型 list
    • 集合类型 set
    • 有序集合类型 sortedset
  • redis的应用场景:

    • 缓存(数据查询、短连接、新闻内容、商品内容等等)
    • 聊天室的在线好友列表
    • 任务队列。(秒杀、抢购、12306等等)
    • 应用排行榜
    • 网站访问统计
    • 数据过期处理(可以精确到毫秒)
    • 分布式集群架构中的session分离
  • 下载安装

    • 官网:https://redis.io
    • 中文网:https://www.redis.net.cn/
    • 绿色版解压直接可以使用:
      • redis.windows.conf:配置文件
      • redis-cli.exe:redis的客户端
      • redis-server.exe:redis的服务器端

    先开启服务器端

    再开启客户端

5.2 命令操作

  • redis的数据结构

    • redis存储的是:key,value格式的数据,其中key都是字符串,value有5种不同的数据结构

      • value的数据结构:

        • 字符串类型 string
        • 哈希类型 hash:map格式
        • 列表类型 list:linkedlist格式
        • 集合类型 set
        • 有序集合类型 sortedset

  • 字符串类型 String

    • 存储set key value
    • 获取get key
    • 删除del key
    127.0.0.1:6379> set username zhangsan
    OK
    127.0.0.1:6379> get username
    "zhangsan"
    127.0.0.1:6379> del username
    (integer) 1
  • 哈希类型 hash

    • 存储hset key filed value

    • 获取hget key field

      hgetall key

    • 删除hdel key field

    127.0.0.1:6379> hset myhash username lisi
    (integer) 1
    127.0.0.1:6379> hset myhash password 123
    (integer) 1
    127.0.0.1:6379> hget myhash username
    "lisi"
    127.0.0.1:6379> hget myhash password
    "123"
    127.0.0.1:6379> hgetall myhash
    1) "username"
    2) "lisi"
    3) "password"
    4) "123"
    127.0.0.1:6379> hdel myhash username
    (integer) 1
    127.0.0.1:6379> hdel myhash password
    (integer) 1
  • 列表类型 list:可以添加一个元素到列表的头部(左边)或者尾部(右边)

    • 存储lpush key value:将元素加入列表左边

      rpush key value:将元素加入列表右边

    • 获取lrange key start end:范围获取

    • 删除lpop key:删除列表最左边的元素,并将元素返回

      rpop key:删除列表最右边的元素,并将元素返回

    127.0.0.1:6379> lpush mylist a
    (integer) 1
    127.0.0.1:6379> lpush mylist b
    (integer) 2
    127.0.0.1:6379> rpush mylist c
    (integer) 3
    127.0.0.1:6379> lrange mylist 0 -1
    1) "b"
    2) "a"
    3) "c"
    127.0.0.1:6379> lpop mylist
    "b"
    127.0.0.1:6379> rpop mylist
    "c"
  • 集合类型 set:不允许重复元素

    • 存储sadd key value
    • 获取smembers key:获取set集合中所有元素
    • 删除srem key value:删除set集合中的某个元素
127.0.0.1:6379> sadd myset a
(integer) 1
127.0.0.1:6379> sadd myset a
(integer) 0
127.0.0.1:6379> smembers myset
1) "a"
127.0.0.1:6379> sadd myset b c d
(integer) 3
127.0.0.1:6379> smembers myset
1) "a"
2) "d"
3) "c"
4) "b"
127.0.0.1:6379> srem myset c
(integer) 1
127.0.0.1:6379> smembers myset
1) "a"
2) "d"
3) "b"
  • 有序集合类型 sortedset:不允许重复元素,且元素有序

    • 存储zadd key score value:存储数据以及数据对应的分数

    • 获取zrange key start end:获取范围所有元素

      zrange mysort start end withscores:获取范围所有元素带分数

    • 删除zrem key value:删除某个元素

127.0.0.1:6379> zadd mysort 60 zhangsan
(integer) 1
127.0.0.1:6379> zadd mysort 50 lisi
(integer) 1
127.0.0.1:6379> zadd mysort 80 wangwu
(integer) 1
127.0.0.1:6379> zrange mysort 0 -1
1) "lisi"
2) "zhangsan"
3) "wangwu"
127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "lisi"
2) "50"
3) "zhangsan"
4) "60"
5) "wangwu"
6) "80"
127.0.0.1:6379> zadd mysort 500 lisi
(integer) 0
127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "zhangsan"
2) "60"
3) "wangwu"
4) "80"
5) "lisi"
6) "500"
127.0.0.1:6379> zrem mysort lisi
(integer) 1
127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "zhangsan"
2) "60"
3) "wangwu"
4) "80"
  • 通用命令

    • keys * :查询所有的键
    • type key:查看键对应的value数据类型
    • del key:删除指定的key value

5.3 持久化操作

redis是一个内存的数据库,当redis服务器重启,或者电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘的文件中。

  • redis的持久化机制

    • RDB:默认方式,不需要进行配置,默认就是用这种机制

      • 在一定的间隔时间中,检测key的变化情况,然后持久化数据
      1. 编辑redis.windows.conf文件

        save 900 1
        save 300 10
        save 60 10000 # after 900 sec (15 min) if at least 1 key changed
        # after 300 sec (5 min) if at least 10 keys changed
        # after 60 sec if at least 10000 keys changed
      2. 重新启动redis服务器并指定配置文件名称

        D:\Code\dependent\redis-2.8.9>redis-server.exe redis.windows.conf

    • AOF:日志记录的方式,可以记录每一条命令的操作。可以在每一次命令操作后,持久化数据

      • 编辑redis.windows.conf文件

        #appendonly no #默认为no
        #需要修改为yes
        appendonly yes #开启AOF持久化机制 # appendfsync always:每一次操作都进行持久化
        appendfsync everysec #每隔一秒进行一次持久化
        # appendfsync no:不进行持久化

5.4 Java客户端操作redis:Jedis

5.4.1 概述

Jedis:一款java操作redis数据库的工具

  • 使用步骤:

    • 下载Jedis的jar包
    • 使用
  • 快速入门:

    • 获取链接
    • 调用对应方法
    • 关闭链接
    /**
    * 快速入门
    */
    @Test
    public void test1() {
    //1.获取链接
    Jedis jedis = new Jedis("localhost",6379);
    //2.调用对应方法操作
    jedis.set("username","zhangsan");
    //3.关闭链接
    jedis.close();
    }

5.4.2 Jedis操作各种数据

  • Jedis操作string

    @Test
    public void test2() {
    Jedis jedis = new Jedis();//空参构造,默认值"localhost",6379 jedis.set("username", "zhangsan"); String username = jedis.get("username");
    System.out.println(username); //可以使用setex()方法存储可以指定过期时间的key value
    jedis.setex("activecode", 20, "haha");//将activecode:hehe键值对存入redis,并且20s后自动删除该键值对 String activecode = jedis.get("activecode");
    System.out.println(activecode); jedis.close();
    }
  • Jedis操作hash

    @Test
    public void test3() {
    Jedis jedis = new Jedis();//空参构造,默认值"localhost",6379 jedis.hset("user","name","lisi");
    jedis.hset("user","age","22");
    jedis.hset("user","gender","male"); //获取
    String name = jedis.hget("user", "name");
    System.out.println(name); Map<String, String> user = jedis.hgetAll("user");
    for (String key : user.keySet()) {
    String value = user.get(key);
    System.out.println(key+":"+value);
    } jedis.close();
    }
  • Jedis操作list

    @Test
    public void test5() {
    Jedis jedis = new Jedis("localhost", 6379); jedis.lpush("mylist","a","b","c");
    jedis.rpush("mylist","b","c"); List<String> mylist = jedis.lrange("mylist", 0, -1);
    System.out.println(mylist); String element1 = jedis.lpop("mylist");
    System.out.println(element1); String element2 = jedis.rpop("mylist");
    System.out.println(element2); List<String> mylist2 = jedis.lrange("mylist", 0, -1);
    System.out.println(mylist2); jedis.close();
    } [c, b, a, b, c]
    c
    c
    [b, a, b]
  • Jedis操作set

    @Test
    public void test5() {
    Jedis jedis = new Jedis("localhost", 6379); jedis.sadd("myset","java","php","C++");
    Set<String> myset = jedis.smembers("myset");
    System.out.println(myset); jedis.close();
    }
  • Jedis操作sortedset

    @Test
    public void test6() {
    Jedis jedis = new Jedis("localhost", 6379); jedis.zadd("mysort",50,"zhangsan");
    jedis.zadd("mysort",60,"lisi");
    jedis.zadd("mysort",100,"wangwu"); Set<String> mysort = jedis.zrange("mysort", 0, -1);
    System.out.println(mysort); jedis.close();
    }

5.4.3 Jedis连接池:JedisPool

  • 使用

    • 创建JedisPool连接池对象
    • 调用方法getResource()方法获取Jedis连接
    @Test
    public void test7() {
    //0.创建一个配置对象
    JedisPoolConfig config=new JedisPoolConfig();
    config.setMaxTotal(50);//设置最大允许的连接数
    config.setMaxIdle(10);//设置最大空闲连接 //1.创建Jedis连接池对象
    JedisPool jedisPool = new JedisPool(config,"localhost",6379);//可以空构造,有默认参数 //2.获取连接
    Jedis jedis = jedisPool.getResource(); //3.使用jedis
    jedis.set("hehe","haha"); //4.关闭 归还到连接池
    jedis.close();
    }
  • JedisPool工具类

    public class JedisUtils {
    private static JedisPool jedisPool; static {
    //读取配置文件
    InputStream is = JedisUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
    //创建Properties对象
    Properties pro = new Properties();
    //关联文件
    try {
    pro.load(is);
    } catch (IOException e) {
    e.printStackTrace();
    }
    //获取数据,设置到jedisPoolConfig中
    JedisPoolConfig config = new JedisPoolConfig();
    config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
    config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle"))); //初始化JedisPool连接池
    jedisPool =new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));
    } /**
    * 获取连接的方法
    */
    public static Jedis getJedis(){
    return jedisPool.getResource();
    }
    }
    /**
    * Jedis工具类测试
    */
    @Test
    public void test8(){
    Jedis jedis = JedisUtils.getJedis(); jedis.set("username","zhangsan"); String username = jedis.get("username");
    System.out.println(username); jedis.close();
    }

6. Maven

6.1 概述

  • Maven是一个项目管理工具,它包含了一个项目对象模型 (POM:Project Object Model),一个依赖管理系统(Dependency Management System),一组标准集合,一个项目生命周期(Project Lifecycle),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。
  • Maven可以解决什么问题?
    • 我们需要引用各种jar包,尤其是比较大的工程,引用的jar包往往有几十个乃至上百个, 每用到一种jar包,都需要手动引入工程目录,而且经常遇到各种让人抓狂的jar包冲突,版本冲突。
    • 可以帮助我们管理项目的生命周期:编译、测试、打包部署...
  • Maven的下载安装
    • 官网下载https://maven.apache.org/download.cgi
    • 解压即安装完成
    • 将maven添加至环境变量

6.2 Maven仓库

仓库作用:存放jar包和插件

  • Maven仓库的分类:

    • 本地仓库:用来存储从远程仓库或中央仓库下载的插件和 jar 包,项目使用一些插件或 jar 包,

    优先从本地仓库查找

    *远程仓库(私服):如果本地需要插件或者 jar 包,本地仓库没有,默认去远程仓库下载。远程仓库可以在互联网内也可以在局域网内。

    *中央仓库:在 maven 软件中内置一个远程仓库地址 http://repo1.maven.org/maven2 ,它是中

    央仓库,服务于整个互联网,它是由 Maven 团队自己维护,里面存储了非常全的 jar 包,它包

    含了世界上大部分流行的开源项目构件

项目使用到一些插件和jar包时,会从本地仓库去查找,如果本地仓库没有,就会从中央仓库下载到本地仓库。由于中央仓库访问较慢且有些不开源的jar包中央仓库没有,也不能向中央仓库添加jar包,公司就会架设自己的远程仓库。有了远程仓库,项目使用jar包时先从本地仓库查找,没有的话就会从远程仓库找,找到了就下载到本地仓库,如果远程仓库也没有,就会从中央仓库查找并下载到远程仓库,这样本地仓库就可以从远程仓库继续下载了。本地仓库就是本地文件夹,当第二次需要此jar 包时则不再从远程仓库下载,因为本地仓库已经存在了,可以将本地仓库理解为缓存,有了本地仓库就不用每次从远程仓库下载了。

  • 配置本地仓库

    默认本地仓库位置:${user.home}/.m2/repository

    • 打开apache-maven-3.8.6\conf\settings.xml文件
    • 在maven安装目录创建mvn_repository文件夹
    • 添加<localRepository>D:\apache-maven-3.8.6\mvn_repository</localRepository>
    • 保存即修改本地仓库目录为mvn_repository
  • 配置远程仓库(这里配置阿里云的私服)

    • 将阿里云私服配置复制粘贴到maven配置文件settings.xml中<mirrors>标签中

      <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>
      </mirror>

6.3 Maven工程的认识

6.4 Maven常用命令

  • compile:compile是maven工程的编译命令,作用是将src/main/java下的文件编译为class文件输出到target目录下。
  • clean:clean是maven工程的清理命令,执行 clean会删除target目录及内容。
  • package:package是maven工程的打包命令(会自动执行编译命令),对于java工程执行package打成jar包,对于web工程打成war包。
  • install:install是maven工程的安装命令,执行install将maven打成jar包或war包发布到本地仓库。

6.5 Maven生命周期

maven对项目构建过程分为三套相互独立的生命周期,请注意这里说的是“三套”,而且“相互独立”,这三套生命周期分别是:

  • Clean Lifecycle 在进行真正的构建之前进行一些清理工作。
  • Default Lifecycle 构建的核心部分,编译,测试,打包,部署等等。
  • Site Lifecycle 生成项目报告,站点,发布站点。

同一套生命周期中,执行后面的操作,会自动执行前边所有的操作!

每一个生命收起其实对应的就是一些插件

6.6 IDEA配置Maven环境

打开File—>Settings配置maven

  • Maven坐标:被Maven管理的资源的唯一标识

    • groupId:组织名称
    • artifactId:模块名称
    • version:版本号
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.9</version>
    <scope>test</scope>
    </dependency>

    上述代码就会使用apache-maven-3.8.6\mvn_repository\junit\junit\4.9下的jar包

    <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
    </dependency>

    上述代码就会使用apache-maven-3.8.6\mvn_repository\javax\servlet\jsp\jsp-api\2.0下的jar包

  • 使用IDEA创建Maven的Java项目(不使用骨架/模板)

    • new—>Module..—>Maven

    • 此时就创建好了一个java项目,并自动显示pom.xml文件

  • 使用IDEA创建Maven的Java项目(使用骨架/模板)

    • new—>Module..—>Maven

  • 使用IDEA创建Maven的Web项目(不使用骨架/模板)

    • 创建后首先设置打包方式为war

      <packaging>war</packaging>
    • 补全目录结构

    • 在settings--->Editor--->File and Code Templates--->other--->Web--->Deployment descriptors下找一个xml模板粘贴到web.xml中

6.7 Java项目编写代码并运行

  • 编写代码

  • 依赖导入jar包

    <!--导入单元测试jar包-->
    <dependencies>
    <!-- https://mvnrepository.com/artifact/junit/junit -->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    </dependency>
    </dependencies>
  • 设置maven编译插件

    alt+Insert导入插件模板

    <!--添加插件-->
    <build>
    <plugins>
    <!--编译插件-->
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <!--设置编译版本-->
    <configuration>
    <target>14</target>
    <source>14</source>
    </configuration>
    </plugin>
    </plugins>
    </build>

6.8 使用Tomcat8插件启动JaveWeb项目

在pom中添加配置

<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version> <configuration>
<!--修改tomcat启动的端口号-->
<port>80</port>
<!--修改tomcat部署当前项目虚拟目录(项目的访问根目录)-->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>

插件中双击run即可运行成功

在运行servlet时需要加入依赖范围

<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!--依赖范围-->
<scope>provided</scope>
</dependency>
</dependencies>
依赖范围 对编译classpath有效 对测试classpath有效 对运行时classpath有效 例子
compile Y Y Y spring-core
test Y Junit
provided Y Y servlet-api
runtime Y Y JDBC驱动
system Y Y 本地的Maven仓库之外的类库

总结:

  • 默认引入 的 jar 包 ------- compile 【默认范围,可以不写】(编译、测试、运行 都有效 )
  • servlet-api 、jsp-api ------- provided (编译、测试有效, 运行时无效,防止和 tomcat 下 jar 冲突)
  • jdbc 驱动 jar 包 ---- runtime (测试、运行有效 )
  • junit ----- test (测试有效)

依赖范围由强到弱的顺序是:compile>provided>runtime>test

7. Vue

7.1 快速入门

  • 新建HTML页面,引入Vue.js文件

    <script src="js/vue.js"></script>

  • 在JS代码区域,创建Vue核心对象,进行数据绑定

    <script>
    new Vue({
    //#选择器,选择id为app的div
    el: "#app",
    data() {
    return {
    username: ""
    }
    }
    /*
    data: function() {
    return {
    username: ""
    }
    }
    */ });
    </script>
  • 编写视图

    <div id="app">
    <input v-model="username">
    <!--插值表达式-->
    {{username}}
    </div>

7.2 常用指令

  • 指令:HTML标签上带有-v前缀的特殊属性,不同指令具有不同的含义。

  • 常用指令:

    指令 周期
    v-bind 为HTML标签绑定属性值,如设置href、css样式等
    v-model 在表单元素上创建双向数据绑定
    v-on 为HTML标签绑定事件
    v-if 条件性的渲染某元素,判定为true时渲染,否则不渲染
    v-else 条件性的渲染某元素,判定为true时渲染,否则不渲染
    v-else-if 条件性的渲染某元素,判定为true时渲染,否则不渲染
    v-show 根据条件展示某元素,区别在于切换的是display属性的值
    v-for 列表渲染,遍历容器的元素或者对象的属性
  • v-bind、v-model

    <div id="app">
    <!--<a v-bind:href="url">百度一下</a>-->
    <a :href="url">哔哩哔哩</a><!--绑定超链接为url路径--> <input v-model="url"><!--输入框的值与url的值进行数据双向绑定-->
    </div> <script src="js/vue.js"></script> <script>
    new Vue({
    el: "#app",
    data() {
    return {
    url:"https://www.bilibili.com"
    }
    }
    });
    </script>
  • v-on

    <div id="app">
    <!--单击事件,绑定show方法-->
    <input type="button" value="按钮" v-on:click="show()">
    <input type="button" value="按钮a" @click="show()">
    </div> <script src="js/vue.js"></script> <script>
    new Vue({
    el: "#app",
    methods:{
    show(){
    alert("别点我");
    }
    }
    });
    </script>
  • v-if、v-else-if、v-else、v-show

    <div id="app">
    <!--当count=3时显示div1-->
    <div v-if="count == 3">div1</div>
    <!--当count=4时显示div2-->
    <div v-else-if="count == 4">div2</div>
    <!--当count的值为其他值时显示div3-->
    <div v-else>div3</div>
    <br>
    <input v-model="count"> <hr>
    <!--当count=3时显示div v-show-->
    <div v-show="count == 3">div v-show</div>
    </div> <script src="js/vue.js"></script> <script>
    new Vue({
    el: "#app",
    data() {
    return {
    count: 3
    }
    }
    });
    </script>
    • v-if操作的是dom树,当条件不满足时,不渲染,在源码中无法找到不满足条件的源码
    • v-show操作的是display属性,当条件不满足时,display为none
  • v-for

    <div id="app">
    <div v-for="addr in addrs">
    {{addr}}<br>
    </div> <div v-for="(addr,i) in addrs">
    {{i+1}}--{{addr}}<br>
    </div> <div :data="addrs"> </div>
    </div> <script src="js/vue.js"></script> <script>
    new Vue({
    el:"#app",
    data(){
    return{
    addrs:["北京","西安","宝鸡"]
    }
    }
    });
    </script>

7.3 生命周期

  • 生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法(钩子)

    状态 阶段周期
    beforeCreate 创建前
    created 创建后
    beforeMount 载入前
    mounted 挂载完成
    beforeUpdate 更新前
    updated 更新后
    beforeDestroy 销毁前
    destroyed 销毁后
  • mounted:挂载完成,Vue初始化成功,HTML页面渲染成功。

    • 发送异步请求,加载数据
    <script src="js/vue.js"></script>
    
    <script>
    new Vue({
    el: "#app",
    mounted() {
    alert("挂载完成,发送ajax请求")
    }
    });
    </script>

7.4 案例

查询所有:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div id="app">
<a href="addBrand.html"><input type="button" value="新增"></a><br>
<hr>
<table id="brandTable" border="1" cellspacing="0" width="100%">
<tr>
<th>序号</th>
<th>品牌名称</th>
<th>企业名称</th>
<th>排序</th>
<th>品牌介绍</th>
<th>状态</th>
<th>操作</th>
</tr> <!--使用v-for遍历tr-->
<tr v-for="(brand,i) in brands" align="center">
<td>{{i + 1}}</td>
<td>{{brand.brandName}}</td>
<td>{{brand.companyName}}</td>
<td>{{brand.ordered}}</td>
<td>{{brand.description}}</td>
<td>{{brand.status}}</td>
<td><a href="#">修改</a> <a href="#">删除</a></td>
</tr> </table>
</div> <script src="js/axios-0.18.0.js"></script>
<script src="js/vue.js"></script> <script>
/*//1. 当页面加载完成后,发送ajax请求
window.onload = function () {
//2. 发送ajax请求
axios({
method:"get",
url:"http://localhost/selectAllServlet"
}).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 += "\n" +
" <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.description+"</td>\n" +
" <td>"+brand.status+"</td>\n" +
"\n" +
" <td><a href=\"#\">修改</a> <a href=\"#\">删除</a></td>\n" +
" </tr>";
} // 设置表格数据
document.getElementById("brandTable").innerHTML = tableData;
})
}*/
new Vue({
el: "#app",
data() {
return {
brands: []
}
},
mounted() {
var _this = this;
axios({
method: "get",
url: "http://localhost/selectAllServlet"
}).then(function (resp) {
_this.brands = resp.data;
})
} })
</script>
</body>
</html>

新增品牌

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>添加品牌</title>
</head>
<body>
<div id="app">
<h3>添加品牌</h3>
<form action="" method="post">
品牌名称:<input id="brandName" v-model="brand.brandName" name="brandName"><br>
企业名称:<input id="companyName" v-model="brand.companyName" name="companyName"><br>
排序:<input id="ordered" v-model="brand.ordered" name="ordered"><br>
描述信息:<textarea rows="5" cols="20" id="description" v-model="brand.description"
name="description"></textarea><br>
状态:
<input type="radio" name="status" v-model="brand.status" value="0">禁用
<input type="radio" name="status" v-model="brand.status" value="1">启用<br> <input type="button" id="btn" value="提交" @click="submitForm">
</form>
</div> <script src="js/axios-0.18.0.js"></script>
<script src="js/vue.js"></script> <script>
/*document.getElementById("btn").onclick = function () {
var formData = {
brandName: "",
companyName: "",
ordered: "",
description: "",
status: ""
}; var brandName = document.getElementById("brandName").value;
formData.brandName = brandName; var companyName = document.getElementById("companyName").value;
formData.companyName = companyName; var ordered = document.getElementById("ordered").value;
formData.ordered = ordered; var description = document.getElementById("description").value;
formData.description = description; var status = document.getElementsByName("status");
for (let i = 0; i < status.length; i++) {
if (status[i].checked) {
//被选中
formData.status = status[i].value;
}
} axios({
method: "post",
url: "http://localhost/addServlet",
data: formData
}).then(function (resp) {
if (resp.data == "success") {
location.href = "http://localhost/brand.html"
}
});
}*/ new Vue({
el: "#app",
data() {
return {
brand: {}
}
},
methods: {
submitForm() {
//发送ajax请求
var _this = this;
axios({
method: "post",
url: "http://localhost/addServlet",
data: _this.brand
}).then(function (resp) {
if (resp.data == "success") {
location.href = "http://localhost/brand.html"
}
});
}
}
}); </script>
</body>
</html>

7.5 ElementUI

7.5.1 概述&快速入门

  • Element:是饿了么公司前端开发团队提供的一套基于Vue的网站组件库,用于快速构建网页

  • 组件:组成网页的部件,例如超链接、按钮、图片、表格等等~

  • Element快速入门

    • 引入Element的CSS、JS文件和Vue.js

      <script src="js/vue.js"></script>
      <script src="element-ui/lib/index.js"></script>
      <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
    • 创建Vue核心对象

      <script>
      new Vue({
      el:"#app"
      })
      </script>
    • 官网复制Element组件代码

      <div id="app">
      <el-row>
      <!--<el-button>默认按钮</el-button>
      <el-button type="primary">主要按钮</el-button>
      <el-button type="success">成功按钮</el-button>
      <el-button type="info">信息按钮</el-button>
      <el-button type="warning">警告按钮</el-button>-->
      <el-button type="danger">删除</el-button>
      </el-row>
      </div>

7.5.2 布局

Element中有两种布局方式:

  • Layout布局:通过基础的24分栏,迅速简便地创建布局

    <head>
    <meta charset="UTF-8">
    <title>Title</title> <style>
    .el-row {
    margin-bottom: 20px;
    } .el-col {
    border-radius: 4px;
    } .bg-purple-dark {
    background: #99a9bf;
    } .bg-purple {
    background: #d3dce6;
    } .bg-purple-light {
    background: #e5e9f2;
    } .grid-content {
    border-radius: 4px;
    min-height: 36px;
    } .row-bg {
    padding: 10px 0;
    background-color: #f9fafc;
    }
    </style> </head>
    <body> <div id="app">
    <el-row>
    <el-col :span="24">
    <div class="grid-content bg-purple-dark"></div>
    </el-col>
    </el-row>
    <el-row>
    <el-col :span="12">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="12">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    </el-row>
    <el-row>
    <el-col :span="8">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="8">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    <el-col :span="8">
    <div class="grid-content bg-purple"></div>
    </el-col>
    </el-row>
    <el-row>
    <el-col :span="6">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="6">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    <el-col :span="6">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="6">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    </el-row>
    <el-row>
    <el-col :span="4">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="4">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    <el-col :span="4">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="4">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    <el-col :span="4">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="4">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    </el-row>
    <el-row>
    <el-col :span="3">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="3">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    <el-col :span="3">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="3">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    <el-col :span="3">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="3">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    <el-col :span="3">
    <div class="grid-content bg-purple"></div>
    </el-col>
    <el-col :span="3">
    <div class="grid-content bg-purple-light"></div>
    </el-col>
    </el-row> </div> <script src="js/vue.js"></script>
    <script src="element-ui/lib/index.js"></script>
    <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script>
    new Vue({
    el: "#app"
    })
    </script> </body>
  • Container布局容器:用于布局的容器组件,方便快速搭建页面的基本结构

    <head>
    <meta charset="UTF-8">
    <title>Title</title> <style>
    .el-header {
    background-color: #B3C0D1;
    color: #333;
    line-height: 60px;
    } .el-aside {
    color: #333;
    }
    </style> </head>
    <body> <div id="app">
    <el-container style="height: 500px; border: 1px solid #eee">
    <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
    <el-menu :default-openeds="['1', '3']">
    <el-submenu index="1">
    <template slot="title"><i class="el-icon-message"></i>导航一</template>
    <el-menu-item-group>
    <template slot="title">分组一</template>
    <el-menu-item index="1-1">选项1</el-menu-item>
    <el-menu-item index="1-2">选项2</el-menu-item>
    </el-menu-item-group>
    <el-menu-item-group title="分组2">
    <el-menu-item index="1-3">选项3</el-menu-item>
    </el-menu-item-group>
    <el-submenu index="1-4">
    <template slot="title">选项4</template>
    <el-menu-item index="1-4-1">选项4-1</el-menu-item>
    </el-submenu>
    </el-submenu>
    <el-submenu index="2">
    <template slot="title"><i class="el-icon-menu"></i>导航二</template>
    <el-menu-item-group>
    <template slot="title">分组一</template>
    <el-menu-item index="2-1">选项1</el-menu-item>
    <el-menu-item index="2-2">选项2</el-menu-item>
    </el-menu-item-group>
    <el-menu-item-group title="分组2">
    <el-menu-item index="2-3">选项3</el-menu-item>
    </el-menu-item-group>
    <el-submenu index="2-4">
    <template slot="title">选项4</template>
    <el-menu-item index="2-4-1">选项4-1</el-menu-item>
    </el-submenu>
    </el-submenu>
    <el-submenu index="3">
    <template slot="title"><i class="el-icon-setting"></i>导航三</template>
    <el-menu-item-group>
    <template slot="title">分组一</template>
    <el-menu-item index="3-1">选项1</el-menu-item>
    <el-menu-item index="3-2">选项2</el-menu-item>
    </el-menu-item-group>
    <el-menu-item-group title="分组2">
    <el-menu-item index="3-3">选项3</el-menu-item>
    </el-menu-item-group>
    <el-submenu index="3-4">
    <template slot="title">选项4</template>
    <el-menu-item index="3-4-1">选项4-1</el-menu-item>
    </el-submenu>
    </el-submenu>
    </el-menu>
    </el-aside> <el-container>
    <el-header style="text-align: right; font-size: 12px">
    <el-dropdown>
    <i class="el-icon-setting" style="margin-right: 15px"></i>
    <el-dropdown-menu slot="dropdown">
    <el-dropdown-item>查看</el-dropdown-item>
    <el-dropdown-item>新增</el-dropdown-item>
    <el-dropdown-item>删除</el-dropdown-item>
    </el-dropdown-menu>
    </el-dropdown>
    <span>王小虎</span>
    </el-header> <el-main>
    <el-table :data="tableData">
    <el-table-column prop="date" label="日期" width="140">
    </el-table-column>
    <el-table-column prop="name" label="姓名" width="120">
    </el-table-column>
    <el-table-column prop="address" label="地址">
    </el-table-column>
    </el-table>
    </el-main>
    </el-container>
    </el-container>
    </div> <script src="js/vue.js"></script>
    <script src="element-ui/lib/index.js"></script>
    <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css"> <script>
    new Vue({
    el: "#app",
    data() {
    const item = {
    date: '2016-05-02',
    name: '王小虎',
    address: '上海市普陀区金沙江路 1518 弄'
    };
    return {
    tableData: Array(20).fill(item)
    }
    }
    })
    </script> </body>

JavaWeb4的更多相关文章

  1. javaWeb4 http

    状态码:服务器处理请求的结果(状态) 常见的状态: 200: 表示请求处理完成并完美返回.ok 302:表示请求需要进一步细化. 404:表示客户访问的资源找不到.Not Found 500:表示服务 ...

随机推荐

  1. JCEF 初体验,window系统构建jar包

    前言 本文记录如何通过jcef源代码去构建自己所需要的jar包,此文章构建的为windows64位jcef 的 jar 包,若需要构建 32 位的 jar 包,则需要按照文章将相关准备软件设置为 32 ...

  2. KingbaseES 如何把一个schema下的所有对象访问权限授权给其他用户

    用户需求:新建一个用户 B,需要能够查询A用户的所有表,并且对以后新建的表也要有select权限. 问题分析:对于现有的表可以通过动态sql批量进行授权,但是未来新建的表要如何进行授权呢? 查询了帮助 ...

  3. OID 与隐含列

    熟悉PostgreSQL的都知道,PG12 开始,不再支持OID伪列.KingbaseES 为了保证与旧版本兼容,特增加了OID 隐含列的支持. R3版本:OID 是整个数据库共用的"序列& ...

  4. Python图像处理丨认识图像锐化和边缘提取的4个算子

    摘要:图像锐化和边缘提取技术可以消除图像中的噪声,提取图像信息中用来表征图像的一些变量,为图像识别提供基础. 本文分享自华为云社区<[Python图像处理] 十七.图像锐化与边缘检测之Rober ...

  5. 【设计模式】Java设计模式 - 组合模式

    Java设计模式 - 组合模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  6. CentOS7使用yum方式安装Containerd

    # 安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 yum install -y yum-utils device-m ...

  7. 内网横向渗透 之 ATT&CK系列一 之 横向渗透域主机

    前言 上一篇文章中已获取了关于域的一些基本信息,在这里再整理一下,不知道信息收集的小伙伴可以看回上一篇文章哦 域:god.org 域控 windows server 2008:OWA,192.168. ...

  8. 痞子衡嵌入式:浅谈i.MXRT10xx系列MCU外接24MHz晶振的作用

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT10xx系列MCU外接24MHz晶振的作用. 痞子衡之前写过一篇关于时钟引脚的文章 <i.MXRT1xxx系列MCU时 ...

  9. python+request+pymysql+pytest数据驱动

    一.pymysql简单使用 1.安装mysql 下载地址:https://www.mysql.com/,安装教程这里不做介绍了,网上一大推. 2.安装pymysql库 在Terminal终端输入:pi ...

  10. P3250 [HNOI2016] 网络 (树剖+堆/整体二分+树上差分+树状数组)

    解法1: 本题有插入路径和删除路径,在每个节点维护插入堆和删除堆,查询时两者top一样则一直弹出.如果每个节点维护的是经过他的路径,显然有些不好处理,正难则反,每个点维护不经过他的路径,那么x节点出了 ...