java 课堂一些小练习和可能出现的面试题,还有打代码中遇到的问题。不定时更新。。。

一、redis实现分页思想

题目:
redis中有String hash list set数据结构,用一个或多个数据结构,实现页面中的前进和后退

实现思路:用两个list分别存储页面的前进和后退
实现具体流程和讲解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、EL表达式拿值

在这里插入图片描述

三、自己实现一个ArrayList

在这里插入图片描述
主要是扩容时间比较重要

package ybb;

import java.util.Arrays;

public class YbbArraylist<E> {
    //定义初始默认容量
    private static final int DEFAULT_CAPACITY = 10;
    //定义初始空数组
    private static final Object[] EMPTY = {};
    //成员属性
    transient Object[] elementData={};
    private int size;
    //定义极限数组大小
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;



    //构造方法
    public void ybbArraylist() {
        this.elementData = EMPTY;
    }




    public void ybbArraylist(int number) {
        if (number > 0) {
            //定义长度
            this.elementData = new Object[number];
        } else if (number == 0) {
            this.elementData = EMPTY;
        } else {
            throw new RuntimeException("请输入数字啊,你这输入的我不知道怎么初始创建了");
        }

    }

    public boolean add(E e) {
        int num= check(size + 1);//检查下能不能加入,或者扩容
       if (elementData.length<num){
           grow(num);
        }
        elementData[size] = e;
        size++;
        return true;
    }


    private void grow(int checkSize) {
        int  oldSize=elementData.length;
        int newSize = oldSize + (oldSize>> 1);
        if (newSize - checkSize < 0 ) {
           newSize=checkSize;
        }
        if (newSize-MAX_ARRAY_SIZE>0){
            if (checkSize>MAX_ARRAY_SIZE){
                  checkSize=Integer.MAX_VALUE;
            }else {
                checkSize=MAX_ARRAY_SIZE;
            }
        }
        elementData = Arrays.copyOf(elementData, newSize);
    }



    private int check(int checkSize) {

        //判断是否为空
        if (Arrays.equals(elementData,EMPTY)) {
            return Math.max(DEFAULT_CAPACITY, checkSize);
        }
        return checkSize;
    }

    public E get(int index) {
        if (index > elementData.length) {
            throw new RuntimeException("越界了呀,瓜皮");
        } else {
            return (E) elementData[index];
        }
    }

    public E set(int index, E element) {
        if (index > elementData.length) {
            throw new RuntimeException("找不到怎么修改啊,瓜皮");
        } else {
            E oldElement = element;
            elementData[index] = element;
            //修改后,返回修改前的数据,可以做比较
            return oldElement;
        }
    }

    public E remove(int index) {
        if (index > elementData.length) {
            throw new RuntimeException("找不到怎么修改啊,瓜皮");
        } else {
            E oldElement = (E) elementData[index];

            int numMoved = size - index - 1;
            if (numMoved > 0) {
                //原目标数组  从原数据的xx位置开始    目标数组  目标数组的xx位置开始  要copy的长度
                System.arraycopy(elementData, index + 1, elementData, index, numMoved);
            }
            elementData[--size] = null;//删完置为空
            return oldElement;
        }
    }

    public int length(){
        return size;
    }

}

四、异常体系

在这里插入图片描述
Throwable是所有异常的超类

Error 错误

不应该视图捕获的严重异常
一般是发生严重故障时,堆内存溢出,绝症,在java程序处理的范畴之外

Exception 异常

在这里插入图片描述

IOException(I/O输入输出异常)(受查异常)
编译期间必须得到处理的异常
例如格式化异常

RuntimeException(运行时异常)(非受查异常)
编译通过,运行时会报错
例如 最经典的数组索引越界异常

处理方式
一:throws/throw关键字
throws关键字声明,放在方法的尾部
或者
throw new 异常类名(参数)

二:try…catch关键字 (捕获异常)
try{
正常运行的代码
}catch(ExceptionName e1){
出现问题后执行的代码,多用于抛出
}finally{
无论发生异常,最终都会执行的代码,多用于关闭资源
}

public static void main(String[] args){
    int result = test3();
    System.out.println(result);
}

public static int test3(){
    //try 语句块中有 return 语句时的整体执行顺序
    int i = 1;
    try{
        i++;
        System.out.println("try block, i = "+i);
        return i;
    }catch(Exception e){
        i ++;
        System.out.println("catch block i = "+i);
        return i;
    }finally{
        i = 10;
        System.out.println("finally block i = "+i);
    }
}

输出结果如下:

try block, i = 2
finally block i = 10
2

是不是有点疑惑?明明我 try 语句块中有 return 语句,可为什么最终还是执行了 finally 块中的代码?

我们反编译这个类,看看这个 test3 方法编译后的字节码的实现:

0: iconst_1         //将 1 加载进操作数栈
1: istore_0         //将操作数栈 0 位置的元素存进局部变量表
2: iinc          0, 1   //将局部变量表 0 位置的元素直接加一(i=2)
5: getstatic     #3     // 5-27 行执行的 println 方法                
8: new           #5                  
11: dup
12: invokespecial #6                                                     
15: ldc           #7 
17: invokevirtual #8                                                     
20: iload_0         
21: invokevirtual #9                                                     24: invokevirtual #10                
27: invokevirtual #11                 
30: iload_0         //将局部变量表 0 位置的元素加载进操作栈(2)
31: istore_1        //把操作栈顶的元素存入局部变量表位置 1 处
32: bipush        10 //加载一个常量到操作栈(10)
34: istore_0        //将 10 存入局部变量表 0 处
35: getstatic     #3  //35-57 行执行 finally中的println方法             
38: new           #5                  
41: dup
42: invokespecial #6                  
45: ldc           #12                 
47: invokevirtual #8                  
50: iload_0
51: invokevirtual #9                
54: invokevirtual #10                 
57: invokevirtual #11                 
60: iload_1         //将局部变量表 1 位置的元素加载进操作栈(2)
61: ireturn         //将操作栈顶元素返回(2)
-------------------try + finally 结束 ------------
------------------下面是 catch + finally,类似的 ------------
62: astore_1
63: iinc          0, 1
.......
.......

从我们的分析中可以看出来,finally 代码块中的内容始终会被执行,无论程序是否出现异常的原因就是,编译器会将 finally 块中的代码复制两份并分别添加在 try 和 catch 的后面。
可能有人会所疑惑,原本我们的 i 就被存储在局部变量表 0 位置,而最后 finally 中的代码也的确将 slot 0 位置填充了数值 10,可为什么最后程序依然返回的数值 2 呢?

仔细看字节码,你会发现在 return 语句返回之前,虚拟机会将待返回的值压入操作数栈,等待返回,即使 finally 语句块对 i 进行了修改,但是待返回的值已经确实的存在于操作数栈中了,所以不会影响程序返回结果。

finally中多个retrun的话会产生覆盖

作者:凯玲之恋
链接:https://www.jianshu.com/p/49d2c3975c56
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

五、内部类

可以将一个类的定义放在另一个类的定义内部。这就是内部类

成员内部类

一个类的定义放在另一个类的定义内部
1.可以无条件的访问外部类的所有的成员属性,不受private和static影响
2.当内部类和外部类有方法或者属性同名的时候,在怎么调用,在内部类中调用的是自己的,调用外部类 “外部类”.this.成员变量/成员方法
3.如果外部类想访问内部类,要先生成内部类对象,才能访问
4.内部类是依附在外部类中的,如果在其他类中想访问内部类,需要先创建内部类

class Circle {
    double radius = 0;
     
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println("drawshape");
        }
    }
}

局部内部类

局部内部类主要是根据内部类定义的作用域来区分的,定义在一个方法或者某个作用域内的类

和局部变量一样,不能访问权限修饰符关键字
作用区间只能在申明的局部内

class People{
    public People() {
         
    }
}
 
class Man{
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //局部内部类
            int age =0;
        }
        return new Woman();
    }
}

匿名内部类

没有名称的内部类
一般用于继承其他类或者是实现接口,并不缺需要增加额外的方法,只对继承方法的实现或是重写
编写代码时用的最多的,在编写事件监听的代码时使用不但方便而且更容易维护

不能使用static和权限修饰符
没有构造器,通过new XXX的方式生成一个对象的引用
匿名内部类属于局部内部类,和上面限制一样

静态内部类

多个static关键字,不需要依赖 外部类
但也必须依附于具体的对象访问

public class Test {
    public static void main(String[] args)  {
        Outter.Inner inner = new Outter.Inner();
    }
}
 
class Outter {
    public Outter() {
         
    }
     
    static class Inner {
        public Inner() {
             
        }
    }
}

六、Mybatis二级缓存

在这里插入图片描述

一级缓存是SqlSession级别的缓存。操作数据库的时候需要构造sqlsession对象来调用对应的方法
二级缓存是Mapper级别 多个SqlSession去操作同一个Mapper的sql语句(共享)

一级缓存是默认开启的
二级缓存需要手动开启

 <!-- 全局参数的配置 -->
     <settings>
        <!-- 开启二级缓存 -->
             <setting name="cacheEnabled" value="true"/>
     </settings> 

缓存数据失效时机
      在表的结构或数据发生改变时,查询缓存中的数据不再有效。有这些INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、

DROP TABLE或DROP DATABASE会导致缓存数据失效。所以查询缓存适合有大量相同查询的应用,不适合有大量数据更新的应用。

二级缓存应用场景

对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,

提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间

隔 flushInterval ,比如设置为30分钟、60分钟、24小时等,根据需求而定。

七、动态代理

代理模式的定义:被代理者没有能力或者不愿意去完成某件事情,那么就需要找个人代替自己去完成这件事,这个人就是代理者, 所以代理模式包含了3个角色: 被代理角色 代理角色 抽象角色(协议 接口)

底层运用 利用反射机制在运行时创建代理类

public class Hello implements HelloInterface{
    @Override
    public void sayHello() {
        System.out.println("Hello"+"我是类中的");
    }
}
public interface HelloInterface {
    void sayHello();
}

package Invocation;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class Invocation implements InvocationHandler {
   private Object object;

   public Invocation(Object object){
       this.object=object;
   }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前面");
        Object invoke = method.invoke(object, args);
        System.out.println("后面");

        return invoke;

    }
}

这里有个细节,return!如果return null,那当方法有返回值的时候,是拿不到的。returun method.invoke的对象,这样如果有返回值的时候,可以取到

package test;


import Invocation.Hello;
import Invocation.HelloInterface;
import Invocation.Invocation;
import ybb.YbbArraylist;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;

import static org.apache.commons.math3.analysis.FunctionUtils.add;

public class test1 {

    public static void main(String[] args) {

        HelloInterface hello=new Hello();
        InvocationHandler invocation = new Invocation(hello);
        HelloInterface proxyInstance = (HelloInterface)Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), invocation);

        proxyInstance.sayHello();

    }

}


jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象
参数1 loader:被代理类的类加载器
参数2 interfaces: 被代理类所有实现的接口的Class对象
参数3 InvocationHandler: 执行处理类
前2个参数是为了帮助在jvm内部生成被代理类的代理对象,第3个参数用来监听代理对象调用的方法,帮助我们代理对象调用方法
是不真实存在的,通过实现接口类的对象直接生成代理对象

public Object invoke(Object proxy, Method method, Object[] args);
回调方法: 当代理对象调用了方法,就会来执行该invoke方法, 在该方法中就可以增强被代理类的方法
参数1: 生成的代理对象 这里就是p这个代理对象 (慎用)
参数2: 当前代理对象执行的方法 这里method就是sayHello方法对象
参数3: 当前代理对象执行的方法,传入的实际参数
返回值:当前代理对象执行的方法的返回值
在这里插入图片描述
PS:如果在调用Proxy.newProxyInstance方法前设置
System.getProperties().setProperty(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);
加载完会有一个class的字节码文件

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import Invocation.HelloInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements HelloInterface {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void sayHello() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("Invocation.HelloInterface").getMethod("sayHello");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

八、反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

利用Java反射机制我们可以加载一个运行时才得知名称的class,获悉其构造方法,并生成其对象实体,能对其fields设值并唤起其methods。

运行时动态加载需要加载的对象
Class类:Class是开启反射的源头;
在Object类中定义了以下的方法,此方法将被所有子类继承:
public final Class getClass();
在这里插入图片描述

Class本身也是一个类;
Class 对象只能由系统建立对象;
一个类在 JVM 中只会有一个Class实例;
一个Class对象对应的是一个加载到JVM中的一个.class文件;
每个类的实例都会记得自己是由哪个 Class 实例所生成;
通过Class可以完整地得到一个类中的完整结构;

反射需要先创建出来Class类,再通过对应的方法去获取或者操作具体的方法或者属性

Class类
获取有三种方式

  1. 类名.class
  2. 对象名.getClass()
  3. Class.forName(“全类名”)

Constructor 类的构造方法

有无Declared的区别是能否能获取到非公共(protected,private)的的构造方法!
Constructor getConstructor(Class… parameterTypes)
* 根据参数类型获得对应的Constructor对象。
* 只能获得public修饰的构造方法
Constructor getDeclaredConstructor(Class… parameterTypes)
* 根据参数类型获得对应的Constructor对象
可以是publicprotected(默认)private修饰符的构造方法。
*  Constructor[] getConstructors()
获得类中的所有构造方法对象,只能获得public* Constructor[] getDeclaredConstructors()
获得类中的所有构造方法对象
可以是publicprotected(默认)private修饰符的构造方法。

如果不知道可以先通过Class对象.getDeclaredConstructors()获取所有的构造方法,然后再操作

Class类.newInstance() 方法创建该类对象
void setAccessible(true) 设置“暴力反射”—是否取消权限检查,true取消权限检查,false表示不取消

Field类 代表类的成员变量(类的属性)

Class类中与Field相关的方法
* Field getField(String name);
    *  根据成员变量名获得对应Field对象,只能获得public修饰
* Field getDeclaredField(String name);
    *  根据成员变量名获得对应Field对象,包括publicprotected(默认)private* Field[] getFields();
    * 获得所有的成员变量对应的Field对象,只能获得public* Field[] getDeclaredFields();
    * 获得所有的成员变量对应的Field对象,包括publicprotected(默认)private

Method类 代表类的方法

**Method** 类的方法

* Method getMethod(String name,Class...args);
    * 根据方法名和参数类型获得对应的构造方法对象,只能获得public* Method getDeclaredMethod(String name,Class...args);
    * 根据方法名和参数类型获得对应的构造方法对象,包括publicprotected(默认)private* Method[] getMethods();
    * 获得类中的所有成员方法对象,返回数组,只能获得public修饰的且包含父类的

* Method[] getDeclaredMethods();
    * 获得类中的所有成员方法对象,返回数组,只获得本类的,包括publicprotected(默认)private的


    设置"暴力访问"——是否取消权限检查,true取消权限检查,false表示不取消
**如果不知道可以先通过Class对象.getDeclaredMethods()获取所有的构造方法,然后再操作**
  • Object invoke(Object obj, Object… args)
    • 调用指定对象obj的该方法
    • args:调用方法时传递的参数
  • void setAccessible(true)

九、打代码中遇到的问题

在自己做VUE和ELEMENT结合ajax实现前后端登录和数据的增删改查

1.错误Binding.BindingException

Dao层的interface和mapper映射文件,有一个很重要的东西!
如果interface传参只有一个,就没事,如果传参多个,需要在接口方法中指定方法名称!!!
在这里插入图片描述
在这里插入图片描述
不然会报
在这里插入图片描述
这个异常!纪念我卡了一天的bug!

2.VUE 双向绑定问题

基本用在表单中
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一定要对应起来,不然调试很麻烦。

3.数据库字段和类属性

数据库字段中会有有时候会有一些下划线(_)这种符号,如果搞不清楚,可以尝试
在这里插入图片描述
这样会好理解些

4.数据库中double类型和idea中double类型代表的存储占用空间不一样,要小心

5.html中表单提交页面交互会有BUG,要用ajax技术来实现异步的前后端交互

6.Dao层的interface和mapper映射文件

Dao层的interface和mapper映射文件,有一个很重要的东西!
如果interface传参只有一个,就没事,如果传参多个,需要在接口方法中指定方法名称!!!
在这里插入图片描述
在这里插入图片描述
不然会报
在这里插入图片描述

7.属性和数据库的字段名 匹配

实体类的属性和数据库的字段名一致,可以直接resultType封装,但是如果不一致,用resultMap处理关系的映射,然后封装。如果不一致,是拿不到数据的
在这里插入图片描述

8. MAVEN中如果都是好的,要打包不行,看下配置的时候是war还是jar

在这里插入图片描述

9. Error querying database. Cause: java.sql.SQLException: Must specify port after ‘:’ in connection string

在这里插入图片描述

多半是url配错了
在这里插入图片描述
这样就对了

Process finished with exit code -1073741819 (0xC0000005) 和解决maven编译 Process terminated

在这里插入图片描述
多半是金山毒霸冲突,删了就好了!!!

十、系统监控功能

问题:监控用户在什么时间请求了什么方法,请求的路径是什么,请求的方法名是什么,这些方法执行耗费了多长时间,把对应的这些数据存到表里面,以上功能完成后需要展示这些数据

思路:
1.根据需求在数据库中建立一个表,id主键自增 int,create_time date ,url varchar,method_name varchar,,waste_time date
2.在类中定义属性和数据库中的字段保持一致
3.然后是三层结构和前端页面,需要两个方法(添加addlog和查找所有findall)
4.重点,过滤器的使用(来回都会经过过滤器,简单了)
domain

public class Log {
    private Integer id;
    private Date create_time;
    private String method_name;
    private String method_url;
    private Date waste_time;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getCreate_time() {
        return create_time;
    }

    public void setCreate_time(Date create_time) {
        this.create_time = create_time;
    }

    public String getMethod_name() {
        return method_name;
    }

    public void setMethod_name(String method_name) {
        this.method_name = method_name;
    }

    public String getMethod_url() {
        return method_url;
    }

    public void setMethod_url(String method_url) {
        this.method_url = method_url;
    }

    public Date getWaste_time() {
        return waste_time;
    }

    public void setWaste_time(Date waste_time) {
        this.waste_time = waste_time;
    }

    public Log(Integer id, Date create_time, String method_name, String method_url, Date waste_time) {
        this.id = id;
        this.create_time = create_time;
        this.method_name = method_name;
        this.method_url = method_url;
        this.waste_time = waste_time;
    }
}

service

public interface LogService {
    List<Log> logs();

    void addlog(Log log);
}

serviceImpl

package com.ybb.service.Impl;

import com.ybb.dao.LogDao;
import com.ybb.domain.Log;

import com.ybb.service.LogService;
import com.ybb.utils.TransactionUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class LogSericeImpl implements LogService {
    @Override
    public List<Log> logs() {
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            is = Resources.getResourceAsStream("MyBatisConfig.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
            sqlSession = build.openSession(true);

            LogDao mapper = sqlSession.getMapper(LogDao.class);
            List<Log> logs = mapper.logs();
            return logs;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void addlog(Log log) {
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            is = Resources.getResourceAsStream("MyBatisConfig.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
            sqlSession = build.openSession(true);

            LogDao mapper = sqlSession.getMapper(LogDao.class);
            mapper.addlog(log);
            TransactionUtil.commit(sqlSession);
        } catch (IOException e) {
            TransactionUtil.rollback(sqlSession);
            throw new RuntimeException(e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            TransactionUtil.close(sqlSession);
        }
    }
}

logServlet

package com.ybb.service.Impl;

import com.ybb.dao.LogDao;
import com.ybb.domain.Log;

import com.ybb.service.LogService;
import com.ybb.utils.TransactionUtil;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class LogSericeImpl implements LogService {
    @Override
    public List<Log> logs() {
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            is = Resources.getResourceAsStream("MyBatisConfig.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
            sqlSession = build.openSession(true);

            LogDao mapper = sqlSession.getMapper(LogDao.class);
            List<Log> logs = mapper.logs();
            return logs;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void addlog(Log log) {
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            is = Resources.getResourceAsStream("MyBatisConfig.xml");
            SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
            sqlSession = build.openSession(true);

            LogDao mapper = sqlSession.getMapper(LogDao.class);
            mapper.addlog(log);
            TransactionUtil.commit(sqlSession);
        } catch (IOException e) {
            TransactionUtil.rollback(sqlSession);
            throw new RuntimeException(e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            TransactionUtil.close(sqlSession);
        }
    }
}

过滤器

package com.ybb.web.filter;

import com.ybb.domain.Log;
import com.ybb.service.Impl.LogSericeImpl;
import com.ybb.service.LogService;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

@WebFilter(value = {"/*"})
public class logFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
        try{
            //1.将请求和响应对象转换为和HTTP协议相关
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            LogService logService=new LogSericeImpl();
            //创建时间
            long create_time = System.currentTimeMillis();
            //方法
            String method = request.getParameter("method");
            //路径
            String requestURI = request.getRequestURI();
            //4.放行
            filterChain.doFilter(request,response);
            // 耗费的时候
            long waste_time = System.currentTimeMillis() - create_time;


            Date create = new Date(create_time);
            Date waste = new Date(waste_time);

            logService.addlog(new Log(null,create,method,requestURI,waste));


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {

    }
}

页面展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>商品管理系统</title>
    <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
    <script src="js/vue.js"></script>
    <script src="element-ui/lib/index.js"></script>
    <script src="js/axios-0.18.0.js"></script>
</head>
<body>
<div id="div">
    <b style="color: red; font-size: 20px;">日志列表</b>
    <el-table :data="tableData">
        <el-table-column prop="id" label="日志编号" width="220">
        </el-table-column>
        <el-table-column prop="create_time" label="请求创建时间" width="220">
        </el-table-column>
        <el-table-column prop="method_name" label="请求方法名" width="220">
        </el-table-column>
        <el-table-column prop="method_url" label="请求路径" width="220">
        </el-table-column>
        <el-table-column prop="waste_time" label="请求耗费时间" width="220">
        </el-table-column>
    </el-table>

    <!--
        分页组件
          @size-change: 当改变每页条数时触发的函数
          @current-change:当改变页码时触发的函数
          current-page :默认的页码
          :page-sizes:每页条数选择框中显示的值
          :page-size : 默认的每页条数
          layout: 分页组件的布局
              total(总条数), sizes(每页条数), prev(上一页), pager(所有的页码), next(下一页), jumper(跳转页码)
          :total: 总条数
    -->
    <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="pagination.currentPage"
            :page-sizes="[3,5,8]"
            :page-size="pagination.pageSize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="pagination.total">
    </el-pagination>


</div>
</body>
<script>
    new Vue({
        el:"#div",
        data:{
            tableData:[],//表格数据
            pagination: {
                currentPage: 1, //当前页
                pageSize: 5,    //每页显示条数
                total: 0        //总条数
            },

        },
        methods:{
            //分页查询功能
            selectByPage(){
                axios.post("logServlet","method=log&currentPage=" + this.pagination.currentPage + "&pageSize=" + this.pagination.pageSize)
                    .then(resp => {
                        //将查询出的数据赋值tableData
                        this.tableData = resp.data;
                        //设置分页参数
                        //当前页
                        this.pagination.currentPage = resp.data.pageNum;
                        //总条数
                        this.pagination.total = resp.data.total;
                    })
            },
            //改变每页条数时执行的函数
            handleSizeChange(pageSize) {
                //修改分页查询的参数
                this.pagination.pageSize = pageSize;
                //重新执行查询
                this.selectByPage();
            },
            //改变页码时执行的函数
            handleCurrentChange(pageNum) {
                //修改分页查询的参数
                this.pagination.currentPage = pageNum;
                //重新执行查询
                this.selectByPage();
            },

        },
        mounted(){
            //调用分页查询功能
            this.selectByPage();
        }
    });
</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值