JavaWeb基础

1,Servlet 生命周期、工作原理

点我跳转

2,JSP和Servlet的区别

jsp经过编译后变成类servlet,
jsp由html代码和jsp标签组成,擅长页面显示,servlet擅长流程控制;
JSP中嵌入JAVA代码,而Servlet中嵌入HTML代码。

3,JSP的动态include和静态include

(1)动态include用jsp:include动作实现,如
它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数。会先解析所要包含的页面,解析后和主页面合并一起显示,即先编译后包含。
(2)静态include用include伪码实现,不会检查所含文件的变化,适用于包含静态页面,如<%@ include file=”qq.htm” %>,
不会提前解析所要包含的页面,先把要显示的页面包含进来,然后统一编译,即先包含后编译。

4,设计模式的6大原则

(1)单一职责原则
可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
提高类的可读性,提高系统的可维护性;
变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。

(2)里氏替换原则
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
子类中可以增加自己特有的方法。
当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

(3)依赖倒置原则
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。
传递依赖关系的三种关系:
接口传递
构造方法传递
setter方法传递
(4)接口隔离原则
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,
则会造成接口数量过多,使设计复杂化。所以一定要适度。
为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,
才能建立最小的依赖关系。
提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
(5)迪米特法则
定义:一个对象应该对其他对象保持最少的了解。
(6)开闭原则
定义:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

4,Hibernate缓存:一级缓存和二级缓存

Hibernate缓存的分类:
(1),Session缓存(又称事物缓存),Hibernate内置的,不能卸载;
缓存范围:缓存只能被当前Session对象访问。缓存的生命周期依赖于Session的生命周期,当Session被关闭后,缓存也就结束生命周期。
(2)SessionFactory缓存(又称作应用缓存):使用第三方插件,可插拔.
缓存范围:缓存被应用范围内的所有session共享,不同的Session可以共享。这些session有可能是并发访问缓存,因此必须对缓存进行更新。
缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用程序范围。

一级缓存:
(1). save()。当session对象调用save()方法保存一个对象后,该对象会被放入到session的缓存中。
(2). get()和load()。当session对象调用get()或load()方法从数据库取出一个对象后,该对象也会被放入到session的缓存中。
(3). 使用HQL和QBC等从数据库中查询数据。
数据从缓存中清除:
(1). evit()将指定的持久化对象从缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象。
(2). clear()将缓存中的所有持久化对象清除,释放其占用的内存资源。
其他缓存操作:
(1). contains()判断指定的对象是否存在于缓存中。
(2). flush()刷新缓存区的内容,使之与数据库数据保持同步。

二级缓存:
定义:SessionFactory级别的缓存,可以跨越Session存在,可以被多个Session所共享。
实现原理:
Hibernate如何将数据库中的数据放入到二级缓存中?注意,你可以把缓存看做是一个Map对象,
它的Key用于存储对象OID,Value用于存储POJO。首先,当我们使用Hibernate从数据库中查询出数据,
获取检索的数据后,Hibernate将检索出来的对象的OID放入缓存中key 中,然后将具体的POJO放入value中,
等待下一次再次向数据查询数据时,Hibernate根据你提供的OID先检索一级缓存,若有且配置了二级缓存,则检索二级缓存,
如果还没有则才向数据库发送SQL语句,然后将查询出来的对象放入缓存中。

Spring定时任务

获取昨天时间

Calendar c=Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH,-1);   //日期月是0-11
c.set(Calendar.HOUR_OF_DAY,0);     
c.set(Calendar.MINUTE,0);
c.set(Calendar.SECOND,0);
c.set(Calendar.MILLISECOND,0);
return c.getTime();

在类上加上注解

@Configuration
@EnableScheduling
@Scheduled(fixedRate = 5000) :上一次开始执行时间点之后5秒再执行
@Scheduled(fixedDelay = 5000) :上一次执行完毕时间点之后5秒再执行
@Scheduled(initialDelay=1000, fixedRate=5000) :第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次
@Scheduled(cron=”/5 “) :通过cron表达式定义规则

获取文件流编码

1,获取文件的流

InportStream importStream = file.getInputStream();

2,把文件流转化为字节流

//字节数组输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
    byte[] buffer = new byte[1024];
    int len;
    while ((len = inputStream.read(buffer)) > -1) {
        baos.write(buffer, 0, len);
    }
    baos.flush();
}catch(IOException e){
    e.printStackTrace();
}
return new ByteArrayInputStream(baos.toByteArray());

3,根据字节流的判断文件的编码

//默认编码
String charset = "GBK";
byte[] first3Bytes = new byte[3];
//缓存流
BufferedInputStream bis = new BufferedInputStream(inputStream1);
try {
    boolean checked = false;
    //标记
    bis.mark(0);
    //读取文件的前3个字符
    int read = bis.read(first3Bytes, 0, 3);
    if (read == -1) return charset;
    if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
        charset = "UTF-16LE";
        checked = true;
    } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
        charset = "UTF-16BE";
        checked = true;
    } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) {
        charset = "UTF-8";
        checked = true;
    }
    bis.reset();
    if (!checked) {

        int loc = 0;
        while ((read = bis.read()) != -1) {
            loc++;
            if (read >= 0xF0) break;
            if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的,也算是GBK
                break;
            if (0xC0 <= read && read <= 0xDF) {
                read = bis.read();
                if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF) (0x80
                    continue;
                else break;
            } else if (0xE0 <= read && read <= 0xEF) {// 也有可能出错,但是几率较小
                read = bis.read();
                if (0x80 <= read && read <= 0xBF) {
                    read = bis.read();
                    if (0x80 <= read && read <= 0xBF) {
                        charset = "UTF-8";
                        break;
                    } else break;
                } else break;
            }
        }
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try {
        bis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}