Java个⼈技术知识点总结(业务场景篇)
业务场景篇
Spring的概述
Spring是完全⾯向接⼝的设计,降低程序耦合性,主要是事务控制并创建bean实例对象。在ssh整合时,充当黏合剂的作⽤。
IOC(Inversion of Control) 控制反转/依赖注⼊,⼜称DI(Dependency Injection) (依赖注⼊)
IOC的作⽤:产⽣对象实例,所以它是基于⼯⼚设计模式的
Spring IOC的注⼊
通过属性进⾏注⼊,通过构造函数进⾏注⼊,
注⼊对象数组注⼊List集合
注⼊Map集合 注⼊Properties类型
Spring IOC⾃动绑定模式:
可以设置autowire按以下⽅式进⾏绑定
按byType只要类型⼀致会⾃动寻,
按byName⾃动按属性名称进⾏⾃动查匹配.
AOP⾯向⽅⾯(切⾯)编程
AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是⾯向⽅⾯(切⾯)编程。
注:OOP(Object-Oriented Programming )⾯向对象编程
AOP主要应⽤于⽇志记录,性能统计,安全控制,事务处理(项⽬中使⽤的)等⽅⾯。
Spring中实现AOP技术:
在Spring中可以通过代理模式来实现AOP
代理模式分为
静态代理:⼀个接⼝,分别有⼀个真实实现和⼀个代理实现。
动态代理:通过代理类的代理,接⼝和实现类之间可以不直接发⽣联系,⽽可以在运⾏期(Runtime)实现动态关联。
动态代理有两种实现⽅式,可以通过jdk的动态代理实现也可以通过cglib来实现⽽AOP默认是通过jdk的动态代理来实现的。jdk的动态代理必须要有接⼝的⽀持,⽽cglib不需要,它是基于类的。
Spring AOP事务的描述:
在l⾥通过<aop:config>⾥⾯先设定⼀个表达式,设定对service⾥那些⽅法 如:对add* ,delete*,update*等开头的⽅法进⾏事务拦截。我们需要配置事务的传播(propagation="REQUIRED")特性,通常把增,删,改以外的操作需要配置成只读事务(read-only="true").只读事务可以提⾼性能。之后引⼊tx:advice,在tx:advice引⽤ transactionManager(事务管理),在事务管理⾥再引⼊sessionFactory,sessionFactory注⼊ dataSource,最后通过<aop:config> 引⼊txAdvice。
Spring实现ioc控制反转描述:
原来需要我们⾃⼰进⾏bean的创建以及注⼊,⽽现在交给spring容器去完成bean的创建以及注⼊。
所谓的“控制反转”就是 对象控制权的转移,从程序代码本⾝转移到了外部容器。
官⽅解释:
控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调⽤权交给容器,通过容器来实现对象组件的装配和管
事务概述
事务概述 √
在数据库中,所谓事务是指⼀组逻辑操作单元即⼀组sql语句。当这个单元中的⼀部分操作失败,整个事务回滚,只有全部正确才完成提交。事务的ACID属性
1.原⼦性(Atomicity)
原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都不发⽣。
2.⼀致性(Consistency)
事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。(数据不被破坏)
3.隔离性(Isolation)
事务的隔离性是指⼀个事务的执⾏不能被其他事务⼲扰.
4.持久性(Durability)
持久性是指⼀个事务⼀旦被提交,它对数据库中数据的改变就是永久性的.即使系统重启数据也不会丢失;在JDBC中,事务默认是⾃动提交的,每次执⾏⼀个SQL语句时,如果执⾏成功,就会向数据库⾃动提交,⽽不能回滚
为了让多个SQL语句作为⼀个事务执⾏:
(1)执⾏语句前调⽤ Connection 对象的 setAutoCommit(false);
以取消⾃动提交事务
(2)在所有的 SQL 语句都成功执⾏后,调⽤ commit(); ⽅法提交事务
(3)在出现异常时,调⽤ rollback(); ⽅法回滚事务。
权限概述
权限涉及到5张表:
⽤户表,⾓⾊表,权限表(菜单表),⽤户⾓⾊关联表,⾓⾊权限关联表
当⽤户登录时,根据⽤户名和密码到⽤户表验证信息是否合法,如果合法则获取⽤户信息,之后根据⽤户id再到⽤户⾓⾊关联表中得到相关连的⾓⾊id集合,之后根据⾓⾊id再到⾓⾊权限关联表中获取该⾓⾊所拥有的权限id集合,然后再根据权限id集合到权限表(菜单表)中获取具体的菜单,展现给当前登录⽤户,从⽽达到不同⽤⽤户看到不同的菜单权限。
我们通过ZTree来给⾓⾊赋权并且通过ZTree来展⽰菜单,以及通过ZTree来管 理菜单即增加和编辑菜单。
我们做的权限控制到url级别,为了防⽌⽤户不登录直接输⼊url访问的这个弊端,通过进⾏拦截验证。
OSCache业务场景
在我以前的项⽬中,我们考虑了系统性能问题,这个时候我们采⽤了Oscache缓存,刚开始把这个功能交给了项⽬组中的另外⼀个同事来做的,但是他做完的时候他发现缓存中明明已经缓存了数据,但是在取得时候发现没有数据,我们项⽬经理让我去帮忙看看这个问题,我阅读完他的代码之后,我发现了他每次缓存的时候都是调⽤⼀个新的缓存对象的⽅法,结果出现了明明已经⾛了缓存的⽅法⽽取
不到数据的问题,通过我多年的⼯作经验,我就想到了应该⽤单例模式去封装⼀个单例⼯具类来调⽤oscache。但是,在后来的测试过程中,发现当并发访问的时候也会出现上述的问题,这个时候我直接采取的DCL(双重判定锁)单例模式封装了⼯具类,既解决了线程安全问题,相对的性能问题也考虑到了,这个问题才得到了完善的解决。
线程概述
1、新建状态(New):新创建了⼀个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调⽤了该对象的start()⽅法。该状态的线程位于可运⾏线程池中,变得可运⾏,等待获取CPU的使⽤权。
3、运⾏状态(Running):就绪状态的线程获取了CPU,执⾏程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使⽤权,暂时停⽌运⾏。直到线程进⼊就绪状态,才有机会转到运⾏状态。阻塞的情况分三种:
(⼀)、等待阻塞:运⾏的线程执⾏wait()⽅法,JVM会把该线程放⼊等待池中。
(⼆)、同步阻塞:运⾏的线程在获取对象的同步锁时,若该同步锁被别的线程占⽤,则JVM会把该线程放⼊锁池中。
(三)、其他阻塞:运⾏的线程执⾏sleep()或join()⽅法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终⽌或者超时、或者I/O处理完毕时,线程重新转⼊就绪状态。
5、死亡状态(Dead):线程执⾏完了或者因异常退出了run()⽅法,该线程结束⽣命周期。
实现线程的两种⽅式:
是继承Thread类或实现Runnable接⼝,但不管怎样,当new了这个对象后,线程就已经进⼊了初始状态
wait和sleep的区别:
线程访问:
锁池状态,之后等待锁释放,然后访问代码
wait
等待队列(释放资源)--->调⽤notify或者notifyall之后锁池状态--->( 等待锁释放)--->可运⾏状态--->运⾏状态---->访问代码
sleep,join
不释放资源-->结束后直接进⼊可运⾏状态--->运⾏状态---->访问代码
⼀个java控制台程序,默认运⾏两个线程,⼀个主线程,⼀个垃圾回收线程。
线程与进程的区别:
1.线程(Thread)与进程(Process)
进程定义的是应⽤程序与应⽤程序之间的边界,通常来说⼀个进程就代表⼀个与之对应 的应⽤程序。不同的进程之间不能共享代码和数据空间,⽽同⼀进程的不同线程可以共 享代码和数据空间。
2.⼀个进程可以包括若⼲个线程,同时创建多个线程来完成某项任务,便是多线程。
Ajax请求Session超时问题
我在做项⽬时有时会遇到session超时问题,如果session超时,平常请求没有什么问题,通过可以正确跳到登陆页⾯,可是你如果⽤ajax请求的话这就出现问题了,因为ajax是异步的,局部刷新,所以登陆界⾯不会再全页⾯中显⽰,他只会显⽰到页⾯的⼀部分当中。所以根据我这⼏年的经验到了我认为⽐较好的⼀种⽅法。因为那我⽤的框架是和struts2集成的,所以就在中进⾏设置:
⾸先判断session是否为空就是判断session是否超时,如果超时就取出请求的head头信息Header("x-requested-with"),如果不为空就和XMLHttpRequest(Ajax标识)进⾏⽐较 (Header("x-requested-
with").equalsIgnoreCase("XMLHttpRequest"))) 如果相等说明此请求是ajax请求。
如果是ajax请求就可以⽤response.setHeader("键","值")来设置⼀个标识来告诉⽤户这是ajax请求并且session超时时发出的,这样我就可以在回调函数中取出⾃⼰设置的那个唯⼀标识:ResponseHeader("");如果取出的值是和⾃⼰在后台中设置的值⼀样的话,就证明session已经超时,这样就可以设置place("登陆界⾯"),来跳转到登陆界⾯了。
这样做虽然解决了问题,但是,会在每个回调函数中写⼊那些代码,这样的话代码就会显得特别零散,所以就想能不能定义⼀个全局的设置
我做项⽬时还⽤到$(document).ajaxStart(),这是ajax请求时的事件;$(document).ajaxSuccess(),这是AJAX请求成功后的事件。我⼀般⽤他们来显⽰遮罩层和隐藏遮罩层⽤的加遮罩层是为了不让⽤户重复提交,更提⾼了⽤户体验度,让⽤户知道已经提交了。
java线程池概述
java线程池的⼯作原理和数据库连接池的差不多,因为每次重新创建线程都是很耗资源的操作,所以我们可以建⽴⼀个线程池,这样当需要java
⽤到线程进⾏某些操作时,就可以直接去线程池⾥⾯到空闲的线程,这样就可以直接使⽤,⽽不⽤等到⽤到的时候再去创建,⽤完之后可以把该线程重新放⼊线程池供其他请求使⽤从⽽提⾼应⽤程序的性能。
线程池的核⼼流程:
1.构建⼀个 ThreadPoolExecutor 并指定默认要创建的线程的数量
2.通过 ute()
去添加⼀个个要执⾏的线程即实现了Runable接⼝的java类
3.在实现了Runable接⼝的java类的run⽅法中写⼊具体的业务代码
:
线程池的业务场景
线程池的业务场景:
我在⼯作的时候,当时⼀个同事给我提了⼀个需求,⽬前有⼤量的图⽚需要处理⽣产缩略图并进⾏加⽔印,因为按照普通的处理⽅法⼀个个的进⾏处理太慢了,问我有没有好的解决⽅案,这个时候我就想到了java中的线程池,我构建了⼀个线程数为5个线程池,然后采⽤分段批量提取的⽅式每500条为⼀组数据进⾏图⽚信息的提取,然后再把这些通过Threadpool的execute⽅法交给线程池中的线程进⾏处理,即充分使⽤CPU硬件资源⼜加快了⼤数据情况下程序的处理效率。
我当时在⼯作的过程中,认识⼀个做电商的朋友,他们当时公司才起步,很多技术都不成熟,所以就常常和我探讨⼀些技术问题,有次他向我请教⼀个问题,问我如何才能提⾼⽹站的性能,我根据⾃⼰在项⽬中的经验以及⾃⼰以前阅读的关于优化⽅⾯的资料给他提出了很多建议,如⽤lucene进⾏全⽂检索,⽤memcached进⾏分布式缓存,以及通过spring定时器结合freeMarker模板引擎来⽣成静态页⾯,由于要⽣成的页⾯的数量⽐较多,考虑到程序的性能,我建议他结合java的线程池进⾏⼯作,这样就可以充分使⽤了CPU硬件资源⼜加快了⼤数据情况下程序的处理效率。
如果你依然觉得有些茫然,不如加⼊我的Java架构师之路:766529531 跟有多年Java开发经验的资深⼯程师聊⼀聊。也可获取免费的视频学习资料以及电⼦书学习资料喔!
OSCache概述
oscache是⼀个⾼性能的j2ee框架,可以和任何java代码进⾏集成,并且还可以通过标签对页⾯内容进⾏缓存,还以缓存请求。我们通常将那些频繁访问但是⼜不是经常改变的数据进⾏缓存。为了保证缓存数据的有效性,在数据发⽣改变的时候,我们要刷新缓存,避免脏数据的出现。刷新缓存的策略有两种,⼀种是定时刷新,⼀种⼿动刷新。缓存数据的时机通常也分为两种,即在tomcat(web容器)启动时候加载数据进⾏缓存,另外也可以在⽤户第⼀次访问数据的时候进⾏缓存,这个相当于缓存的⽴即加载和按需加载。
缓存的层次如下:jsp-->action-->service-->dao,缓存越靠前对性能的提升越⼤,⼀个action⾥⾯可以有多个service,⼀个service中可以有多个dao或者多个service,任何类之间都可以进⾏相互调⽤,可以通过构造函数传参,set,get传参或者是⽅法传 参将相关的类连接起来。OSCache+autocomplete+单例业务场景
在我以前做某项⽬的过程中,其中我们在做产品列表的查询的时候为了提⾼⽤户的体验度,我们使⽤了autocomplete插件来代替select进⾏品牌的选择,才开始的时候每次都要根据⽤户输⼊的信息去查询数据库进⾏模糊匹配返回结果,后来我们考虑到系统的性能,因此我们采⽤了oscache缓存,才开始这个功能是交给我们项⽬组中的另外⼀个同事来做的,但是他做完后,我们在使⽤这个⼯具类的时候,发现有时缓存中明明已经有时我们需要的数据,但是从缓存⾥⾯取的时候,发现没有,之后项⽬经理让我去帮这个同事看看这个问题,我经过阅读他的代码发现,它⾥⾯在使⽤缓存的时候,针对于
每次⽅法的调⽤都产⽣⼀个新的实例,结果导致了上⾯的问题,这个时候我想起了可以使⽤设计模式中的单例模式来解决这个问题,才开始我直接采⽤了普通的单列模式,但是后来在测试的过程中,发现当⽤户并发量⼤的时候还是会出现上⾯的问题,之后我再次考虑了代码,最后发现是因为没有给单列模式加锁的原因,从⽽导致了⼤⽤户并发的时候,线程安全的问题,之后我便在⽅法上加上了synchronized关键字,解决上述的问题,但是后来测试⼈员反馈,觉的这段的性能有问题,我考虑之后便采⽤在⽅法体内加锁并结合双重判定的⽅式解决了上⾯的问题。我们是将数据在tomcat启动的时候加载到缓存中,之后⽤户进⾏查询的时候直接从缓存中获取数据,根据前缀匹配进⾏查询,将结果返回给⽤户。这样在提⾼⽤户体验度的同时也提⾼性能。
java学习资源应⽤程序为了提⾼性能,可以通过使⽤缓存来达到⽬的,缓存的存储介质可以内存或者硬盘,通常将数据存储在内存⾥,确切的说是jvm的内存中,缓存是基于Map这种思想构建的,以键值对的⽅式进⾏存取,之所以还可以将缓存的数据存储在硬盘中,是因为内存资源相当有限和宝贵,所以当内存资源不⾜的时候,就可以将其存储到硬盘中,虽然硬盘的存取速度⽐内存要慢,但是因为减少了⽹络通信量,所以还是提⾼程序的性能。缓存可以分为客户端缓存和服务器端缓存,所谓的客户端缓存通常指的是IE浏览器的缓存,服务器端缓存指的web服务器的缓存,通常可以通过第三⽅组件实现,如oscache,memcache
我们通常将那些频繁访问但是⼜不是经常改变的数据进⾏缓存。为了保证缓存数据的有效性,在数据
发⽣改变的时候,我们要刷新缓存,避免脏数据的出现。刷新缓存的策略有两种,⼀种是定时刷新,⼀种⼿动刷新。
缓存的层次如下:jsp-->action-->service(通常放置在service)-->dao,缓存越靠前对性能的提升越⼤
缓存的策略:(缓存空间不⾜需要进⾏清理的时候使⽤)
LRU:最近最少使⽤原则.(理解:存储书)
FIFO:先进先出的缓存策略.(理解:排队)
你来说说缓存?说说你对缓存的理解(如果遇到重复的,就可以省略)
我们在项⽬中使⽤缓存的⽬的是为了提⾼应⽤程序的性能,减少访问数据库的次数,从⽽提⾼应⽤程序的吞吐量。我们通常将权限,菜单,组织机构这些频繁访问但是不经常改变的基础数据进⾏缓存,其中我在做()某某项⽬的时候就通过oscache对ZTree的树形菜单进⾏了缓存,并且在做的时候和单列设计模式进⾏结合,考虑到多线程下的安全问题,还对单例模式加⼊了双重判定锁的检查⽅式。
实现页⾯静态化业务场景
我们在做某项⽬时,涉及到程序访问的性能问题,这时候我们想到可以通过静态化来提⾼⽤户访问时候的性能,所以我们就采⽤了freemarker模板引擎,考虑到页⾯也是要有动态的变化的,所以我们采⽤spring定时器在每天晚上2点钟的时候定时再次⽣成html静态页⾯,考虑发布时候的性能问题,我们⼜采取线程池技术,让多个线程同时发布,从⽽缩减发布时间。
servlet线程安全描述
servlet是单列的,对于所有请求都使⽤⼀个实例,所以如果有全局变量被多线程使⽤的时候,就会出现线程安全问题。
解决这个问题有三种⽅案:
1.实现singleThreadModel接⼝,这样对于每次请求都会创建⼀个新的servlet实例,这样就会消耗服务端内存,降低性能,但是这个接⼝已经过时,不推荐使⽤。
2.可以通过加锁(synchroniezd关键字)来避免线程安全问题。这个时候虽然还是单列,但是对于多线程的访问,每次只能有⼀个请求进⾏⽅法体内执⾏,只有执⾏完毕后,其他线程才允许访问,降低吞吐量。
3.避免使⽤全局变量,使⽤局部变量可以避免线程安全问题,强烈推荐使⽤此⽅法来解决servlet线程
安全的问题。
(jbpm4)⼯作流引擎描述:
JPBM是JBOSS旗下的⼀个开源的基于hibernate的⼯作流引擎。⼯作流就是在⽇常⽣活中,我们⼀些常见的如请假流程、采购流程、⼊职流程,通俗的来讲就是⼀些在现实⽣活中的流程以信息化以程序的⽅式实现。
⼀个⼯作流⾸先需要进⾏流程定义,流程定义是由节点和跳转组成的,节点⼜可以称为环节、活动节点、活动环节,并且节点也可以分为两⼤类型:⼈⼯节点和⾃动节点,⼈⼯节点有start开始节点、end结束节点、task任务节点,⾃动节点有decision判断节点、fork分⽀节点、join聚合节点和state状态节点,并且⼀个流程有且只有⼀个开始节点,但可以有多个结束节点。
流程定义是静⽌的,它在运⾏状态时会转换成流程实例,⼀个流程定义可以对应多个流程实例。流程运⾏后,会产⽣两个⽂件,*.l ⽂件和*.png图⽚⽂件,也会⽣成18张数据库表,常⽤且核⼼的表有JBPM4_LOB 存储表,主要存储xml⽂件和png图⽚、JBPM4_TASK 任务表、JBPM4_EXECUTION 流程实例表、JBPM4_VARIABLE变量表。
图形化的灵活定制(主动说)
可以根据需求进⾏流程图的改变的,即定义的流程图是可以根据需要改变的,⽽不是死的。
可以进⾏图形化的监控(主动说)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论