day23-服务器端渲染技术01
服务器端渲染技术01
- 为什么需要jsp?
 
在之前的开发过程中,我们可以发现servlet做界面非常不方便:

引出jsp技术=> jsp=html+java代码+标签+javascript+css
1.JSP基本介绍
- JSP全称是Java Server Pages,Java的服务器页面,就是服务器端渲染技术
 - JSP这门技术最大的特点在于,写JSP就像在写HTML
- 相比HTML而言,HTML只能为用户提供静态数据,而JSP技术允许在页面中嵌套java代码,为用户提供动态数据
 - 相比Servlet而言,Servlet很难对数据进行排版,而jJSP除了可以用java代码产生动态数据的同时,也很容易对数据进行排版
 
 - JSP技术基于Servlet,可以理解成JSP就是对Servlet的包装,JSP的本质就是Servlet。
 - 会使用JSP的程序员,再使用thymeleaf是非常容易的事情,几乎是无缝接轨。
 
2.JSP的快速入门
2.1应用实例-jsp的基本使用
创建web项目,并引入jsp和servlet的jar包(servlet和jsp的jar包在tomcat安装目录下的lib目录下)

创建的jsp文件应放在web目录下面

配置Tomcat
编写jsp
<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/11/24
Time: 16:59
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>jsp简单的求和计算器</title>
</head>
<body>
<h1>jsp简单的求和计算器</h1>
<%
//1. 在jsp中的该标签内可以写java代码
int i = 10;
int j = 20;
int res = i + j;
//jsp的本质就是servlet,因此servlet可以使用的东西jsp都可以使用
//2.jsp中内置了许多对象,可以直接使用,比如out
out.print(i + "+" + j + "=" + res);
%>
</body>
</html>
运行Tomcat,在浏览器中访问该jsp资源

2.1注意事项和细节
jsp页面不能像html页面一样,直接用浏览器运行。只能通过浏览器访问Tomcat来访问jsp页面
如何设置jsp模板,设置完模板后,当你再去生成一个jsp文件后就会根据模板的内容自动生成文件头


3.JSP的运行原理
jsp页面本质是一个Servlet程序(jsp本质就是java程序),其性能是和java相关的,只是长得丑
第一次访问jsp页面的时候,Tomcat服务器会将jsp页面解析成一个java源文件,并且将它编译成一个.clsaa字节码程序。


分析下sum_jsp.java源码,可以看出jsp本质就是Servlet
3.1可以看到sum_jsp类继承了一个名叫HttpJspBase的类:

想要看到源码和分析类图,需要加入jasper.jar包。这个包在tomcat/lib下拷贝
3.2我们引入jasper.jar包,查看该类的类图:

4.常用的jsp指令

- language表示jsp翻译后是什么语言文件,只支持java
 - contentType表示jsp返回的数据类型,对应源码中response.setContentType()参数值
 - pageEncoding属性表示当前jsp页面文件本身的字符集
 - import属性和java源代码中一样,用于导包,导类。
 
5.JSP三种常用脚本
5.1声明脚本基本语法
声明脚本的格式是:
<%! 声明java代码 %>
作用:定义jsp需要的属性,方法,静态代码块和内部类等
应用实例
statement.jsp:
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/24
  Time: 18:28
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jsp声明脚本</title>
</head>
<body>
<h1>jsp声明脚本</h1>
<%!
    //这里我们可以声明该jsp需要的属性,方法,静态代码块和内部类等,
    // 也就是给statement.jsp对应的statement_jsp类定义成员
    //1.属性
    private String name = "jack";
    private int age;
    private static String company;
    //2.方法
    public String getName() {
        return name;
    }
    //3.静态代码块
    static {
        company = "中国移动";
    }
%>
</body>
</html>
在浏览器中访问该jsp页面,在Tomcat启动时的Using CATALINA_BASE:文件目录下可以看到对应jsp文件生成的java文件:

打开该java文件,可以看到在jsp页面中定义的属性和方法等:

5.2表达式脚本基本语法
表达式脚本的格式是:
<%=表达式%>
表达式的概念和java基础的表达式一样,只要有一个具体的值返回,都可以称之为一个表达式
表达式脚本的作用是:在jsp页面上输出数据
脚本中的表达式不能以分号结束
应用实例
expression.jsp:
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/24
  Time: 18:47
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>表达式脚本的使用</title>
</head>
<body>
<h1>表达式脚本的使用</h1>
<%
    String name = "一只大猫咪";
    //可以在jsp页面中动态获取一些值,并将其展示出来
    String email = request.getParameter("email");
    //表达式可以是变量,常量,还可以是动态获取的变量
%>
用户名:<%=name%><br/>
工作是:<%="java工程师"%><br/>
年龄:<%=request.getParameter("age")%><br/>
邮箱:<%=email%>
</body>
</html>
访问浏览器:http://localhost:8080/jsp/expression.jsp?age=100&email=mimi@qq.com

5.3代码脚本基本语法
代码脚本的语法是:
<% java代码 %>
代码脚本的作用是:可以在jsp页面中,编写我们需要的功能(使用java)
可以由多个代码脚本块组合完成一个完整的java语句
代码脚本还可以和表达式脚本一起组合使用,在jsp页面上输出数据
应用实例
在src文件夹下创建一个Monster类:
package com.li.entity;
public class Monster {
    private Integer id;
    private String name;
    private String skill;
    public Monster(Integer id, String name, String skill) {
        this.id = id;
        this.name = name;
        this.skill = skill;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSkill() {
        return skill;
    }
    public void setSkill(String skill) {
        this.skill = skill;
    }
}
javaCode.jsp:
<%@ page import="java.util.ArrayList" %>
<%@ page import="com.li.entity.Monster" %>
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/24
  Time: 19:16
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>演示代码脚本的使用</title>
</head>
<body>
<h1>演示代码脚本的使用</h1>
<%
    //先创建ArrayList,放入两个monster对象(使用的类会自动导入)
    ArrayList<Monster> monsterList = new ArrayList<>();
    monsterList.add(new Monster(1, "牛魔王", "芭蕉扇"));
    monsterList.add(new Monster(2, "蜘蛛精", "吐丝"));
%>
</body>
<%--tr 是行标签,th是表头标签,td是单元格标签--%>
<table bgcolor="#f0f8ff" border="1px" width="300px">
    <tr>
        <th>id</th>
        <th>名字</th>
        <th>技能</th>
    </tr>
    <%
        for (int i = 0; i < monsterList.size(); i++) {
            //先取出monster对象
            Monster monster = monsterList.get(i);
    %>
            <tr>
                <th><%=monster.getId()%></th>
                <th><%=monster.getName()%></th>
                <th><%=monster.getSkill()%></th>
            </tr>
         <%
        }
    %>
</table>
</html>
在浏览器访问:
http://localhost:8080/jsp/javaCode.jsp
在Tomcat启动时的Using CATALINA_BASE:文件目录下可以看到对应jsp文件生成的java文件。
可以看到jsp文件中的for循环被解析成如下形式:

6.JSP注释
jsp可以写java代码和html,可以使用java代码的注释,以及html的注释<!--html注释-->。此外还可以使用jsp自己的注释方式<%--jsp注释--%>
 
7.JSP的内置对象
基本介绍
- JSP内置对象(已经创建好的对象,可以直接使用-inbuild),是指Tomcat在翻译jsp页面成为Servlet后,内部提供的九大对象,称为内置对象
 - 内置对象可以在jsp页面直接使用,不需要手动定义
 
JSP九大内置对象
- out:向客户端输出数据,out.println("");
 - request:客户端的http请求
 - response:响应对象
 - session:会话对象
 - application:对应 ServletContext
 - pageContext:jsp页面的上下文,是一个域对象,可以setAttribute(),作用范围是本页面
 - exception:异常对象,getMessage()
 - page:代表jsp这个实例本身
 - config:对应ServletConfig
 
对照Servlet来理解就轻松了
只要学某个类,建议熟悉该类的继承关系

应用实例
inbuild.jsp:
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/24
  Time: 20:05
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jsp内置对象</title>
</head>
<body>
<h1>jsp内置对象</h1>
<%
    //jsp的内置对象
    //1.out 的类型是 JspWriter
    out.print("jsp out");
    //2.request 的类型是 HttpServletRequest
    request.getParameter("age");
    //3.response 的类型是 HttpServletResponse
    //response.sendRedirect("http://www.baidu.com");
    //4.session 的类型是 HttpSession
    session.setAttribute("中国", "北京");
    //5.application 的类型 ServletContext
    application.setAttribute("name", "jack");
    //6.pageContext 的类型是PageContext
    //该对象可以存放数据(属性),但是该数据只能在本页使用
    pageContext.setAttribute("age", 99);
    //7.exception:异常对象使用比较少,忽略
    //8.page 内置对象,类似this
    out.print("page对象= " + page);//org.apache.jsp.inbuild_jsp@2ac0d5df
    //9.config 的内置对象就是ServletConfig
    String password = config.getInitParameter("password");
%>
</body>
age:<%=pageContext.getAttribute("age")%>
</html>
对照一下servlet的对象使用,其实是大同小异的:

8.JSP域对象
所谓"作用域"就是"信息共享的范围",也就是说一个信息能够在多大的范围内有效。所谓的域对象就是在某个范围存数据和取数据的对象。
8.1JSP四大域对象介绍
JSP中四大作用域详解- 博客园 (cnblogs.com)
Web交互的最基本单位为HTTP请求。每个用户从进入网站到离开网站这段过程称为一个HTTP会话,一个服务器的运行过程中会有多个用户访问,就是多个HTTP会话。
| 名称 | 作用域 | 
|---|---|
| application(应用程序作用域) | 整个web应用运行期间有效 | 
| session(会话作用域) | 存放的数据在一次会话内有效 | 
| request(请求作用域) | 存放的数据在一次request请求有效 | 
| page(页面作用域) | 存放的数据只能在当前页面有效 | 




8.2应用实例
scope.jsp:
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/25
  Time: 15:36
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>scope文件</title>
</head>
<body>
<%
    //在不同的域对象中,放入数据
    //因为四个域对象是不同的对象,因此name相同(key相同)并不会冲突
    pageContext.setAttribute("k1", "pageContext数据v1");
    request.setAttribute("k1", "request数据v1");
    session.setAttribute("k1", "session数据v1");
    application.setAttribute("k1", "application数据v1");
    //做一个请求转发的操作
    //因为是在服务器解析的,可以不用写 web工程路径
    //request.getRequestDispatcher("/scope2.jsp").forward(request, response);
    //重定向
    //因为是在浏览器解析的,需要写 web工程路径
    response.sendRedirect("/jsp/scope2.jsp");
%>
<h1>四个域对象在本页面获取数据的情况</h1>
pageContext-k1:<%=pageContext.getAttribute("k1")%><br/>
request-k1:<%=request.getAttribute("k1")%><br/>
session-k1:<%=session.getAttribute("k1")%><br/>
application-k1:<%=application.getAttribute("k1")%>
</body>
</html>
scope2.jsp:
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/25
  Time: 15:44
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>scope2</title>
</head>
<body>
<h1>在scope2页面获取数据的情况</h1>
pageContext-k1:<%=pageContext.getAttribute("k1")%><br/>
request-k1:<%=request.getAttribute("k1")%><br/>
session-k1:<%=session.getAttribute("k1")%><br/>
application-k1:<%=application.getAttribute("k1")%>
</body>
</html>
首先访问scope.jsp页面,可以看到在本页设置的四个域对象都可以获取到数据

访问scope.jsp,它请求转发到scope2.jsp页面, pageContext对象不能取到数据,其余对象可以取出数据

访问scope.jsp,它重定向到scope2.jsp,pageContext和request对象不能取到数据,其余对象可以取出数据

换一个浏览器直接访问scope2.jsp。只有application对象可以访问到数据,其余对象不能取到数据。

- jsp四大域对象注意事项和细节
- 域对象是可以像Map一样存储数据的对象。四个域对象功能一样,不同的是它们对数据的存储范围。
 - 从存储范围(作用域范围来看):pageContext < request < session < application
 
 
9.JSP请求转发标签
<jsp:forward page="xxx"></jsp:forward>是请求转发标签,它的功能就是请求转发到page属性设置的路径
应用实例
aa.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>aa.jsp</title>
</head>
<body>
<h1>aa.jsp</h1>
<%--
   请求转发标签的本质等价于
   request.getRequestDispacher("/bb.jsp").forward(request,response);
--%>
<jsp:forward page="/bb.jsp"></jsp:forward>
</body>
</html>
bb.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>bb.jsp</title>
</head>
<body>
<h1>bb.jsp</h1>
</body>
</html>
浏览器访问aa.jsp,可以看到请求转发到了bb.jsp页面(请求转发的地址栏不变)

10.练习
需求分析:使用jsp页面完成一个简单的计算器,需求如下:

要求在前端页面对输入的num1和num2进行校验,必须是整数(提示:使用正则表达式)
验证成功,提交数据给服务器,能够显示结果
点击超链接,可以返回界面
思考题:如果用户这样提交:
http://localhost:8080/jsp/calServlet?num1=null&num2=bb,需要你返回calculator.jsp页面,并给出提示信息如下:
练习
思路:

calculator.jsp:
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/25
  Time: 16:30
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jsp计算器</title>
    <script type="text/javascript">
        //使用js+正则表达式完成校验
        function check() {
            //得到num1,num2的值
            var num1 = document.getElementById("num1").value;
            var num2 = document.getElementById("num2").value;
            //验证-必须是整数
            var regStr = /^[-]?([1-9]\d*|0)$/;
            if (!regStr.test(num1)) {//如果不是整数
                window.alert("num1不是一个整数");
                return false;//代表不提交表单
            }
            if (!regStr.test(num2)) {//如果不是整数
                window.alert("num2不是一个整数");
                return false;//代表不提交表单
            }
            return true;
        }
    </script>
</head>
<body>
<h1>jsp计算器</h1>
<form action="/jsp/calServlet" method="post" onsubmit="return check()">
    num1:<input type="text" id="num1" name="num1"/>
    <%=request.getAttribute("num1") != null ? request.getAttribute("num1") : ""%>
    <br/><br/>
    num2:<input type="text" id="num2" name="num2"/>
    <%=request.getAttribute("num2") != null ? request.getAttribute("num2") : ""%>
    <br/><br/>
    运算符号:<select name="operator">
    <option value="+">+</option>
    <option value="-">-</option>
    <option value="*">*</option>
    <option value="/">/</option>
</select>
          
    <input type="submit" value="计算">
</form>
</body>
</html>
calServlet:
package com.li.servlet;
import com.utils.WebUtils;
import javafx.scene.Parent;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@WebServlet(name = "CalServlet", value = "/calServlet")
public class CalServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("calServlet was run ..");
        //1.正则验证-防止用户直接在地址栏请求CalServlet
        String regStr = "^[-]?([1-9]\\d*|0)$";
        boolean matches = Pattern.matches(regStr, request.getParameter("num1"));
        boolean matches2 = Pattern.matches(regStr, request.getParameter("num2"));
        //如果用户直接通过地址栏输入非法数据,可以先正则验证出哪个数据非法
        //再将提示转发回计算器页面这里使用request域对象
        if ((!matches) || (!matches2)) {
            request.setAttribute("num1", "你输入num1=" + request.getParameter("num1"));
            request.setAttribute("num2", "你输入num2=" + request.getParameter("num2"));
            //请求转发到显示页面
            request.getRequestDispatcher("/calculator.jsp").forward(request, response);
            return;
        }
        //2.将用户输入的数据转成double类型
        double num1 = WebUtils.parseDouble(request.getParameter("num1"), 0);
        double num2 = WebUtils.parseDouble(request.getParameter("num2"), 0);
        String operator = request.getParameter("operator");
        //3.完成计算
        double result = 0.0;//使用一个变量来接收运算结果
        if ("+".equals(operator)) {
            result = num1 + num2;
        } else if ("-".equals(operator)) {
            result = num1 - num2;
        } else if ("*".equals(operator)) {
            result = num1 * num2;
        } else if ("/".equals(operator)) {
            if (0 == num2) {
                System.out.println("被除数不能为0");
            } else {
                result = num1 / num2;
            }
        } else {
            System.out.println(operator + "不正确..");
        }
        //4.一次请求对应一次计算,因此将结果保存到request中
        // 将结果保存到一个字符串中,方便下一个页面显示。使用String.format,可以格式化字符串
        String resInfo = String.format("%s %s %s = %s", num1, operator, num2, result);
        request.setAttribute("resInfo", resInfo);
        //5.请求转发到显示页面
        request.getRequestDispatcher("/calResult.jsp").forward(request, response);
    }
}
WebUtils:
package com.utils;
public class WebUtils {
    public static double parseDouble(String strNum, int defaultVal) {
        try {
            return Double.parseDouble(strNum);
        } catch (NumberFormatException e) {
            System.out.println(strNum + "不能转成整数");
        }
        return defaultVal;
    }
}
calResult.jsp:
<%--
  Created by IntelliJ IDEA.
  User: li
  Date: 2022/11/25
  Time: 17:22
  Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>计算结果</title>
</head>
<body>
<h1>计算结果</h1>
<h1>
    <%=request.getAttribute("resInfo")%>
    <br/>
</h1>
<h3><a href="/jsp/calculator.jsp">返回再来玩一次</a></h3>
</body>
</html>
在表单中输入合法数据:

表单输入非法数据:
 
在地址栏中输入非法数据:

day23-服务器端渲染技术01的更多相关文章
- day24-服务器端渲染技术02
		
服务器端渲染技术02 11.EL表达式 11.1EL表达式介绍 EL表达式全称:Expression Language,是表达式语言 EL表达式主要是代替jsp页面的表达式脚本 EL表达式输出数据时, ...
 - 【大前端之前后分离01】JS前端渲染VS服务器端渲染
		
前言 之前看了一篇文章:@Charlie.Zheng Web系统开发构架再思考-前后端的完全分离,文中论述了为何要前后分离,站在前端的角度来看,是很有必要的:但是如何说服团队使用前端渲染方案却是一个现 ...
 - 基于React服务器端渲染的博客系统
		
系统目录及源码由此进入 目录 1. 开发前准备 1.1 技术选型1.2 整体设计1.3 构建开发 2. 技术点 2.1 react2.2 redux, react-router2.3 server-r ...
 - 服务器端渲染VS浏览器端渲染
		
1)浏览器渲染和服务器渲染区别:何为渲染?如果我们只是想显示一堆不变的数据,那么我们直接写一个a.html丢到服务器上让客户端访问就可以了.但这是基本不可能的事情,数据一般是变化的.你不可能为每套数据 ...
 - 细说后端模板渲染、客户端渲染、node 中间层、服务器端渲染(ssr)
		
细说后端模板渲染.客户端渲染.node 中间层.服务器端渲染(ssr) 前端与后端渲染方式的发展大致经历了这样几个阶段:后端模板渲染.客户端渲染.node 中间层.服务器端渲染(ssr). 1. 后端 ...
 - react实现ssr服务器端渲染总结和案例(实例)
		
1.什么是 SSR SSR 是 server side render 的缩写,从字面上就可以理解 在服务器端渲染,那渲染什么呢,很显然渲染现在框架中的前后端分离所创建的虚拟 DOM 2.为什么要实现服 ...
 - 剖析Unreal Engine超真实人类的渲染技术Part 3 - 毛发渲染及其它
		
目录 四.毛发渲染 4.1 毛发的构造及渲染技术 4.1.1 毛发的构造 4.1.2 Marschner毛发渲染模型 4.1.3 毛发的间接光照 4.2 毛发的底层实现 4.3 毛发的材质解析 4.3 ...
 - React服务器端渲染框架next.js项目实战及部署上下文context问题解决办法
		
在前段时间折腾过搭建react服务器端项目架构,点击这里了解下,正好最近有个重构PC网站的需求,考虑SEO等因素.在做技术选型的时候决定采用nextjs.项目开发过程中,nextjs的体验非常棒,个人 ...
 - React 服务器端渲染流程
		
其实我们在访问客户端渲染的页面时,请求到的只是一个 html 空壳,里面引入了一个 js 文件,所有的内容都是通过 js 进行插入的,正是因为页面是由 js 渲染出来的,所以会带来如下几个问题: 1. ...
 - 服务端渲染技术NUXT
		
什么是服务端渲染  服务端渲染又称SSR (Server Side Render),是在服务端完成页面的内容,而不是在客户端通过AJAX获取数据. 服务器端渲染(SSR)的优势主要在于:更好的 SE ...
 
随机推荐
- 取代传统BIOS的EFI和UEFI究竟是什么?
			
传统的蓝白BIOS界面可以说是陪伴着很多玩家共同成长,不过在英特尔发布Sandy Bridge架构处理器的时候,传统BIOS也到了和我们说再见的时间,采用图形化界面的EFI以及UEFI很快就取代了传统 ...
 - P6824 「EZEC-4」可乐 题解
			
题目链接:可乐 一开始想着 0-1 Trie,枚举 \(x\) 去写,然后判断就行了.然后想起南京区域赛的 C 题,其实和这个也有点大同小异的感觉,可以用更朴素的办法,找到对于一个 \(a_i\) 而 ...
 - 【题解】P9749 [CSP-J 2023] 公路
			
\(Meaning\) \(Solution\) 这道题我来讲一个不一样的解法:\(dp\) 在写 \(dp\) 之前,我们需要明确以下几个东西:状态的表示,状态转移方程,边界条件和答案的表示. 状态 ...
 - Build 和 Compile 区别
 - Python 装饰器解析(一)
			
装饰器用于在源码中"标记"函数,以增强函数的行为. 我们先来看下面的例子,现有一个求和函数add,现在要求统计函数执行的时长 def add(a, b): print(a+b) 最 ...
 - MySQL专题2: 事务和锁
			
合集目录 MySQL专题2: 事务和锁 说说数据库事务特性及存在的问题 这属于数据库事务的基础概念了, 就是ACID Atomicity, 原子性, 事务包含的所有操作要么全部成功, 要么全部失败回滚 ...
 - 一键部署Home Assistant ubuntu 20.4.3 树莓派3b+脚本
			
树莓派3b+安装好 Ubuntu Server 20.04.3 LTS 32bit 后即可适用此脚本,其他版本树莓派/系统可能需要微调脚本*为方便一些未知/已知错误排查 脚本存在冗余部分,足够了解 ...
 - 在SpringBoot中实践AOP编程
			
具体实践 Spring AOP是Spring框架中一个支持实现面向切面编程的模块,由于Spring Boot已经把Spring框架组合得非常好用,所以在基于Spring Boot框架的项目中实现AOP ...
 - 2021-07-30 JavaScript中常用数据的判断
			
为什么要判断一个变量的常用数据? 实际业务场景里,一个变量的数据是否合法或符合预期,会影响到项目中用到的UI组件库特定组件的运行.比如element-ui中的el-select组件,单选时绑定的数据不 ...
 - python各版本新特性
			
# py3.7 https://docs.python.org/zh-cn/3/whatsnew/3.7.html # py3.8 https://docs.python.org/zh-cn/3/wh ...