java两大数据类型:
1.引用数据类型
引用数据型在被创建时,首先要在栈上给其引用(句柄)分配一块内存,而对象的具体信息都存储在堆内存上,然后由栈上面的引用指向堆中对象的地址。
引用数据类型包括:类、接口类型、数组类型、枚举类型、注解类型,字符串型;
2.基本数据类型
基本数据类型在被创建时,在栈上给其划分一块内存,将数值直接存储在栈上
包括数值型,字符型和布尔型
静态变量Static
原理:系统在进行编译时就会对Static这一行进行初始化,为静态变量赋值
函数在调用的时候,会自动跳过Static这一行
静态变量的作用是为了跨函数共享数据(同一个函数被多次调用)
静态变量的使用:
1.为了统计:当前函数被调用的次数
2.为了统筹函数多次调用得到的不同结果(递归思想)
静态方法调用不需要实例化对象,常用在工具类中
封装类是引用类型
向上转型,JAVA中的一种调用方式。向上转型是对A的对象的方法的扩充,即A的对象可访问B从A中继承来的和B复写A的方法。
if(!语句)里边的语句会被执行
ArrayList t类型不安全,因为加入的数据为object类型,所以需要装箱与拆箱,效率较低。
List:声明时就决定了类型,所以是类型安全的,省掉了装箱与拆箱的过程,效率比ArrayList要高。
(顶级接口)Collection-->Queue-->Deque-->LinkedList(实现类)
string 和int之间的转换
string转换成int :Integer.valueOf("12")
int转换成string : String.valueOf(12)
char和int之间的转换
首先将char转换成string
String str=String.valueOf('2')
Integer.valueof(str) 或者Integer.PaseInt(str)
Integer.valueof返回的是Integer对象,Integer.paseInt返回的是int
Lambda
Collections.sort(heros,(h1,h2)->h1.hp>=h2.hp?1:-1);
静态块,执行一次,随着类的加载被加载,只有一次哈,实例的是每次创建对象都执行
在创建对象时
先调用构造方法,后创建对象
静态数据区:全局变量,静态变量,类加载器
栈:局部变量,函数调用call(调用函数式的寄存器信息),每次调用函数时,会在栈上分配一帧,每当函数返回时,再从栈上将此帧移去(保留现场和恢复现场)
方法区(元空间):存放类信息
当一个类加载器启动时,(类加载器在堆中),然后他会去主机的硬盘上将我们的字节码文件装载进jvm方法区,方法区此时装载了类的信息,堆中的Class对象的引用,和类加载器的引用
堆的可用空间远大于栈(对象很大,地址很小)
在准备阶段如果是final修饰的static变量会赋值,否则只创建不赋值
实例化子类对象时,会优先调用父类无参构造方法(不论当前子类构造方法含不含参),再调用子类构造方法
如果没有写父类无参构造函数,而写了父类含参构造函数,则用super调用含参的,否则报错
类方法就是类的静态方法的一种简单说法,至于为什么这么说,因为它可以直接通过类名调用。要加深理解的话,可以和对象方法这个说法进行比较。
至于类对象指的是一个类在jvm中加载后所形成的对象,每一个类都只有一个类对象,该类对象被所有的实例对象所共享。所以要注意类对象与类的实例对象的区别,这是两个不同的概念。
Math.abs(Integer.MIN_VALUE)的值是其本身!
Integer.MIN_VALUE是 -2147483648的,但一个32位整数可以包含最高值是 +2147483647。试图代表 +2147483648在32位int将有效地“翻转”到 -2147483648。
gbk中文2个字节,英文1个字节;utf-8中文3个字节,英文1个字节
fis按字节读取某个文件里面的内容(这种情况是是一个字节一个字节的读取),当读到最后的时候,就会返回-1。
FileReader fr = new FileReader(a);
char [] ba = new char[1024];
int len = -1;
while ((len=fr.read(ba))!=-1){
System.out.print(new String(ba,0,len));
}
或者
byte[] bytes = new byte[(int) f1.length()];
fis.read(bytes);
两种方法,不可混用(空文件死循环)
getText().trim()的作用是在获得的文本中除去空格.
byte[] buf = new byte[1024];
int num = in.read(buf);
String str = new String(buf,0,num);
in.read方法的返回值是读取的字节总数,也就是读取了num个字节放在buf里。
然后将buf里的前num个字节转换为字符串。
字节流:String(byte[] bytes, String charsetName)
通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
字符流:InputStreamReader isr = new InputStreamReader(new FileInputStream(f),Charset.forName("UTF-8");
正则表达式:
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字 等价于 '[^A-Za-z0-9_]'。
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
\w能不能匹配汉字要视你的操作系统和你的应用环境而定
\d是表示0-9的一个数字。正则表达式在运用到有些编程语言的时候需要转义一下,比如java就需要写成\d
监听器的两种实现方法
1.用接口,显示所有方法,只重写需要用到的方法
需要 this.addKeyListener(this); //添加键盘监听接口
2.用适配器(只显示这一种方法)
例:this.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
});
1.setPreferredSize需要在使用布局管理器的时候使用,布局管理器会获取空间的preferredsize,因而可以生效。例如borderlayout在north中放入一个panel,panel的高度可以通过这样实现:panel.setPreferredSize(new Dimension(0, 100));这样就设置了一个高度为100的panel,宽度随窗口变化。
2.setSize,setLocation,setBounds方法需要在不使用布局管理器的时候使用,也就是setLayout(null)的时候可以使用这三个方法控制布局。
Map paramMap = request.getParameterMap();
druid
配置 JDBCHelper(当前类)
InputStream in = JDBCHelper.class.getClassLoader().getResourceAsStream("db.properties");
Properties = props = new Properties();
props.load(in);
连接
ds = DruidDataSourceFactory.createDataSource(props);
connection = ds.getConnection();
sql语句
(字符串数据是用单引号包在外面的,而+号只是用来连接这些字符串的. 数据库里的字段是整型的时候不要加单引号,是字符串的时候要加,其它类型根据实际情况来,双引号就是用来拼接字符串的,单引号是sql文的固有写法,因为你要动态的来拼接,涉及到变量,所以要用“+”来组合各个字符串片段。)
id和age是int型的所以不用加单引号
String sql = "insert into student values ( " + student.getId() + " ,' "
+ student.getUsername() + " ', " + student.getAge() + " ,' "
+ student.getClassnumber()+" ')";
/*会匹配jsp页面
/不会
RestController ResponseBody(配合Controller)
不会走视图解析器
Restful
@RequestMapping(value="/editBook/{id}",method= RequestMethod.GET)
public String editBook(Model model,@PathVariable Integer id){}
@RequestMapping("/editBook/{id}")
public String editBook(Model model,@PathVariable Integer id){}
href只能get参数,action能get参数又能post参数
Get是Form的默认方法
MyISAM B+树 不支持事务
MEMORY hash索引
InnoDB B+树
B+数
有n棵子树的结点中含有n个关键码有n棵子树的结点中含有n个关键码
所有的叶子结点中包含了全部关键码的信息,
及指向含有这些关键码记录的指针,
且叶子结点本身依关键码的大小自小而大的顺序链接
当索引部分某个结点的关键字与所查的关键字相等时,并不停止查找,应继续沿着这个关键字左边的指针向下,一直查到该关键字所在的叶子结点为止
jvm调优 减少full gc次数
增大对年轻代内存的分配(减少老年代大小),使原来的大文件(超过surviror的50%)不容易进入老年代
一个类可以实现多个接口,只能继承一个抽象类
接口没有构造方法。不可以被实例化,抽象类有构造方法,但不能通过new实例化
接口只能被public修饰(并且默认为public abstract修饰),抽象类可以被public,protected,默认修饰符修饰
接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值,抽象类任意
强引用----普通引用
软引用----内存不够时清除
弱引用----gc时清除
虚引用----返回一个储存信息的对列,当gc时储存信息,告诉外部内存(jvm外)也进行清除
threadlocal
thread维护了一个map:threadLocals
key是threadloacl
spring TranscationManager事务
使a操作和b操作共用一个链接 把conn放进threadlocal中,保证ab拿的是同一个conn
java有三种类加载器(面试会问)
1)根类加载器(bootstrap class loader)
2)扩展类加载器(extension class loader)
3)应用类加载器(application class loader)
双亲委派机制
即一个类加载器接收到加载此类的请求时会先去请求父类加载器加载此类,如果父类还有父类则继续传给父类的父类,当找到最根的类加载器时(启动类加载器),加载器会尝试在自己的查找范围内找此类的class文件,若找到则加载,找不到就往回走,即告诉子类我不能处理这个任务,然后子类看看在他的范围能不能找到,找到就加载,再找不到继续往下传,都找不到报错
总之一句话:有事往上级抛,上级都处理不了我再处理
缓存机制
缓存机制指,类加载器加载时将缓存所有加载过的class,存在每一个类加载器的缓冲中,下次获取此类的class时先去缓存中找,那么结合双亲委派机制,流程应该是这样的
拿到加载请求后,先去我的缓存里找,没有了往上抛,上面接收到了,直接在自己的缓存找,没有了再往上抛,如果上面没有了,那就尝试加载,找不到了,往下扔,然后下面的拿到直接尝试加载,找不到了,再往下扔,下面没有了就报错
Properties properties = new Properties();
InputStream is = te.class.getResourceAsStream("a.properties");
properties.load(is);
System.out.println(properties.getProperty("b"));
- Class.getResourceAsStream(String path) : path 不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取。其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源。
- Class.getClassLoader.getResourceAsStream(String path) :默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。
- ServletContext. getResourceAsStream(String path):默认从WebAPP根目录下取资源,Tomcat下path是否以’/'开头无所谓,当然这和具体的容器实现有关。
@Bean是一个方法级别上的注解,主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名,方法返回值 就是要注册的bean
@Configuration 注释的类 类似于于一个 xml 配置文件的存在(针对于ClassXmlPathApplicationContext 来说)
当调用ShiroHandler中的subject.login()的时候,会自动调用Realm中的doGetAuthenticationInfo方法
subject.hasRole 判断Subject是否拥有该角色,会自动调用Realm中的doGetAuthorizationInfo方法
Subject.isPermitted(permission)已登陆用户判断是否具有某权限s,会自动调用Realm中的doGetAuthorizationInfo方法
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
这种写法就和 applicationContext-shiro.xml 中的
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
shiro如何验证
shiro会校验info和token,Token和SimpleAuthenticationInfo的credentials做对比,进行验证。
这块对比逻辑是先对比username,但是username肯定是相等的,所以真正对比的是password。从这里传入的password(这里是从数据库获取的)和token(filter中登录时生成的)中的password做对比,如果相同就允许登录,不相同就抛出异常。如果验证成功,最终这里返回的信息authenticationInfo 的值与传入的第一个字段的值相同(我这里传的是user对象)
SimpleAuthenticationInfo放盐值
HashedCredentialsMatcher放加密算法和加密次数
anon: 无需认证即可访问
authc: 需要认证才可访问
user: 点击“记住我”功能可访问
perms: 拥有权限才可以访问
role: 拥有某个角色权限才能访问
ClassLoader和ClassForname的区别
两者的区别在在于一个会初始化操作,一个不会初始化操作,而在类加载过程中,初始化的作用主要是执行静态代码块。
通过结果进行分析classform在之前便执行了静态代码块,而我们的loaderclass这个方法并没有执行静态代码块,只有在后面使用类的时候才执行了。
动态代理没有代理 0类0(或者说是动态的),直接反射调用class对象
三次握手
为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误
SSL/TLS协议的基本思路是采用公钥加密法,也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
1)newCachedThreadPool()用来处理大量短时间工作任务的线程池。当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过 60 秒,则被终止并移出缓存;其内部使用SynchronousQueue 作为工作队列。
(可以无限制的创建线程(其实也有限制的,数目为Interger. MAX_VALUE),有需要就创建,某线程60秒未使用会终止,如要再使用需要创建新的)
2)newFixedThreadPool(int nThreads),重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。
(创建一个指定工作线程数量的线程池,每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。)
3)newSingleThreadExecutor(),它的特点在于工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态
(创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO,优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。)
4)newSingleThreadScheduledExecutor() 和 newScheduledThreadPool(int corePoolSize),创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程。
(支持定时的以及周期性的任务执行)
5)newWorkStealingPool(int parallelism),Java 8 才加入这个创建方法,并行地处理任务,不保证处理顺序。
6)ThreadPoolExecutor():是最原始的线程池创建,上面1-3创建方式都是对ThreadPoolExecutor的封装。
spring bean 的生命周期
1.Spring 容器根据配置中的 bean 定义中实例化 bean。
2. Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。
3. 如果 bean 实现 BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用 setBeanName()。
4. 如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory()。
5. 如果存在与 bean 关联的任何 BeanPostProcessors,则调用 postProcessBeforeInitialization() 方法。
6. 如果为 bean 指定了 init 方法( 的 init-method 属性),那么将调用它。
7. 最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法。
8. 如果 bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。
9. 如果为 bean 指定了 destroy 方法( 的 destroy-method 属性),那么将调用它。
HashMap底层原理
HashMap实现Map接口,非线程安全的,允许使用null值和null键,不保证映射的顺序.底层数据结构是一个“数组+链表+红黑树“
volatile
保证可见性
禁止指令重排
单例模式的双重锁为什么要加volatile
指令重排(分配内存后执行设置instance指向刚分配的地址)导致a线程还未初始化对象,B线程判断instance不为null,返回一个未初始化的对象(synchronized并不能禁止指令重排和处理器优化)
在mybatis中#和$的主要区别是:#传入的参数在SQL中显示为字符串,#方式能够很大程度防止sql注入;$传入的参数在SqL中直接显示为传入的值,$方式无法防止Sql注入
脏读(读取未提交数据)
不可重复读(前后多次读取,数据内容不一致)
幻读(前后多次读取,数据总量不一致)
@Resource=@Autowired+@Qualifier
@Configuration+@Bean=@Component+xml
@RequestParam(value="aa") String inputStr =request.getParameter(“name”)
SpringMVC流程
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
mybatis的的一级缓存是SqlSession级别的缓存,一级缓存缓存的是对象,当SqlSession提交、关闭以及其他的更新数据库的操作发生后,一级缓存就会清空。二级缓存是SqlSessionFactory级别的缓存,同一个SqlSessionFactory产生的SqlSession都共享一个二级缓存,二级缓存中存储的是数据,当命中二级缓存时,通过存储的数据构造对象返回。查询数据的时候,查询的流程是二级缓存>一级缓存>数据库
parameterType:参数类型,只能传一个参数,如果有多个参数要封装,如封装成一个类,要写包名加类名,基本数据类型则可以省略
resultType 就是返回的类型
resultMap 返回的是一个结果集,这个结果集一般是用过resultMap节点来配置的,相应的type一般是一个Model。
而resultType则就是类型,包括了,int,sring,以及类似model这样的Object类型。
resultMap:适合使用返回值是自定义实体类的情况
resultType:适合使用返回值的数据类型是非自定义的,即jdk的提供的类型
#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值。
使用#{}可以有效的防止SQL注入,提高系统安全性。
Mapper 接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行MapperStatement所代表的sql,然后将sql执行结果返回。
数据库中每张表只能有一个聚集索引
innodb将通过主键聚集数据,如果没有定义主键,Innodb会选择第一个非空的唯一索引代替,如果没有非空唯一索引,Innodb会隐式定义一个6字节的rowid主键来作为聚集索引。innodb只聚集在同一个页面中的记录,包含相邻键值的页面可能会相距甚远。
BIO无法处理并发
socket.accept()会阻塞,socket.getInputStream().read(bytes);也会阻塞
SocketChannel可以设置为非阻塞serverSocketChannel.configureBlocking(false);
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(8080));
//设置为非阻塞
serverSocketChannel.configureBlocking(false);
一些常见的端口号及其用途如下:
21端口:FTP 文件传输服务
22端口:SSH 远程连接服务
23端口:TELNET 终端仿真服务
25端口:SMTP 简单邮件传输服务
53端口:DNS 域名解析服务
80端口:HTTP 超文本传输服务
443端口:HTTPS 加密的超文本传输服务
3306端口:MYSQL数据库端口
5432端口:postgresql数据库端口
6379端口:Redis数据库端口
8080端口:TCP服务端默认端口
8888端口:Nginx服务器的端口
9200端口:Elasticsearch服务器端口
27017端口:mongoDB数据库默认端口
22122端口:fastdfs服务器默认端口
子网掩码:子网掩码又叫网络掩码,是一个32位地址,用于屏蔽IP地址的一部分以区别网络号和主机标号,子网掩码——屏蔽一个IP地址的网络部分的“全1”比特模式。对于A类地址来说,默认的子网掩码是255.0.0.0;对于B类地址来说默认的子网掩码是255.255.0.0;对于C类地址来说默认的子网掩码是255.255.255.0
Status Code:200表示响应成功,很常见的一个状态
Status Code:301表示客户端跳转,永久性跳转
Status Code:302客户端跳转,临时性的跳转
status:304 304 表示资源未被修改。当不是第一次访问一个静态页面或者图片的时候,就会得到这么一个提示。这是服务端提示浏览器,这个资源没有发生改变,你直接使用上一次下载的就行了,不需要重新下载。 这样就节约了带宽,并且浏览器的加载速度也更快。
Status Code:404表示访问的页面不存在,表示一个浏览器的错误,就是服务端没提供这个服务,但是你却去访问。一般检查路径优先
Status Code:500表示服务端的错误
Status Code:100 表示继续
Status Code:401 表示未授权
Status Code:402 表示需要付费(很少见)
Status Code:403 表示禁止
Status Code:405 表示方法不被允许
Status Code:406 表示无法接受(很少见)
Status Code:408 表示请求超时
Status Code:413 表示实体过大(这个什么鬼)
Status Code:507 表示存储不足
偏向锁
偏向锁是Java 6之后加入的新锁,它是一种针对加锁操作的优化手段,经过研究发现,在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,因此为了减少同一线程获取锁(会涉及到一些CAS--Compare And Swap--比较并交换操作,耗时)的代价而引入偏向锁。偏向锁的核心思想是,如果一个线程获得了锁,那么锁就进入偏向模式,此时Mark Word 的结构也变为偏向锁结构,当这个线程再次请求锁时,无需再做任何同步操作,即获取锁的过程,这样就省去了大量有关锁申请的操作,从而也就提供程序的性能。所以,对于没有锁竞争的场合,偏向锁有很好的优化效果,毕竟极有可能连续多次是同一个线程申请相同的锁。但是对于锁竞争比较激烈的场合,偏向锁就失效了,因为这样场合极有可能每次申请锁的线程都是不相同的,因此这种场合下不应该使用偏向锁,否则会得不偿失,需要注意的是,偏向锁失败后,并不会立即膨胀为重量级锁,而是先升级为轻量级锁。
轻量级锁
倘若偏向锁失败,虚拟机并不会立即升级为重量级锁,它还会尝试使用一种称为轻量级锁的优化手段(1.6之后加入的),此时Mark Word 的结构也变为轻量级锁的结构。轻量级锁能够提升程序性能的依据是“对绝大部分的锁,在整个同步周期内都不存在竞争”,注意这是经验数据。需要了解的是,轻量级锁所适应的场景是线程交替执行同步块的场合,如果存在同一时间访问同一锁的场合,就会导致轻量级锁膨胀为重量级锁。
自旋锁
轻量级锁失败后,虚拟机为了避免线程真实地在操作系统层面挂起,还会进行一项称为自旋锁的优化手段。这是基于在大多数情况下,线程持有锁的时间都不会太长,如果直接挂起操作系统层面的线程可能会得不偿失,毕竟操作系统实现线程之间的切换时需要从用户态转换到核心态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,因此自旋锁会假设在不久将来,当前的线程可以获得锁,因此虚拟机会让当前想要获取锁的线程做几个空循环(这也是称为自旋的原因),一般不会太久,可能是50个循环或100循环,在经过若干次循环后,如果得到锁,就顺利进入临界区。如果还不能获得锁,那就会将线程在操作系统层面挂起,这就是自旋锁的优化方式,这种方式确实也是可以提升效率的。最后没办法也就只能升级为重量级锁了。
锁消除
消除锁是虚拟机另外一种锁的优化,这种优化更彻底,Java虚拟机在JIT编译时(可以简单理解为当某段代码即将第一次被执行时进行编译,又称即时编译),通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过这种方式消除没有必要的锁,可以节省毫无意义的请求锁时间,如下StringBuffer的append是一个同步方法,但是在add方法中的StringBuffer属于一个局部变量,并且不会被其他线程所使用,因此StringBuffser不可能存在共享资源竞争的情景,JVM会自动将其锁消除。
sleep()不释放同步锁,wait()释放同步锁.
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入(如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用),而@Resource默认按 byName自动注入罢了
当使用 context:component-scan 后,就可以将 context:annotation-config移除
生产者生产消息传送到队列,消费者从队列中拿取消息并处理,生产者不用关心是谁来消费,消费者不用关心谁在生产消息,从而达到解耦的目的。
singleton是默认的作用域,当定义Bean时,如果没有指定scope配置项,Bean的作用域被默认为singleton。singleton属于单例模式,在整个系统上下文环境中,仅有一个Bean实例。也就是说,在整个系统上下文环境中,你通过Spring IOC获取的都是同一个实例。
Spring IOC容器创建一个Bean实例时,可以为Bean指定实例的作用域,作用域包括singleton(单例模式)、prototype(原型模式)、request(HTTP请求)、session(会话)、global-session(全局会话)
Spring的自动装配原理:Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载,这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个JavaConfig形式的Spring容器配置类,通过@Bean导入到Spring容器中,以Properties结尾命名的类是和配置文件进行绑定的。它能通过这些以Properties结尾命名的类中取得在全局配置文件中配置的属性,我们可以通过修改配置文件对应的属性来修改自动配置的默认值,来完成自定义配置
Mybatis都有哪些Executor执行器?它们之间的区别是什么?
答:Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。
SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。
ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。
BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内。
Java的多线程中yield()方法的作用是放弃当前线程获取CPU的执行权,将让其它的线程去获取。但这个是不固定的,有可能刚放弃CPU的执行权,又被CPU执行了。
suspend(挂起)、resume(恢复)
Mybatis默认的事务管理器就是JDBC,连接池:POOLED
使用class文件绑定注册
接口和他的Mapper配置文件必须同名
接口和他的Mapper配置文件必须在同一个包下
KeySet():
将Map中所有的键存入到set集合中。因为set具备迭代器。所有可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。 keySet():迭代后只能通过get()取key
entrySet():
Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的 Set 视图。 Map.Entry表示映射关系。entrySet():迭代后可以e.getKey(),e.getValue()取key和value。返回的是Entry接口 。
Java中HashMap遍历几种方式
一、使用迭代器
第一种:
Map map = new HashMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue();
}
效率高
第二种:
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
Object key = iter.next();
Object val = map.get(key);
}
效率低
二、for each 遍历
第一种:
Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
map.get(key);
}
第二种:
Map<String, String> map = new HashMap<String, String>();
for (Entry<String, String> entry : map.entrySet()) {
entry.getKey();
entry.getValue();
}
盒子模型W3C、IE
W3C:width = content
IE: width = content+border+padding
大小都是content + border + padding + margin
@Param
基本类型的参数或String类型,需要加上
引用类型不需要加
只用一个基本类型,可以忽略
Sql中的引用即为@Param(“uid”)中设定的属性名
关联association 多对一
集合collection 一对多
javaType 用来指定实体类中属性的类型
ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
一级缓存:同一个用户查询同一个数据
二级缓存:
不同的mapper查出的数据会放在自己对应的缓存(map)中
只有会话提交,或者关闭的时候,才会提交到二级缓存中
对称加密算法主要有DES、TripleDES、RC2、RC4、RC5和Blowfish等六种
非对称加密算法主要有DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)
对称加密过程和解密过程使用的同一个密钥,加密过程相当于用原文+密钥可以传输出密文,同时解密过程用密文-密钥可以推导出原文。但非对称加密采用了两个密钥,一般使用公钥进行加密,使用私钥进行解密。
对称加密解密的速度比较快,适合数据比较长时的使用。非对称加密和解密花费的时间长、速度相对较慢,只适合对少量数据的使用。
对称加密算法安全性相对较低
非对称加密算法安全性较高
子类对象重写方法的访问权限必须大于等于父类对象方法的访问权限
HTTP协议中
OPTIONS:
HEAD:
GET:
POST:
PUT:
DELETE:
TRACE:
CONNECT:
https解决的问题
防监听
防伪装
防篡改
无法防止dns劫持
Timer和TimerTask的使用
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
log.e("time:");
}
}, 2000, 40);//2000表示第一次执行任务延迟时间,40表示以后每隔多长时间执行一次run里面的任务
ScheduledThreadPoolExecutor的使用
ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(2);
scheduled.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
loge("time:");
}
}, 0, 40, TimeUnit.MILLISECONDS);//0表示首次执行任务的延迟时间,40表示每次执行任务的间隔时间,TimeUnit.MILLISECONDS执行的时间间隔数值单位
间隔单位毫秒:TimeUnit.MILLISECONDS
间隔单位秒:TimeUnit.SECONDS
间隔单位分钟:TimeUnit.MINUTES
间隔单位小时:TimeUnit.HOURS
间隔单位天:TimeUnit.DAYS
过滤表情
.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "*")
provided不会把jar包打进去
项目的打包类型:pom、jar、war
packing默认是jar类型
ctrl+alt+o 去掉无用import
ctrl+alt+L 格式化
当使用 context:component-scan 后,就可以将 context:annotation-config移除。
1.网络层:路由器、防火墙
2.数据链路层:网卡、网桥、交换机
3.物理层:中继器、集线器
因为虚存= min(2^计算机位数, 内存+外存)
编译生成汇编代码,汇编对汇编代码进行处理,生成机器语言代码。
nginx反向代理
把静态请求交给nginx,动态请求,如jsp, servlet,ssm, struts等请求交给tomcat. 从而达到动静分离的效果。
所谓的动静分离就是指图片,css, js之类的都交给nginx来处理,nginx处理不了的,比如jsp 就交给tomcat来处理~
好处是nginx处理静态内容的吞吐量很高,比tomcat高多了,这样无形中提升了性能。
负载均衡的概念就是当访问量很大的时候,一个 Tomcat 吃不消了,这时候就准备多个 Tomcat,由Nginx按照权重来对请求进行分配,从而缓解单独一个Tomcat受到的压力
下载文件--TCP,聊天--UDP。
Comments | NOTHING