1、CGLIB代理

有一个类没有实现接口,想要对这个类实现增强,就需要使用CGLIB代理
  • 导入CGLIB的包
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
  • 编写被代理的类
package com.wz.practice.proxy.cglib;

public class UserService {
    public void add(){
        System.out.println("--------add执行--------");
    }

    public void update(){
        System.out.println("--------update执行--------");
    }
}
  • 实现代理
package com.wz.practice.proxy.cglib;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 实现了MethodInterceptor接口:该接口是CGLIB提供的用于连接方法调用的机制
 * 通过实现intercept方法,可以在方法调用前后进行额外的操作.
 */

public class UserServiceFactory implements MethodInterceptor {

    private UserService userService;
    public UserServiceFactory(UserService userService){
        this.userService=userService;
    }
    public UserService getUserServiceProxy(){
        //创建Enhancer对象,
        Enhancer enhancer = new Enhancer();
        //给生成的类指定一个爹
        enhancer.setSuperclass(UserService.class);
        //将UserServiceFactory设置为方法拦截器callback
        enhancer.setCallback(this);
        //创建代理对象,将其转换为UserService并返回
        return (UserService) enhancer.create();
    }

    /**
     *在这里进行拦截
     * @param o
     * @param method
     * @param objects
     * @param methodProxy
     * @return
     * @throws Throwable
     */
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("打开事务");
        //method.invoke() 方法是 Java 反射 API 提供的方法,
        // 用于在指定对象上调用指定的方法。
        // 它接受两个参数:第一个参数是要调用方法的对象实例,第二个参数是要传递给方法的参数。
        Object invoke = method.invoke(this.userService, objects);
        System.out.println("提交事务");
        return invoke;
    }
}
  • 测试
package com.wz.practice.proxy.cglib;

public class Test001 {
    public static void main(String[] args) {
        UserService userServiceFactory = new UserServiceFactory(new UserService()).getUserServiceProxy();
        userServiceFactory.add();
    }
}

结果:

CGLIB代理,jsp,EL表达式,JSTL标准标签库_EL表达式

2、jsp是什么

jsp的爹是 HttpJspbase      HttpJspBase  继承了 HttpServlet

也就是说 jsp本质就是一个Servlet

jsp的对外表象就是一个页面,但是这个页面上可以完成Servlet的所有功能

jsp是不能直接运行的,在运行之前需要先经过翻译这样一个过程,翻译成Java代码之后,在编译成.class文件 最终这个class文件才会运行

3、域对象

拥有作用域的对象称为域对象,简单来说就是有作用范围的Java对象
jsp中有四个域对象

request:作用范围是当前请求,当前请求结束,这个域对象就不存在了,每一个请求都会创建你这样一个域对象。

session:生命周期是当前会话 (简单理解就是一次浏览器的打开和关闭)实际上会话的生命周期是30分钟,即使页面关闭了,这个对象也会在jvm中存活一定时间才会死亡

application(ServletContext):Tomcat只要打开这个对象就存在,tomcat关闭这个对象就不存,生命周期最长

pageContext:生命周期是当前页面,页面关闭,这个对象就不存在了

按照生命周期先后顺序排序:

pageContext < request < session < application(ServletContext)

在开发中使用的最多的是 request   session也有使用  application和pageContext基本不会使用

与域对象究竟有啥作用呢?

可以将Servlet的执行结果直接 带到jsp页面并进行显示

4、EL表达式

EL表达式能直接从四个域对象中取出数据
4.1、El表达式的基本使用
4.1.1、在Servlet中向域对象放数据
package com.wz.practice.servlet;

import com.wz.practice.pojo.User;

import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;

@WebServlet(urlPatterns = "/users")
public class UserServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //这里可以向域对象里放数据
        req.setAttribute("username","ZhangSan");
        req.setAttribute("user",new User(01,"ZhangSan","123456"));
        ArrayList<User> userList = new ArrayList<User>();
        for (int i = 0; i < 3; i++) {
            userList.add(new User(i+1,"Username"+i,"123456"));
        }
        req.setAttribute("list",userList);

        //在session对象中放数据
        HttpSession session = req.getSession();
        session.setAttribute("sessionKey","sessionVal");
        //在application中放对象
        ServletContext application = req.getServletContext();
        application.setAttribute("applicationKey","applicationVal");

        req.getRequestDispatcher("/index.jsp").forward(req,resp);

    }
}
4.1.2、在页面上使用EL表达式取数据
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%
        pageContext.setAttribute("pageKey","pageVal");
        %>

        <%--从req中取数据--%>
        用户名是:${username}<br>
        对象的名字:${user.username}<br>
        集合中第一个对象的名字:${list[0].username}<br>

        <%--从session中取数据--%>
        从session中取数据:${sessionKey}<br>
        从application中取数据:${applicationKey}<br>
        从pageContext中取数据:${pageKey}
    </body>
</html>

结果:

4.2、EL取出数据的顺序
pageContext <  req  <  session   <   application

上面的顺序就是我们的EL表达式取出数据的顺序  

如果是pageContext没取到 那么就会去 req中取数据  req中没取到 那么就要去session中取数据  session中没取

到 那么就要去application中取出数据

EL表达式 只能 取出数据 不能表达逻辑关系 以及遍历集合

5、JSTL标准标签库的基本使用

JavaServer Pages Standard Tag Library

EL存在的问题:

  • EL主要用于作用域获取数据,虽然可以做判断,但是得到的都是一个结果做展示
  • EL不存在流程控制语句,比如判断
  • EL对于集合只能做单点访问,不能实现遍历操作,比如循环

JSTL是一个jsp的标签集合

JSTL的作用:

可以对EL获取到的数据进行逻辑操作

可以与EL合作完成数据的展示

  • 导包
<!--jstl的标签库-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
  • 数据准备
package com.wz.practice.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
    private Integer id;
    private String username;
    private Double salary;
}


package com.wz.practice.servlet;

import com.wz.practice.pojo.Dept;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

@WebServlet(urlPatterns = "/depts")
public class DeptServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("age",18);

        req.setAttribute("score",10);

        ArrayList<Dept> depts = new ArrayList<Dept>();
        for (int i = 0; i < 10; i++) {
            depts.add(new Dept(i+1,"clerk"+i+1,8000.));
        }
        req.setAttribute("deptList",depts);

        req.getRequestDispatcher("/dept_list.jsp").forward(req,resp);
    }
}
  • 取数据
<%--
    Created by IntelliJ IDEA.
    User: WangZhi
        Date: 2023/8/19
            Time: 11:37
                To change this template use File | Settings | File Templates.
                --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%--prefix标签库的前缀--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%--jstl中的逻辑运行算符--%>
        <c:if test="${age>=18}">
            电影可看
        </c:if>
        <%--if-----else if---else--%>
        <c:choose>
            <c:when test="${score<=60}">不及格</c:when>
            <c:when test="${score<75}">良好</c:when>
            <c:otherwise>优秀</c:otherwise>
        </c:choose>


        <table cellpadding="0" cellspacing="0" border="1" style="width: 600px;text-align: center">

            <tr>
                <th>id</th>
                <th>名称</th>
                <th>工资</th>
                <th>遍历下标</th>
            </tr>
    <%--
    items:遍历的集合是啥
    var:每一次遍历出来的对象是啥
    varStatus:每一次遍历的状态
    begin="起始下标"  不写
    end="结束下标" 不写
    step="间隔长度" 不写
    --%>
            <c:forEach items="${deptList}" var="dept" varStatus="status">
                <tr>
                    <td>${dept.id}</td>
                    <td>${dept.username}</td>
                    <td>${dept.salary}</td>
                    <td>${status.index}</td>
                </tr>
            </c:forEach>
        </table>
    </body>
</html>

结果:

CGLIB代理,jsp,EL表达式,JSTL标准标签库_JSTL标准库的基本使用_02