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. [HDU1812] Count the Tetris - polya定理

    题面 Problem Description 话说就是因为这个游戏,Lele已经变成一个名人,每当他一出现在公共场合,就有无数人找他签名,挑战. 为了防止引起社会的骚动,Lele决定还是乖乖呆在家里. ...

  2. .NET 开源工作流: Slickflow流程引擎高级开发(十) -- BpmnJS流程设计器集成

    前言: 在Slickflow产品开发过程中,前端流程设计器经历了几个不同的版本(jsPlumb, mxGraph等),目的是为了在设计流程时的用户体验更加良好,得到客户的好评和认可.BpmnJS流程设 ...

  3. STC15 串口通信

    串口1选择定时器2产生波特率 串口1相关寄存器 1.选择串口1所放的管脚 2.串口1配置步骤 3.选择串口工作模式 4.确定定时器2工作速度 代码配置 void Uart1_Tim2_Config(i ...

  4. 源码(chan,map,GMP,mutex,context)

    目录 1.chan原理 1.1 chan底层数据结构 1.2 创建channel原理 1.3 写入channel原理 1.4 读channel原理 1.5 关闭channel原理 1.6 总结 2.m ...

  5. Centos7 安装部署Kubernetes(k8s)集群

    目录 一.系统环境 二.前言 三.Kubernetes 3.1 概述 3.2 Kubernetes 组件 3.2.1 控制平面组件 3.2.2 Node组件 四.安装部署Kubernetes集群 4. ...

  6. 践行初心|方正璞华爱心捐赠人脸识别测温系统WelComID

    近日,方正璞华向金鸡湖社区卫生服务中心捐赠了人脸识别测温系统.该设备集人员识别.体温检测等功能于一体,在人员进出的时候完成体温的检测,从而判断是否有异常人员等问题,有效节省人力成本.减少人员接触风险, ...

  7. 后端程序员实现一个IP归属地的小程序

    在日常开发中,后端主要提供数据以及处理业务逻辑,前端主要提供页面布局以及数据展示.后端程序员对于页面布局接触比较少,但是小程序有完善的文档说明.页面布局也相对简单,实现起来相对简单一些.而且小程序相对 ...

  8. 如何在Windows中查询证书颁发机构已颁发的证书

    有时候需要看一下证书颁发机构已经颁发出去的证书,看看某个用户或者某个计算机获取过的证书有哪些.通常可以在证书颁发机构的MMC中查看.对于测试环境或者刚开始用的CA来说,这样查看挺简单的.但是对于用了一 ...

  9. .NET静态代码织入——肉夹馍(Rougamo) 发布1.2.0

    肉夹馍(https://github.com/inversionhourglass/Rougamo)通过静态代码织入方式实现AOP的组件,其主要特点是在编译时完成AOP代码织入,相比动态代理可以减少应 ...

  10. 8.X 的安装配置简化体现

    文章转载自:https://mp.weixin.qq.com/s/CEYYKUub81mk59B3lqAcBA 节点无需任何安全配置,即可实现 TLS 加密通信.Https 加密通信. TLS 应用于 ...