那些问到的而我不会的问题

登录是怎么做的,为什么要这么做

登录的基本思路是:
正常的登录界面,需要键入用户名密码,用户名密码正确可以进入之后的操作;用户名密码错误则要重试。最后要有退出登录功能。
在这里插入图片描述

所以我们需要写一个用户servlet,一个登录界面和一个登录失败页面。其中用户userServlet需要能查找用户的其他信息,能跳转到登录和登录失败界面,可以用一个if实现。

但是有一个大问题就是:目前我如果输入我项目里的某些网址可以跳过登录的步骤直接访问,非常不安全,但给每一个都加上登录method太过于繁杂,所以我需要过滤器。

过滤器实现Filter接口,三个生命历程(init,doFilter,destroy)都要有。主要的过滤操作在doFilter里实现。

Spring里面常使用的一些注解

Tomcat是什么

tomcat是一个中间件,在B/S架构中,浏览器发出的http请求经过tomcat中间件,转发到最终的目的服务器上,响应消息再通过tomcat返回给浏览器。

tomcat所做的事情主要有:开启监听端口监听用户的请求,解析用户发来的http请求然后访问到你指定的应用系统,然后你返回的页面经过tomcat返回给用户。

对反射是怎么理解的

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

要想解剖一个类,必须先要获取到该类的字节码文件对象(class)。而解剖使用的就是Class类中的方法。所以先要获取到每一个字节码文件对应的Class类型的对象。

如何获得字节码文件

Class:是反射的核心类
每个类加载到内存后,系统都会有唯一的一份字节码对象(Person.class/Student.class字节码对象都是Class这个类的实例)

三个方法:
Class.forName(类路径)
类型.class
对象.getClass(),已经实例化的情况下

为什么使用反射

增加程序的灵活性,避免将程序写死到代码里。
例如: 实例化一个 person()对象,
不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码,并重新编译。
使用反射: class.forName(“person”).newInstance(); 而且这个类描述可以写到配置文件中,如 **.xml, 这样如果想实例化其他类,只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。

很少情况下是非用反射不可的。大多数情况下反射是为了提高程序的灵活性。
因此一般框架中使用较多。因为框架要适用更多的情况。对灵活性要求较高。

哪里用到了反射

1、JDBC中,利用反射动态加载了数据库驱动程序。

 java Class.forName('com.mysql.jdbc.Driver');//加载MySQL的驱动类 

2、Web服务器中利用反射调用了Sevlet的服务方法(service)。
3、IDEA等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。
4、很多框架都用到反射机制,注入属性,调用方法,如Spring。

了解过MySQL的配置吗

1、安装,设置密码。
2、MySQL环境变量的配置,
创建 MYSQL_HOME 环境变量,配置的是MySQL的安装目录;
配置 path 环境变量
%MYSQL_HOME%\bin,确定。
3、在命令提示符下启动、停止MySQL服务器

MyBatis的增强(MyBatis-Plus)

MyBatis 增强工具包,简化 CRUD 操作。
CRUD:增删改查
启动加载 XML 配置时注入单表 SQL 操作 ,为简化开发工作、提高生产率而生。

与其他 Mybatis 工具包区别
1、优势一、 Mybatis-plus 启动注入非拦截实现、性能更优。
2、优势二、多种 ID 选择,类型 ID_WORKER , UUID 全局唯一、支持实现分库。
3、优势三、完全继承原生易理解、扩展使用,支持自定义表、字段、ID动态注解。

创建对象的方法

使用New关键字、使用Class类的newInstance方法、使用Constructor类的newInstance方法、使用Clone方法、使用反序列化。

1、使用new关键字:这是我们最常见的也是最简单的创建对象的方式,通过这种方式我们还可以调用任意的构造方法(无参的和有参的)。比如:Student student = new Student();
2、使用Class类的newInstance方法:我们也可以使用Class类的newInstance方法创建对象,这个newInstance方法调用无参的构造器创建对象,如:

Student student2 = (Student)Class.forName("根路径.Student").newInstance(); 
Student stu = Student.class.newInstance();

3、使用Constructor类的newInstance方法:本方法和Class类的newInstance方法很像,java.lang.relect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数的和私有的构造函数。如:

Constructor<Student> constructor = Student.class.getInstance();
Student stu = constructor.newInstance(); 

这两种newInstance的方法就是大家所说的反射,事实上Class的newInstance方法内部调用Constructor的newInstance方法。这也是众多框架Spring、Hibernate、Struts等使用后者的原因。
4、使用Clone的方法:无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。要使用clone方法,我们必须先实现Cloneable接口并实现其定义的clone方法。如:

Student stu2 = <Student>stu.clone();

这也是原型模式的应用。
5、使用反序列化:当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象,在反序列化时,JVM创建对象并不会调用任何构造函数为了反序列化一个对象,我们需要让我们的类实现Serializable接口。如:

ObjectInputStream in = new ObjectInputStream (new FileInputStream("data.obj")); 
Student stu3 = (Student)in.readObject();

final关键字

可以修饰类,方法,局部变量和成员变量4个
1、类
使当前这个类不能有任何子类。
注意:一个类如果是final的,那么其中所有的成员方法都无法进行覆盖重写
2、方法
不能被重写覆盖。
所以abstract关键字和final关键字不能同时使用
3、局部变量
变成常量,“一次赋值,终生不变”
4、成员变量
对于成员变量来说,如果使用了final关键字修饰,那么这个变量也照样是不可变的
① 由于成员变量具有默认值,所以用了final之后必须手动赋值,不会再给默认值了
② 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值,只能二选一
③ 必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值

重写和重载

重载与重写是 Java 多态性的不同表现。
重写是父类与子类之间多态性的表现,在运行时起作用(动态多态性,譬如实现动态绑定)
而重载是一个类中多态性的表现,在编译时起作用(静态多态性,譬如实现静态绑定)。

重载(Overload)是让类以统一的方式处理不同类型数据的一种手段,实质表现就是多个具有不同的参数个数或者类型的同名函数(返回值类型可随意)同时存在于同一个类中,是一个类中多态性的一种表现(调用方法时通过传递不同参数个数和参数类型来决定具体使用哪个方法的多态性)。
重载规则:必须具有不同的参数列表; 可以有不同的返回类型;可以有不同的访问修饰符;可以抛出不同的异常。

重写(Override)是父类与子类之间的多态性,实质是对父类的函数进行重新定义,如果在子类中定义某方法与其父类有相同的名称和参数则该方法被重写,不过子类函数的访问修饰权限不能小于父类的;若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法,如需父类中原有的方法则可使用 super 关键字。
重写规则:参数列表必须完全与被重写的方法相同;
返回类型必须一直与被重写的方法相同;
访问修饰符的限制一定要大于等于被重写方法的访问修饰符;
重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常,譬如父类方法声明了一个检查异常 IOException,在重写这个方法时就不能抛出 Exception,只能抛出 IOException 的子类异常,可以抛出非检查异常。

Spring Bean生命历程

bean整个生命周期的过程:

1、首先这个bean在进行开始实例化的时候会先进行调用该类的构造函数,默认是单例的
2、然后去注入bean
3、如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;
4、如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;
5、如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中;
6、如果bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization方法将被调用;
7、如果bean实现了InitializingBean接口,spring将调用它的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会被调用;
8、如果bean实现了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法将被调用;
9、此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁;
10、若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用;

p1p2p3三个线程怎么保证按顺序进行

有三个线程T1,T2,T3,如何保证顺序执行?
在多线程中有多种方法让线程按特定顺序执行,用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。
T3调用T2,T2调用T1,这样T1就会先完成而T3最后完成。
实际上先启动三个线程中哪一个都行,因为在每个线程的run方法中用join方法限定了三个线程的执行顺序。
public class JoinTest2 {
// 1.现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行

public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 引用t1线程,等待t1线程执行完
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
// 引用t2线程,等待t2线程执行完
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}

});
t3.start();//这里三个线程的启动顺序可以任意,大家可以试下!
t2.start();
t1.start();
}
}

泛型

Collection虽然可以存储各种对象,但实际上通常Collection只存储同一类型对象。例如都是存储字符串对象。因此在JDK5之后,新增了泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样我们使用API的时候也变得更为简洁,并得到了编译时期的语法检查。

泛型:可以在类或方法中预支地使用未知的类型。
一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。

使用泛型的好处
1、将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
2、避免了类型强转的麻烦。

Tomcat怎么配置的

1.配置 CATALINA_BASE,路径为你自己的tomcat的安装目录,不要出现中文
2. 配置 CATALINA_HOME,路径为你自己的tomcat的安装目录,不要出现中文
3. 配置 JRE_HOME: “D:\jdk 1.8.0_181\jre”
4. 配置 JAVA_HOME : "D:\jdk 1.8.0_181
5. 配置PATH
6. 配置好了之后,可以win + X 打开 命令提示符(管理员),输入startup ;
或者在浏览器输入localhost:8080

CurrentHashMap是如何保证安全又快捷的

HashMap、HashTable和CurrentHashMap中,
HashMap线程不安全但是效率高,HashTable使用Synchronized锁,线程安全但效率低,为了能集两者的优点,CurrentHashMap出现了。
ConcurrentHashMap避免了对全局加锁改成了局部加锁操作,这样就极大地提高了并发环境下的操作速度。
ConcurrentHashMap在JDK1.7和1.8中的实现非常不同,
JDK1.7:在JDK1.7中ConcurrentHashMap采用了数组+Segment+分段锁的方式实现。 在数组基础上增加了一层Segment,一个Segment对应数组的一段,这样对某段进行的操作只需要锁住对应段,不影响其他段的操作。Segment的锁是可重入的。
JDK1.8:在JDK1.7中ConcurrentHashMap,数据结构上,首先整体上是数组+链表+红黑树的结构与HashMap保持一致,其次取消了Segment分段锁的数据结构,取而代之的是Node,Node的value和next都是由volatile关键字进行修饰,可以保证可见性。将细化的粒度从段进一步降低到节点。线程安全实现上,采用CAS+Synchronized替代Segment分段锁。

JDK1.7和1.8

1、Lambda表达式
2、更强的Strean API
3、接口的增强
4、方法引用/构造器引用
5、函数式接口
6、Optional
7、新的时间和日期API
8、其它新特性,如注解中的重复注解、类型注解,HashMap底层的变化,JVM中Metaspace取代PermGen空间等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值