zl程序教程

您现在的位置是:首页 >  Java

当前栏目

Java面试常见题

2023-04-18 15:54:20 时间

一.面向对象

  1. 面向对象三大特性? 封装,继承,多态 多态: 继承 重写 父类引用指向子类对象
  2. 面向对象与面向过程区别? 面向对象是根据功能来划分模块,每一个对象的存在都是为了实现某个功能.面向过程是以步骤来划分模块。 假如用面向对象开发一个支付系统,支付系统可以调用用户系统,订单系统的功能与类,不会存在代码冗余。如果用面向过程来做,支付系统无法调用其他系统的类与功能代码块,开发过程较为复杂.
  3. 权限修饰符有效范围? public: 整个项目中可以调用 protected:被其修饰过的方法属性只能被他本身,或者他的子类访问. 缺省:同包可以访问 private:当前类可以访问
  4. 八种基本数据类型
    byte short int long float double char boolean

只听到从山间传来架构君的声音: 虎竹救边急,戎车森已行。有谁来对上联或下联?

  1. Java多线程工作原理? 多个线程“同时”运行只是我们感观上的一种表现。事实上线程是并发运行的,操作系统将时间划分为很多时间段,尽可能的均匀分配给每一个线程,获取到时间片的线程被CPU执行,其他则一直在等待。所以微观上是走走停停,宏观上都在运行。这种现象叫并发,但不是绝对意义上的同时发生。实则操作系统里面“同一时刻”只有一个线程在执行,但是处理速率快,效果上是并发运行。
  2. 创建线程的方式? 方式一:继承Thread类 方式二:实现runnable接口 方式三:实现callable接口 方式四:线程池ThreadPoolExcutor 方式五:
此代码由Java架构师必看网-架构君整理
    ExecutorService executorService = Executors.newCachedThreadPool(); 可缓存线程池
    ExecutorService executorService= Executors.newFixedThreadPool(3);  定长线程池
    ScheduledExecutorService ses= Executors.newScheduledThreadPool(3); 定时线程池
    ExecutorService executor = Executors.newSingleThreadExecutor();    单例线程池
  1. 线程生命周期? 无阻塞: 线程新建—>调用start方法到就绪阶段—> 得到cup分配的时间片运行阶段---->执行完后线程消亡状态 有阻塞: 线程新建—>调用start方法到就绪阶段—> 得到cup分配的时间片运行阶段---->遇到IO流阻塞或者sleep…sleep结束再次来到就绪阶段—>重复上述步骤
  2. ThreadPoolExcutor类?
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
1,2,5,TimeUnit.SECONDS,new LinkedBlockingDeque<Runnable>(3));
      /**
       * 第一个参数:   核心线程数
       * 第二个参数:   最大线程数
       * 第三个参数:   线程执行完任务后,多长时间销毁
       * 第四个参数:   时间单位
       * 第五个参数:   阻塞队列长度
       */
  1. 阻塞队列 先进后出,栈先进先出
  2. 时间复杂度 计算机科学中,算法的时间复杂度是一个函数,它定性描述了该算法的运行时间。
  3. IO流,序列化,反序列化 序列化:磁盘—>内存 反序列化:内存—>磁盘
  4. 网络编程套接字协议 TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)或插口。
  5. 集合分类?底层? 集合:collection ---- list set

List

ArrayList

linkedlist

vector

有序可重复

可变长度数组

双向链表

效率低弃用

Set

hashset

treeSet

无序不可重复

哈希表

实现comparable自然排序

数组+ 重写compareTo方法 链表+ 实现comparetor定制排序 二叉树 集合:Map:键值对

此代码由Java架构师必看网-架构君整理
  TreeMap    、 HashMap  、 HashTable
   Map.enrtySet 查询map中所有元素
  1. 反射 Class p= Class.forName(“全限定路径创建类”); p.newInstance(); ----得到people实例
  2. Mysql数据库,sql语言,DDL,DML,DQL,DCL 数据库定义语言,数据库操纵语言,数据库查询语言,数据库控制语言.
  3. 数据库事物特征与隔离级别 事物四大特性: (1) 原子性(Atomicity): 事物对数据的操作要么完全成功,要么失败回滚,事物不可分割. (2)一致性(Consistency) : 事务的一致性指的是在一个事务执行之前和执行之后数据库系统的数据是一致的。 (3)隔离性(Isolation): 一个事物执行不会被另一个事物干扰. (4)持久性(Durability): 事物一旦提交,持久化到数据库,不可回滚.

隔离级别: 设置事物隔离级别:

 set global  transaction isolation level repeatable-read;

查看:

select @@global.tx_isolation;

四种隔离级别:

read-uncommitted    -----  读未提交  问题:脏读       解决: ->
read-committed      -----  读已提交  问题:不可重复读 解决: ->    
repeatable-Read     -----  可重复读  问题:幻读       解决: ->
(锁了事物B读取事物的时间点)
Serializable        -----   串行化   问题:效率低   
(锁住了整张表)
  1. 存储过程 数据库服务运行后,在数据库所在的服务器的内存中开辟一块空间,里面存放的存储过程类似于java中的方法,里面可以包括逻辑和sql集合. 这个类似于java中的方法就可以成为存储过程. 我们程序员开发的时候,可以直接通过存储过程名去调用,省去了service 层的业务逻辑. 好处: 可以批量加工数据. 可以将应用程序代码逻辑放在数据库中直接调用. 客户端在与服务端交互只需要调存储过程名就OK,减少了网络流量. 在服务器内存中,不需要经过sql编译,运行效率高. 坏处: 需要消耗服务器内存. create producer 存储过程名(参数列表) begin end
  2. Sql优化 (1)sql语句:尽量别用 * , in ,或者like模糊查询,这种全表查询关键字 (2)加索引,一种是Btree,一种是hash. Btree底层是二叉树,hash底层是hash散列表. Sql:
ALTER  TABLE  `table_name`  ADD  INDEX index_name (  `column1`,  `column2`,  `column3`  )

(3)读写分离:数据库常用的引擎有两种,一种是Innodb,一种是Myisam. Innodb支持事物,但是事物只收到增删改影响,所以增删改时候,用引擎为Innodb的,查询的时候用MyIsam.

  1. jsp四大作用域,九大内置对象 JSP九大内置对象 request response session application out pageContext config page exception

四大作用域

page
request
session
application
  1. request,response? request:封装了所有请求信息; response:封装了所有响应信息;
  2. session,cookie? 1.cookie存放在前端,session存放在后端. 2.cookie由于是存在前端的,所以其安全性低于session. 3.session由于是一定时间在服务器上会占用你服务器的性能.考虑到减轻服务器性能方面,应当使用COOKIE 4.单个cookie保存的数据不能超过4k 5.将登陆信息等重要信息存放为SESSION,其他信息如果需要保留,可以放在COOKIE中
  3. Servlet声明周期? (1) 如果在web.xml中配置了自启动,此时声明周期为服务器开启,到服务器关闭. (2) 如果没有配置自启动,就是从servlet初始化,init方法,到服务器关闭.
  4. 解决乱码问题? 方式一:
req.setCharacterEncoding(“utf-8”);
resp.setCharacetEncoding(“utf-8”);
resp.setContentType(“text/html;charset=utf-8”);

简洁,但是不能解决get请求乱码问题. 方式二:

new String(xxx.getBytes(“Iso-8859-1”),”utf-8”);

方式复杂; 方式三:字符编码过滤器(最好)

	<!-- 字符编码过滤器 -->
	<filter>
		<filter-name>encoding</filter-name>		 <filter-class>
org.springframework.web.filter. CharacterEncodingFilter
</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encoding</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

第四种:在server.xml配置URIEncoding=utf-8.但是开发中,一定不会用第四种,因为你把服务器编码变了会影响其他人的编码格式.

  1. 前端html,重点form表单 表单校验
  2. Css选择器?样式?颜色调试 三种选择器:id , class ,标签。 与自身的style属性 优先级:自身的style属性大于>id>class>标签
Id: #div的 id { 
}
Class: .div的class{
}
Div{
}
  1. Javascript操作BOM,DOM,事件 JS:基于对象(不需要new,直接把对象拿来用)和事件驱动的一门语言,应用于客户端. 特点:交互性,安全性(js不能访问本地磁盘),跨平台性. Bom:把浏览器封装成一个对象,存在window对象中。 Dom:(标签,文本,属性,节点,全部封装成对象)然后通过操作节点操作html文档.根据html层级结构,在内存中给他分配一个树形结构,把标签,文本,节点,属性全部封装成对象.通过获取对象中的属性,来操作html文档. XML:解析技术dom,sax解析.约束:dtd,scheme
  2. jQuery jQuery选择器:
//id选择器        var inp=$("#uname");
//标签选择器     var inps=$("input");
//类选择器       var inps=$(".common");
//组合选择器:
function testAll(){
		var eles=$("h3,input");
		alert(eles.length);
}
//测试子选择器
	function testChild(){
		var inps=$("#showdiv>input");
alert(inps.length);
		}
//测试层级选择器
	function testCj(){
		var inp=$("input:first");
		alert(inp.val());
	}

jQuery操作元素属性

//获取元素对象
var uname=$("#uname");
//获取
alert(uname.attr("type")+":"+uname.attr("value")+":"+uname.val());

//jQuery操作元素内容
	//获取元素对象
		var showdiv=$("#showdiv");
	//获取元素的内容
		alert(showdiv.html());
		
	
	//修改元素内容
showdiv.html(showdiv.html()+
"<i>今天天气真好,适合抓鬼子</i>");
	
			
	//获取元素内容
	alert(showdiv.text());
	//修改元素内容
	showdiv.text("<i>今天天气真好,
适合抓鬼子</i>");
 jQuery操作表单: 
   //全选 
	$(function(){
	$("#btn1").click(function(){
});
})		
//反选
	$(function(){
$("#btn3").click(function(){				
	$("input[type='checkbox']").each(function(){
		$(this).prop("checked",!$(this).prop("checked"));
			})
		})					
	})
  1. Ajax和json,Ajax工作原理,json如何实现前后端传送数据? Ajax:异步请求,局部刷新. 传统的ajax原理: 1.创建xmlhttprequest对象(ajax引擎对象) 2.复写onreadystatechange 3.判断ajax状态码==4,响应状态码为200 4.获取响应数据 5.处理响应数据 但是开发中都用jQuery封装好的ajax:
$(function(){
$.ajax({
type:   请求方式,
url:    请求地址,
data:   发送数据,
async:  同步异步,
dataType: 返回数据类型,
jsonp:   
Jsonpcallback:
success:function(data){

},
error:function(){

}    })    })
$.getJSON("url", data:{ name: "John", time: "2pm" }, function(json){
  alert("JSON Data: " + json.users[3].name);
});
$.get("url",data { name: "John", time: "2pm" },
  function(data){
    alert("Data Loaded: " + data);
  },返回内容样式);
$.post("test.php", { name: "John", time: "2pm" },
   function(data){
     alert("Data Loaded: " + data);
   },返回内容样式);
$.getScript(url,data,success)

JSON用JackSon转换.(fastJson,Gson,@responseboby)

EasyUIDataGrid easyUIDataGrid = tbItemServiceImpl.show(page, rows);
ObjectMapper mapper = new ObjectMapper();
 String show = mapper.writeValueAsString(easyUIDataGrid);
return show;
  1. Mybatis工作原理? 在 MyBatis 运行时需要先加载全局xml配置文件与实例化 SqlSessionFactoryBuilder 构建器,用来实例化sqlSessionFactory工厂.在实例化sqlSessionFactory工厂之前,MyBatis底层会创建xml解析器,去解析全局配置文件流,解析完成后把结果封装在configuration对象中.然后在把configuration传递给工厂,由工厂实例化出sqlsession,接着sqlsesion会创建Excutor执行器.完成MyBatis对数据库的操作.
  2. spring中的IOC,AOP? 一.Spring实例化对象的三种方法: (1)默认通过无惨构造器 (2)有参构造器
<constructor-arg index="0" name="id" type="int"value="123" /> 

(3)实例工厂

<bea id="factory"class="com.bjsxt.pojo.PeopleFactory"></bean>
<bean id="peo1" factory-bean="factoryfactory-method="newInstance"></bean>

(4)静态工厂

<bean  id="peo2" class="com.bjsxt.pojo.PeopleFactory"factory-method="newInstance"></bean>

(5)基于注解 @Component —>然后用context命名空间去扫包

二.依赖注入 (1)通过property标签中的name和value (2)标签中的 value标签 (3)如果属性是List

<propertyname="list">
<list>
<value>1</value>
<value>2</value>
</list>
</property>

同理属性是数组 strs 属性是map:

<property name=map>
<map>
<entry key="a" value="b" >
</entry><entry key="c" value="d" >
</entry>
</map>
</property>
  1. java的垮平台原理 为什么要跨平台使用?其实说白了就是个操作系统支持的指令集是不一样的。我们的程序需要再不同的操作系统上运行这些代码。 但是不要说jvm是跨平台的,而真正跨平台的是 Java 程序,而不是 JVM。JVM 是用 C/C++ 开发的,是编译后的机器码,不能跨平台,不同平台下需要安装不同版本的 JVM 答:我们编写的 Java 源码,编译后会生成一种 .class 文件,称为字节码文件。Java 虚拟机(JVM)就是负责将字节码文件翻译成特定平台下的机器码然后运行,也就是说,只要在不同平台上安装对应的 JVM,就可以运行字节码文件,运行我们编写的 Java 程序。而这个过程,我们编写的 Java 程序没有做任何改变,仅仅是通过 JVM 这一 “中间层” ,就能在不同平台上运行,真正实现了 “一次编译,到处运行” 的目的。
  2. JVM由哪些部分组成? JVM 的结构基本上由 4 部分组成: 类加载器,在 JVM 启动时或者类运行时将需要的 class 加载到 JVM 中 执行引擎,执行引擎的任务是负责执行 class 文件中包含的字节码指令,相当于实际机器上的 CPU 内存区,将内存划分成若干个区以模拟实际机器上的存储、记录和调度功能模块,如实际机器上的各种功能的寄存器或者 PC 指针的记录器等 本地方法调用C 或 C++ 实现的本地,调用方法的代码返回结果
  3. 类加载器是有了解吗? 答:顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说, Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。 类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象
  4. Java 虚拟机是如何判定两个 Java 类是相同的? 答:Java 虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,被不同的类加载器加载之后所得到的类,也是不同的。比如一个 Java 类 com.example.Sample,编译之后生成了字节代码文件 Sample.class。两个不同的类加载器 ClassLoaderA和 ClassLoaderB分别读取了这个 Sample.class文件,并定义出两个 java.lang.Class类的实例来表示这个类。这两个实例是不相同的。对于 Java 虚拟机来说,它们是不同的类。试图对这两个类的对象进行相互赋值,会抛出运行时异常 ClassCastException。
  5. 双亲委派模型(Parent Delegation Model) 该模型要求除了顶层的 Bootstrap class loader 启动类加载器外,其余的类加载器都应当有自己的父类加载器。子类加载器和父类加载器不是以继承(Inheritance)的关系来实现,而是通过组合(Composition)关系来复用父加载器的代码。每个类加载器都有自己的命名空间(由该加载器及所有父类加载器所加载的类组成,在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类;在不同的命名空间中,有可能会出现类的完整名字(包括类的包名)相同的两个类)
  6. 双亲委派模型的工作过程?
  • 当前 ClassLoader 首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。 每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存, 等下次加载的时候就可以直接返回了。
  • 当前 ClassLoader 的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,一直到 bootstrap ClassLoader. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。
  • 为什么这样设计呢? 解析:这是对于使用这种模型来组织累加器的好处 答:主要是为了安全性,避免用户自己编写的类动态替换 Java 的一些核心类 同时也避免了重复加载,因为 JVM 中区分不同类,不仅仅是根据类名,相同的 class 文件被不同的 ClassLoader 加载就是不同的两个类,如果相互转型的话会抛java.lang.ClassCaseException. 装箱和拆箱:有了基本的数据类型,我们为什么还要有包装类型。 就是体现面向对象的思想 自动装箱是jdk1.5以后增加的功能。装箱:就是把基本数据类型转化成对应的包装类型。 总结一下:Java是一个面向对象的语言,而基本的数据类型,不具备面向对象的特性。
  1. Hashmap存储原理 API中的常用的属性 Hashmap、默认四个构造方法 Hash碰撞 ,桶的概念 Entry,next属性
  2. ArrayList 和LinkedList的区别 ArrayList底层使用的是数组,LinkedList底层使用的是链表 数组查询的时候具有查询特定元素比较快。而插入和删除和修改比较慢(数组在内存当中是一块联系的内存,如果插入或者删除是需要移动内存的) 链表不要求内存是连续的,当查询的时候,需要从头部一个一个的找,所以查询效率低,而插入的时候不需要移动内存,只需要改变引用的指向。 应用场景:ArrayList使用在查询比较多,答案是插入和删除比较少的情况,而LinkedList使用在查询比较少而插入和删除比较多的情况
  3. HashMap和HashTable的区别 相同点:都可以用来存储Key.value型数据 区别: 1、 hashMap是可以把null作为可以key或者value,而hashtable不可以 2、 HashMap是线程不安全的,效率较高,而hashtable是线程安全的,效率较低

三.spring,springmvc,MyBatis整合步骤

(1)在web.xml: 1.配置spring上下文参数contextConfigLocation —> classpath:applicationContex.xml 2.配置spring监听器 contextLoaderListener 3.配置dispatcherServlet前端控制器,配置cp下的:springmvc.xml 4.配置字符集编码过滤器 characterEncodingFilter (2)在applicationContext.xml中配置 1.注解扫描 context component-scan base-package= 2.加载属性文件context:property-placeholder location= 3.配置数据源驱动类,Druid —>数据库四个属性 4.配置sqlSessionFactoryBean —>引用dataSource数据源 5.配置MapperScannerConfigurer扫描器 6.配置事务管理器,声明式事务,aop

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" value="dataSource"></property>
</bean>
<!-- -->
<tx:advice id="advice" transaction-manager="txManager">
  <tx:attributes>
       <tx:method name="ins*" propagation="REQUIRED" rollback-for="java.lang.Throwable" />
       <tx:method name="del*"/>
       <tx:method name="upd*"/>
       <tx:method name="*" read-only="true" />
  </tx:attributes>
</tx:advice>
<!-- aop -->
<aop:config>
 <aop:pointcut expression="execution(* service.impl.*.*(..))" id="mypoint"/>
 <aop:advisor advice-ref="advice" pointcut-ref="mypoint"/>
</aop:config>

(3)在springmvc.xml中配置

<!-- 1.注解扫描 -->
<context:component-scanbase-package="controller">
<!-- 2.配置映射器与适配器 -->
<mvc:annotation-driven /> 
<!-- 3.放行静态资源 -->
<mvc:default-servlet-handler/>
<!-- 4.视图解析器 -->
<InternalResourceViewResolver ,MutipartResolver/>
  1. Springmvc运行原理? 首先,我们一般在web.xml中配置dispatchServlet对应的servlet-mapping中的url-pattern为/时.前端的请求分为两种,一种是对.jsp文件的请求,一种是对servlet的请求,当处理对.jsp的请求的时候,springmvc的前端控制器dispatchservlet不对其进行处理,直接跳转.当对非.jsp文件进行请求的时候,此时请求会进入springmvc的前端控制器dispatchservlet.然后由前端控制器dispatchserlvet调用HandlerMapping 的DefaultAnnotationHandlerMapping 解 析 URL,当解析完成调用handleAdapter前端适配器,为请求确定具体访问的服务器的某个方法,当方法操作完成后将结果反馈给视图解析器,视图解析器解析出具体的模型或者视图响应给用户.
  2. 版本控制工具,Svn和Git。 svn:灰色—>本地有,资源库没有 蓝色—>本地没有,资源库更新 红色—>本地和资源库冲突 解决办法: 第一 : 右键编辑冲突,这个时候你的代码和服务器代码不一样的地方就分别显示,你根据自己的需求在别人基础上进行增删,然后右键标记为处理完成. 第二 : 把你的代码和对方代码都copy到notpad,直接改,改完 提交覆盖. 事先和别人商量

git:

  1. 项目管理工具Mavan和Gradle?
  2. Redis数据库工作原理与集群部署? 单机版: 第一步,因为redis是c语言写的,我们服务器如果没有c语言编译环境的话.需要yum install gcc c++ -y 去在线安装C语言环境. 这里一定要注意,Linux系统的ip一定不能和主机共享ip,因为这样会造成网络资源冲突,下载失败,需要去DHCP中设置下网络适配模式.

第二步,使用filezila上传linux系统下的redis安装包,上传完成后 解压,然后复制文件到/usr/local下,改名叫redis

第三步,然后cd redis 进入redis解压后的文件夹去用make指令编译,编译完后直接make install安装.

第四步,然后我们进入bin目录启动redis.后把redis.conf文件拷贝到安装目录的redis的bin中.

第五步,开启redis.conf的守护进程.把 daemonize 由 no 修改成 yes.然后:wq.

第六步,再次启动redis服务./redis-server redis.conf

第七步,进入./redis-cli,redis客户端进行操作.

集群: 和单击步骤差不多,如果是伪集群.部署在同一台服务器上的话,需要把redis.conf中的端口改一下,开启守护进行,写批量自启动文件授权,3主3备模式,减小down机率.

  1. Dubbo工作原理?
  2. Linux系统中的基本操作,jdk安装环境变量配置,mysql,zookeeper,tomcat安装配置,与linux系统下的项目部署?
  3. 跨域请求的几种方式? HttpCilent对象 基于Ajax的Jsonp
  4. hibernate与mybatis差别
  5. Nginx
  6. Shiro Shiro是一个安全框架,他有两个作用,一个是认证,一个是授权. 认证: 如果用shiro,首先我们要在shiro的xml配置文件中去实例化,他的securityManage安全管理器,给安全管理器的realm和cacheManage缓存管理器引用自己配置的bean. 在自己配置的realm可以定义加密算法.在最后配置一个shiro自带的过滤器,这个过滤器的作用就是拦截请求,类似于MVC里面的拦截器. 然后他有个属性filterChainDefinitions,把需要认证访问的控制器或者视图url以/全路径的方式,/url=authc 代表认证后才可以访问,anno代表不认证也可以访问. 然后我们在自己写的realm中让他继承AuthorizingRealm,重写认证与授权的两个方法方法. 因为是我们自定义的realm,所以我们要把传入的令牌token转成我们认证方式用的token类型.然后我们将token对象中封装的用户名密码取出来,将认证信息return作为返回值,认证结束. 授权: 用户的权限封装在一个,PrincipalCollection类中,我们调用该类的getPrimaryprincipal方法获取授权主体对象. 在从数据库查这个人的角色,以及他的权限,然后我们给主体对象添加查出的权限,最后把认证主体return出给控制器,控制器根据return出的认证主体和他的权限,把用户的权限以视图方式响应给用户.
  7. Mycat
  8. 工厂设计模式 public class PeopleFactory { public People newInstance(){ return new People(1,“测试”); } }

43.乐观锁 一、乐观锁 总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。 version方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。 核心SQL代码: update table set x=x+1, version=version+1 where id=#{id} and version=#{version};

CAS操作方式:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。 一、悲观锁 总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁,在Java中,synchronized的思想也是悲观锁。

二. MySQL数据库

  1. 常用函数. SELECT COUNT(f_id) FROM fruits ---- COUNT 求列总数函数

SELECT SUM(f_price) FROM fruits ---- SUM 求和函数

SELECT AVG(f_price) FROM fruits ---- AVG求均值函数

SELECT MAX(f_price) FROM fruits ---- MAX求最大值函数

SELECT MIN(f_price) FROM fruits ---- MIN求最小值函数

  1. 外键 Constraint 外键名称 foreign key (cid) reference Clazz (cno)

修改表名: alter table 表名 rename 新的表名

添加字段: alter table 表名 add 字段名 数据类型 属性

修改表字段名: alter table 表名 modify 字段名 数据类型 列属性

删除表的字段: alter table 表名 drop column 列名

  1. 基础SQL 对于emp表查询工资2000到5000之间员工姓名,between…and… : select ename from emp where sal between 2000 and 5000

查询工作地点在纽约的员工姓名,部门编号,奖金(也有not in) select e.ename,e.deptno,e.sal from emp e,dept d where e.deptno=d.deptno and d.loc in (‘new york’)

查询姓名中含有A的员工姓名,经理名 select e.ename,d.ename from emp e,emp d where e.mgr=d.empno and e.ename like ‘%A%’

查询员工奖金不为空的员工姓名,奖金 select ename,comm from emp where comm is not null

查询部门编号大于10的所有员工信息 select * from emp where deptno >any(select deptno from dept where deptno>10);

4.distinct去重复关键字 例:查询emp表中所有job类型数量 select count(distinct job) from emp

5.order by 默认升序,DESC表降序 例如:查询有奖金的员工姓名,工资,按工资的降序排列 select ename,sal from emp where comm is not null order by sal desc (多个列之间也可以排序,order by sal,hiredate,comm…等) 6.Limit (放在order by 后) 查询员工表前五条记录: select * from emp limit 0,5

  1. join…on语句 查询员工姓名和部门所在名称: select e.ename,d.deptno from emp e join dept d on e.deptno= d.deptno
  2. 三表连接查询 查询每个员工的编号,姓名,工资,工资等级,所在工作城市,按照工资等级进行升序排列 select e.empno,e.ename,e.sal,s.greade from emp e join dept d on e.deptno=d.deptno join grade s on e.sal between s.losal and hisal order by s.grade
  3. group by分组查询 求各部门平均工资,按照部门进行分组 select deptno,avg(sal) from emp group by deptno;

求总的平均工资 select avg(sal) from emp

求每个部门工作类型和数量 select count(distinct job) from emp group by deptno

查询每个部门的部门编号,部门名称,部门人数,最高工资,最低工资,工 资总和,平均工资. select e.deptno,d.dname,count(e.empno),max(e.sal),min(e.sal) from emp e join dept d on e.deptno = d.deptno group by d.deptno

查询每个部门,每个岗位的部门编号,部门名称,岗位名称,部门人数,最高工资,最低工资,工资总和,平均工资. select e.deptno,d.dname,e.job,count(d.deptno),max(e.sal), min(e.sal),sum(e.sal),avg(e.sal) from emp e join dept d on e.deptno=d.deptno group by d.deptno

查询每个经理所管理的人数,经理编号,经理姓名,要求包括没有经理的人员信息.(左连接) select count(e.empno),m.empno,m.ename from emp e left join emp m on e.empno=m.empno group by e.mgr

10.having关键字排除分组结果 求每个组内最高薪水大约2900才输出. select max(sal) from emp group by deptno having max(sal)

2900

查询部门人数大于2的部门编号,部门名称,部门人数. select e.deptno,d.dname,count(e.empno) from emp e join dept d on e.deptno=d.deptno group by d.deptno having count(e.empno)>2

查询部门平均工资大于2000,且人数大于2的部门编号,部门名称,部门人数,部门平均工资,并按照部门人数升序排序.(order by 放最后) select d.deptno,d.dname,count(e.empno),avg(e.sal) from emp e join dept d on e.deptno=d.deptno group by d.deptno having avg(e.sal)>2000 and count(e.empno)>2 order by d.deptno

  1. 笛卡尔积 第一个表中所有行与第二个表中所有行都发生连接,查询出M*N条数据.
  2. 多表连接与非等值连接 (1)A.B.C三个表 :A表与B表有关联,B表与C表有关联. 查询员工的姓名,工资,工资等级. select e.ename,e.sal,s.grade from emp e join dept d on e.deptno=d.deptno join grade s on e.sal between s.losal and s.hisal

(2)查询每个员工的编号,姓名,工资,工资等级,所在工作城市,按照工资等级进行升序排列. select e.empno,e.ename,e.sal,s.grade,d.loc from emp e join dept d on e.deptno=d.deptno join grade s on e.sal between s.losal and s.hisal

三.JavaScript 43. Js和java不同 (1)Js可以声明同名变量,后面会覆盖前面的,不会报错. (2)Js中判断数据类型的关键字typeof,java里判断类型关键字instanceof. (3)Js中数据类型有6种,number|String|boolean|object|null|un Defined

  1. Js中的和= ==:判断的是值 ===:判断的是值和类型
  2. Js中数组的声明|赋值|取值|length|遍历 声明: var arr = new Array(); //声明一个空对象数组

var arr = new Array(length); //声明一个长度为length的数组

Js中不指定数组长度,数组长度不是固定的

赋值: 数组名[脚标]=值; //角标可以使任意正整数和0

取值: 数组名[角标] //返回当前脚标对应存储的值

遍历: (1) for( var i=0;i<arr.length;i++){ Alert(arr[i]); } (2)for-in: for(var i in arr){ alert(i); }

42.Js数组的常用操作 (1)数组的合并:arr.concat(b,c);

(2)数组的移除最后一个元素并返回:arr.pop();

(3)数组的追加:arr.push(“lol”);//追加元素也可以使一个数组

(4)数组移除第一个元素并返回:arr.shift();

(5)数组开始位置追加元素,并返回数组长度:arr.unshift(“又是要改bug了”);

(6)数组删除指定位置的元素:arr.splice(1,3,”a”); //把角标从1到3换成a

43.Js的函数的声明 (1)function test1(a1,a2){ alert(“函数声明一”); }

(2)var method = new function(“a1”,”a2”,”alert(‘函数声明方式二’)”);

(3)var test = function(a1,a2){ alert(“函数声明方式三”); }

44.函数返回值 var testReturn = function(){ alert(“函数返回值”); return “javascript”; } alert(testReturn());

  1. Js自定义对象 var obj=new Object(); obj.name=“张三”; obj.age=23; obj.test=function(){ alert(obj.name); alert(“我是obj”); return 112; } alert(obj.test); Js当中继承实现了数据共享,关键字是prototype

46.Js中的常用对象和方法 (1)字符串大小写转换: var str = new String(“abc”); str.toUpperCase; //将字符串转换为大写 str.toLowerCase; //将字符串转为小写

(2)字符串切割: var str = “a,b,c”; str.spilt(“,”); //按照指定的字符切割字符串, 返回值类型为数组. (3)字符串的截取: var str = “abcdef”; alert(s.substr(1,3)); //从指定位置开始截取指定长度字符串: bcd alert(s.substring(1,3)); //从指定开始位置和指定结束位 置截取字符串,区间[); 结果:bc

(4)查找字符串第一次出现的角标: var str = “abcdefg”; alert(str.indexOf(“dd”)); //返回子字符串第一次出现的角标, 若未找到返回-1 结果:-1

47.Js中的Date对象 (1)创建Date对象 var date = new Date(); alert(date); (2)Date对象中的常用方法 alert(d.getYear()); //返回的是1900年开始距今的年分数 alert(d.getFullYear()); //返回的是当前的年份 alert(d.getMonth()+1); //返回的当前月份的角标值,需要+1 alert(d.getDate()); //返回的是当前的日期数 alert(d.getDay()); //返回的是当前的星期数,但是周天会返回值为0; alert(d.getHours()); //返回当前时间的小时数 alert(d.getMinutes()); //返回当前时间的分钟数 alert(d.getSeconds()); //返回当前时间的秒数

48.Js中的Math对象 Math.random(); //返回0到1之间的数字

Math.floor(); //向下取整

Math.ceil(); //向上取整

Math.round(12.15) //四舍五入 12

Math.round(12.56) //四舍五入 13

Math.min(1,2,3) //取最小: 1

Math.max(1,2,3) //取最大值: 3

49.Js中的事件 一.鼠标事件 (1)单击事件:onclick 鼠标单击的时候会触发

(2)双击事件:ondbclick 鼠标双击的时候会触发

(3)鼠标悬停在某个html元素上触发:onmouseover

(4)鼠标移出某个html元素后触发:onmouseout

二.键盘事件

(1)当键盘在某个html元素上弹起的时候触发onkeyup

(2)当键盘在某个html元素下压的时候触发onkeydown

三.焦点事件与页面加载事件

(1)当某个html元素获取焦点的时候触发:onfocus

(2)当某个html元素失去焦点的时候触发:onblur

(3)页面渲染完成后触发: onload

Js触发事件驱动的两种方法: 第一种:在html元素的属性标签上,加入事件名称,事件名称等于监听函数名称.一旦触发事件调用定义的函数. 第二种:通过DOM获取元素,然后对元素进行操作与事件绑定,触发函数.

50.BOM 浏览器对象模型 (1)浏览器对象模型:是规范浏览器对JS语言的支持.

BOM封装在window对象中.

Window关键字不需要new,也可以省略.

(2)window对象中的常用方法:

一.框体方法 1.alert(); 警告框 2.confirm(‘确认提交?’); 确定框 确定,返回true; 取消,返回false; 3.prompt(); 提示框 写完后输出写入的值

二.定时器方法

  1. setTimeout:指定的时间后执行指定的函数 参数1:函数对象 参数2:时间,单位毫秒。 返回值:返回当前定时器的id 2.setInterval:每间隔指定的时间执行指定的函数 参数1:函数对象 参数2:时间,单位毫秒。 返回值:返回当前间隔器的id 3.clearTimeout:用来停止指定的定时器 参数:定时器的id clearInterval:用来停止指定的间隔器 参数: 间隔器的id 4.clearInterval:用来停止指定的间隔器 参数:间隔器的id

三.window对象的常用属性方法 1.window.open(‘子资源相对路径’,’打开方式’,’配置’);

function testOpen(){
window.open('son.html','newwindow',
'height=400, width=600, top=100px,left=320px, toolbar=yes, menubar=yes, scrollbars=yes, resizable=yes,location=no, status=yes');
}

2.window.location.href=”www.baidu.com”; 跳转到百度 3.window.location.reload(); 重新加载页面资源 4.window.history.forward(); 跳转到历史页面 5.window.history.go(1); 跳转到刚才访问第一次的页面 6. 屏幕属性

var x=window.screen.width;    //屏幕宽
var y=window.screen.height;    //屏幕高
  1. 浏览器配置
window.navigator.userAgent;

51.DOM 文档对象模型 (1)document对象的概念: 浏览器对外提供的支持js的用来操作HTML文档的一个对象,此对象封存的HTML文档的所有信息. HTML文档的所有信息都封装在Document对象中. (2) 使用document获取HTML元素 直接获取: 通过id , 通过name , 通过标签名(返回数组),通过class 1.id方式获取:var html = document.getElementById(元素id名); alert(html); 结果是标签名称 2. name方式获取: — 返回是数组

var html =document.getElementsByName(元素name值);
  1. TagName方式获取: — 返回是数组
var html = document.getElementsByTagName(标签名);
  1. className方式获取:
var html = document.getElementByClassName(元素class属性值);

间接获取: 父子节点,兄弟节点,子父节点 1.通过父标签获取子节点标签

 //获取父标签
   var fbq =document.getElementById(父标签的名称);
       //通过父标签获取父标签的子节点 --- 返回数组
      var zjd = fbq.childNodes;
      //输出子节点长度
      alert(zjd.length);
      //遍历子节点数组
      for (var i in zjd){
 alert(zjd[i].value);
}

2.通过子节点标签获取父节点标签

//获取子节点标签
var  child = document.getElementById(子节点id);
//通过子节点获取父标签
var  parent = child.parentNode;
alert(parent);	

3.通过兄弟节点获取

//获取子根节点
var brother = document.getElementById(子根节点);
//获取上一个节点
var top =  brother.previousSubling;
//获取下一个节点
var  after = brother.nextSubling;

52.Js操作html元素属性. (1) 获取元素对象:

var uname =document,getElementById(“uname”);

获取元素属性值:

uname.type   ----  获取元素类型
uname.name   ----  获取元素name属性值
uname.id     ----  获取元素id属性值
uname.value  ----  获取元素value属性值

修改元素属性值:

 uname.value= 123;
 uname.type = “button”;

(2)

<input type="text" name="username" id="uname" value="123" abc="嘿嘿"/>
获取元素对象:
      var  htmlInp = document.getElementById(“username”);
获取元素属性值:
    htmlInp.getAttribute(“abc”);
修改元素属性值(自定义):
       htmlInp.setAttribute(“abc”,”呵呵”);
获取标签属性值(非自定义):
       htmlInp.getAttribute(“type”);
       htmlInp.getAttribute(“value”);

53.Js操作html元素内容 (1)

//获取元素  --- 对象!
var  div = document.getElementById(“div01”);
//获取元素  --- 内容!
     div.innerHTML    ----  输出元素内容包含html标签
     div.innerText    ----  输出元素内容不包含html标签
//修改元素内容:
     div.innerHTML=”<b>innerHTML内容修改</b>”
     ----  innerHTML 会解析html标签,字体加粗
//修改元素内容:
     div.innerText=“<b>innerText内容修改</b>”
     ----  innerText不会解析html标签,把<b>标签直接输出

54.Js操作元素样式 (1)获取元素对象

var showdiv = document.getElementById(“showdiv”);

(2)添加元素样式

showdiv.style.backgroundColor="#FFA500";
//修改元素样式
showdiv.style.border="solid 2px red";
//删除元素样式
showdiv.style.border="";

55.Js操作文档结构 (1)removeChild(子DIV名称)

function delInp(btn){
//获取父级div
var showdiv=document.getElementById("showdiv");
//获取要删除的子div
var cdiv=btn.parentNode;
//父div删除子div
showdiv.removeChild(cdiv);
}

(2)appendChild(追加标签名称)

//获取元素对象
var  showdiv=document.getElementById("showdiv");
//创建input标签
//创建input元素对象
var inp=document.createElement("input");
//给标签属性赋值
inp.type="file";
//创建按钮元素对象
var btn=document.createElement("input");
btn.type="button";
btn.value="删除";
btn.onclick=function(){
					showdiv.removeChild(inp);
					showdiv.removeChild(btn);
					showdiv.removeChild(br);
}
//创建换行符
var br=document.createElement("br");
//将创建的元素对象存放到div中
showdiv.appendChild(inp);
showdiv.appendChild(btn);
showdiv.appendChild(br);	
}

56.Js操作form (1)获取form对象

var from = document.getElementById(表单id);

(2)form常用方法

from.submit();    ----   提交表单
form.reset();     ----   重置表单

(3) form.action=www.baidu.com ----操作form属性 (4) disabled=”disabled” ----不可操作,数据不提交 (5) readonly=”readonly” ----不可操作,数据可提交

57.Js操作全选,反选 (1)获取多选元素对象数组

 var  favs = document.getElementsByName(“fav”);
//遍历数组,如果被选中则alert
for(var i in favs){
	if(favs[i].checked){							
	    alert(i+favs[i].checked); 
	}								
}
//全选
var fav = document.getElementsByName(“fav”);
for(var i in fav){
  fav[i].checked = true;
}
//全不选
var fav = document.getElementsByName(“fav”);
for(var i in fav){
  fav[i].checked = true;
}
//反选
var fav = document.getElementsByName(“fav”);
for(var i in fav){
  fav[i].checked = ! fav[i].checked;
}

58.Js操作下拉框

function testSel(){
//获取下拉框对象
var sel=document.getElementById("address");
//获取下拉框对象属性值
var os=sel.options;
	for(var i=0;i<os.length;i++){
     //判断是否被选中
	     if(os[i].selected){
			alert(os[i].value+":"+os[i].text);
	     }
	}
}

59.Js校验表单

<script type="text/javascript">
	//常见验证码
	function createCode(){
	//创建随机四位数字
	var code=Math.floor(Math.random()*9000+1000);
	//获取元素对象
	var span=document.getElementById("codeSpan");
	//将数字存放到span中
	span.innerHTML=code;					
	}
//验证用户名
function checkUname(){
	//获取用户的用户名信息
var uname=document.getElementById("uname").value;
	//创建校验规则
			var reg=/^[u4e00-u9fa5]{2,4}$/
	//获取span对象
	var span=document.getElementById("unameSpan");
	//开始校验
	if(uname=="" || uname==null){
//输出校验结果
	span.instylenerHTML="用户名不能为空";
	span.color="red";
	return false;
}else if(reg.test(uname)){
	//输出校验结果
span.innerHTML="用户名ok";
	 span.style.color="green";
	 return true;
}else{
	 //输出校验结果
	span.innerHTML="用户名不符合规则";
	span.style.color="red";
	return false;
			}
	}
//验证密码
	function checkPwd(){
//获取用户的密码信息
	var pwd=document.getElementById("pwd").value;
	//创建校验规则
	var reg=/^[a-z]w{5,7}$/;
	//获取span对象
	var span=document.getElementById("pwdSpan");
	//开始校验
	if(pwd=="" ||pwd==null){
	//输出校验结果
	span.innerHTML="*密码不能为空";
	span.style.color="red";
	return false;
	}else if(reg.test(pwd)){
	//输出校验结果
	span.innerHTML="*密码ok";
	span.style.color="green";
	return true;
}else{
	//输出校验结果
span.innerHTML="*密码格式不正确";
span.style.color="red";
return false;
	}
checkPwd2();
}
//校验确认密码
function checkPwd2(){
//获取第一次密码
var pwd=document.getElementById("pwd").value;
//获取确认密码
var pwd2=document.getElementById("pwd2").value;
//获取span对象
var span=document.getElementById("pwd2Span");
	//比较两次密码是否相同
	if(pwd2==""||pwd2==null){
	span.innerHTML="确认密码不能为空";
	span.style.color="red";
	return false;
	}else if(pwd==pwd2){
	span.innerHTML="确认密码ok";
	span.style.color="green";
	return true;
}else{
	span.innerHTML="两次密码不一致";
	span.style.color="red";
	return false;
	}
				}
//校验手机号
function checkPhone(){
return checkField("phone",/^1[3,4,5,7,8]d{9}$/);
}
//校验邮箱
function checkMail(){
    return checkField("mail",/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+$/ )
					
}
		
}
//封装校验:相同的保留,不同的传参。
	function checkField(id,reg){
	//获取用户数据			
var inp=document.getElementById(id);
	 var va=inp.value	
 	 var alt=inp.alt;
//创建校验规则
//获取span对象
var span=document.getElementById(id+"Span")
	//开始校验
if(va=="" ||va==null){
	//输出校验结果
	span.innerHTML=alt+"不能为空";
	span.style.color="red";
	return false;
}else if(reg.test(va)){
//输出校验结果
span.innerHTML=alt+"ok";						
span.style.color="green";
	return true;
	}
else{
	//输出校验结果
	span.innerHTML=alt+"不符合规则";						
	span.style.color="red";
		return false;
		}
	}