好早以前看的,保存了下来了,不知道原作者的链接了!!!
在面试官问到技术的时候
是什么?有什么特点?what
为什么用它why
在项目的哪一个地方用过使用的具体步骤使用过程中问题总结?how
冒泡排序:
每次拿两个数进行比较,总是把小的放在最前面,大的放在最后面,第二次是第二个数和第三个数比较,如果第三个小于第二个,那么第三个和第二个替换位置,一次这样比较替换,第一轮循环完了呢,放在最后面的那个数就是这一串数字中最大的数。第二轮循环和第一轮一样,第一个和第二个比较,最小的放在最前面,依次类推。如果有10个数字,那么就进行9次循环,最小的在最前面,最大的放在最后面。
好处呢,就是查询速度快
二分查找:
二分查找就是从一串数字中找到某个数字。
原理就是必须有一串数字是从小到大排序,把这串数字进行划分,分为三段,前半段,中止段,和中止后半段。查找数字或者字符先从中止段查找,查到的数字或者字符和中止正好相等,那么久直接取出来,如果比它大就从后半段查找,后半段在进行二分法,进行递归的调用查找,如果比中止小,走前面的中止段,在进行拆分,进行二分查找法。
关于Spring的话,我们平时做项目一直都在用,不管是使用ssh还是使用ssm,都可以整合。Spring里面主要的就三点,也就是核心思想,DI,IOC,AOP。
DI就是依赖注入,把我们需要的类啊,接口啥的注入到spring中去。
IOC控制反转,像我们之前开发,如果想创建一个对象,就new一个,如果想这个对象中定义其他的变量或者对象,就在对象内部创建一个成员变量。但是现在的话,如果想用这个类的对象,咱们可以在spring的配置文件中配置一个bean,指定对应的全路径名称。spring通过配置文件用反射的方式,就可以直接帮我们获取到这个类的对象。但是现在的话,我们还是用注解,方便太多了。
还有AOP,就是面向切面编程,它的原理的话,我看过它的底层代码,它实际上就是实现了JDK的动态代理,以前的话用这个做过事务的控制,现在的话我们都用注解来控制事务。
AOP执行过程是一个纵向的过程,把每个方法当作一个点.基于这些点可以进行增强处理.形成了横向的切面,包含了原有方法和增强方法.不改变原有代码结构,还添加了额外的功能.
平时AOP我们常用来进行事务管理,日志打印(面试题:项目部署后如果监听项目执行状态.)等。
整体来说的话,Spring在使用的时候非常方便,在配置文件中配置要依赖的对象,或者在配置文件中将对象及属性进行注入,当然现在基本都用注解的方式,更方便。
除了这些,我们之前的项目也用过spring的其他产品,像springboot(简化新Spring应用的初始搭建以及开发过程,用我的话来理解,就是springboot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,springboot整合了所有的框架),springcloud微服务框架。比spring更简单,快速,方便。
(然后就可以扯微服务,和springboot、cloud)。。。
mybatis一级缓存是SqlSession级别的缓存,默认支持一级缓存,不需要在配置文件去配置。
mybaits的二级缓存是mapper范围级别,,除了在SqlMapConfig.xml设置二级缓存的总开关
,还要在具体的mapper.xml中开启二级缓存:
useCache配置禁用二级缓存(默认情况是true,即该sql使用二级缓存。)
mybatis刷新缓存(就是清空缓存flushCache='true'属性,默认情况下为true即刷新缓存,如果改成false则不会刷新)
ng-model双向绑定,ng-controller指定模块ng-appng-clickng-ifng-init初始化ng-rpeat
分部式项目就是项目中的模块,把每一个模块拆分成为一个个的工程,这样我们各个模块之间的耦合度不就降低了嘛,然后我们各个模块之间通过dubbo框架来相互通讯,我们公司用到的是一个第三方的插件dubbo来实现项目之间通信,这样我们的代码的拓展性不就更好了嘛,最后我们在部署项目的时候,可以根据用户的访问量来给各个模块的服务器增大配置,我们还可以采用nginx负载均衡来实现一个反向代理,当用户请求后台服务器的时候,有nginx来决定哪台服务器空闲或者压力小,来让用户访问。我们这样做的目的不都是为了防止高并发嘛
单例:其实单例本质的就是控制对象的产出,要想产生一个唯一的实例,你就要私有化构造方法,然后私有化一个的静态的全局变量,并且提供一个公共的静态的方法供外界访问,单例大概就是这样的。
工厂:它是java设计模式的一种,工厂模式的优势还是很多的,我举一个简单的共厂的例子吧,就是假如我们有好多接口,好多的接口的实现类,我们如果使用工厂模式的话,当我们有需求需要改变接口的实现类的话,直接在工厂里面改变返回的类型就好。这样会应对不同的需求变化。
这两个符号一般是在使用Mybatis编写底层SQL语句时使用,#就是一个占位符,具体的使用是#{id},而$是一个原样输出的标识,是${value},我在项目里一直是使用#,因为这样可以防止Sql注入,安全性高。
Hashmap底层是通过数组和链接联合实现的,当我们创建hashmap时会先创建一个数组,当我们用put方法存数据时,先根据key的hashcode值计算出hash值,然后用这个哈希值确定在数组中的位置,再把value值放进去,如果这个位置本来没放东西,就会直接放进去,如果之前就有,就会生成一个链表,把新放入的值放在头部,当用get方法取值时,会先根据key的hashcode值计算出hash值,确定位置,再根据equals方法从该位置上的链表中取出该value值。
答:简单的说springMVC在ssm中整合就是在web.xml里边配置springMVC的核心控制器:DispatcherServlet;它就是对指定后缀进行拦截;然后在springMVC.xml里边配置扫描器,可以扫描到带@controller注解的这些类,现在用springMVC都是基与注解式开发,像@service,@Repository@requestmapping,@responsebody啦这些注解标签等等都是开发时用的,每个注解标签都有自己的作用;它还配置一个视图解析器,主要就是对处理之后的跳转进行统一配置,大致就是这些
Hibernate一个是全封装,mybatis是半封装,使用hibernate做单表查询操作的时候比较简单(因为hibernate是针对对象进行操作的),但是多表查询起来就比较繁琐了,比如说5张表10张表做关联查询,就算是有SQLquery那后续的维护工作也比较麻烦,还有就是Hibernate在Sql优化上执行效率上会远低于MyBatis(因为hibernate会把表中所有的字段查询出来,比较消耗性能)我们以前在做传统项目方面用过hibernate,但是现在基本上都在用mybatis.
1.我们公司的项目准备南迁,而我个人不喜欢去南方发展,我也想换个工作环境.
2.我们公司转型做别的了,老板做微商了,开发这一块就不需要了,所以就离职了
3.合同正好到期了,我也想换个环境了.
4.老板转行做实体经济去了,做出口贸易了.
在dubbo架构中,service接口和实体对象时各个工程共享的,service实现类是发布服务的工程独有的。只需要发布服务的工程把他的接口注册到zookeeper中,其他工程就可以从zookeeper中进行调用了。
用dubbo的好处是:把项目拆分成各个独立的小工程,通过接口调用方式,互相交互数据,可以单独进行部署和升级,这样就减少了他们直接的耦合性和代码的复用性。还可以针对不同模块采用不同的部署策略,比如订单模块并发比较高,所以可以把订单模块这个war包,单独部署多套,都注册到同一个zookeeper中。当客户端调用时,zookeeper会帮忙进行负载处理。
答:它的底层是通过动态代理实现的面向切面编程,主要用在管理事物这一块,我们在配置文件里配置切入点,比如以save/insert/update等开头的方法我们开启事物,配置了一个REQUIRED开头的事物特性,还可以用在日志管理,还有权限方面也可以用aop来实现,但现在基本上没有人去这样控制权限,都用shiro框架来实现权限管理,springaop大概就是这样,咱们公司是用什么来管理事物的,应该使用注解的方式来管理的吧。
在数据库中,所谓事务是指一组逻辑操作单元即一组sql语句。当这个单元中的一部分操作失败,整个事务回滚,只有全部正确才完成提交,多表操作的时候会用到事务,我们在项目中直接配置到spring里就用啦,用的注解式的事务,比如说银行转账,从A账户向B账户转账,必须得两条SQL语句同时执行成功.
指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户
事物主要是为了保证一次操作里边涉及到多次增删改时,保证他们可以同步提交或回滚。他有四大特性ACID(原子性、一致性、隔离性、持久性)
注解式事物:在Spring配置文件里边开启以后,在需要事物增删改事物的方法上加上@Transactional注解就可以了;
事务的隔离级别也分为四种,四个级别可以逐个解决脏读、不可重复读、幻读这几类问题
7种事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播
上家公司是在上地那块的嘉华大厦里呢,HR还会聊你在哪住,每天坐几号地铁过去,这个一定要说清楚,我在沙河高教园住的呢,我每天直接坐昌平线到西二旗,换13号线人太多了我就直接骑个小黄车就过去.
我在公司的时候,都是通过solr全文检索、redis缓存,还有使用高性能的服务器、高性能的数据库、高效率的编程语言、高性能的Web容器等等来解决高并发的问题。
微服务就是一种分布式的架构
把项目中的每一个模块采用单独的业务逻辑封装,每个项目都可以独立部署和扩展,服务之间可以通过springCloud的Eureka组件作为注册中心使用Feign组件进行服务间的互相通信,我个人认为使用了微服务架构可以降低我们代码的耦合度,在开发的时候,比较好分配项目,还有就是后期再进行项目功能扩展的时候也比较灵活.
使用SpringBoot实现分页非常简单。使用SpringData-JPA可以实现将可分页的org.springframework.data.domain.Pageable传递给存储库方法。
用的是FastDFS文件服务器,FastDFS架构包括一个Trackerserver和一个Storageserver。
客户端请求Trackerserver进行文件上传、下载,通过Trackerserver调用Storageserver完成文件上传和下载。
Trackerserver可以完成负载均衡,它其实是这样的,这个Storageserver会定时的向trackerserver发送自己的状态,trackerserver就能知道那个storageserver是空闲还是忙碌,当上传下载的时候,就会调用空闲的storageserver,当上传或下载的时候,这个storageserver会生成filedid,并将文件写到磁盘,返回一个路径信息和文件名,拿到路径信息我们就可以存到数据库或调用了。
1、@Component是所有受Spring管理组件的通用形式,@Component注解可以放在类的头上,@Component不推荐使用。标注一个普通的springBean类。
2、@Controller对应表现层的Bean。标注一个控制器组件类。
3、@Service对应的是业务层Bean。标注一个业务逻辑组件类。
4、@Repository对应数据访问层Bean。标注一个DAO组件类。
在spring未来的版本中,@Controller,@Service,@Repository会携带更多语义。尽量考虑使用@Controller,@Service,@Repository代替通用的@Component。
5、@Transactional应用事务的注解
3)定义到父类上:当执行父类的方法时候应用事务。
然后将事物增强与切面组合
最后开启事物注解标注
Transaction的类和方法将具有事物
可以。在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器、信息量机构等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核。
不同进程之间共享内存通常安排在同一段物理内存中,进程可以将同一段共享内存连接到他们自己的地址空间中如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
共享内存并未提供同步机制,就是说在第一个进程结束对共享内存的写操作之前并没有自动机制可以阻止第二个进程开始对它进行读取,使用我们通常需要用其他的机制来同步对共享内存的访问。
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
cookie数据存放在客户的浏览器上,session数据放在服务器上。
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
所以个人建议:将登陆信息等重要信息存放为SESSION其他信息如果需要保留,可以放在COOKIE中
讲这个ActiveMQ,需要先聊到java中有一个JMS规范,就是java消息服务规范,这套规范包含点对点,订阅两种方式来收发消息,简单来说的话,就是JMS制定了这样一个规范,里边的API与具体的平台无关。
ActiveMQ是支持JMS规范的一个开源技术,它支持好多通讯协议,像我们最常用的TCP和UDP,它都支持,activeMQ支持多种通讯协议TCP/UDP等。对于TCP协议,我们知道TCP有一个三次握手,所谓的三次握手可以这样来理解,比如A和B建立连接时,首先A向B发出一个同步请求,然后B回复一个同步请求应答,最后A回复一个确认信息。
就拿ActiveMQ中所支持的TCP协议来说,ActiveMQ初始化时,通过类根据配置打开TCP侦听端口,客户通过该端口发起建立链接的动作。生产者发送一个消息,进入到消息队列中,然后消费者可以从队列中取出消息
在ActiveMQ中分为生产者和消费者,生产者发送消息,消费者接受消息,里边有一个比较重要的机制叫做消息中转器,它是activeMQ的核心,消息会先经过中转器,然后再分发给消费者
对于ActiveMQ发送消息的方式,是分为两种的,其实它也是符合JMS规范的,就是点对点和订阅消息类型,对于点对点,每个消息只能有一个消费者,这种方式是基于队列的,如果消息不被消费,就会一直阻塞在队列中,只有当消费者消费之后消息才会消失。
对于订阅方式,它是基于主题topic的,可以有多个消费者,类似于广播,只要你订阅了,就能够收到这个消息,如果发的时候还没启动消费者,那这个消息就会被错过。
其实这个ActiveMQ的信息还是挺多的,比如它发送消息能实现即时发送,还能实现定时,延时发送.
ActiveMQ收发消息的原理和具体流程大约是这样的:
发送方:
创建一个连接消息中转服务器的连接工厂。
根据这个工厂获取到一个具体的connection
启动连接,创建session回话
设置发送消息的类型,可以指定topic也可以指定点对点
将消息发送出去
消费方:
也是创建一个连接消息中转服务器的连接工厂
启动连接,创建session会话
定义消息消费者,准备接收消息
设置一个消息接收的监听者,当有消息回调接收到的时候,回调到onMessage方法中
我们做的项目由于是分布式项目,各个模块之间都是相互独立的,就会有这样的需求,比如模块之间的通信问题,或者高并发,就会用到消息队列,消息队列的话,常用的有RabbitMQ,ActiveMQ,阿里的RocketMQ,rabbitmq支持的协议比较多,是一种重量级的消息框架,阿里的rocketmq没有用过,我们常用的是activeMQ,属于轻量级的。
当然,除了商品添加同步更新索引库,像商品详情模块,在商品审核通过以后,想消息队列中发送了一个商品id到消息队列中,pageService工程中有一个监听类,可以生成相应的静态页面,,还有订单模块也有用到过,当执行生成订单,进行银行扣款,扣款成功,减库存啊,这种类型的操作,都可以通过ActiveMQ发生消息来实行同步操作。
以上呢,是介绍一下ActiveMQ,对于ActiveMQ的使用,我们是这样来做的
,拷贝一个ActiveMQ压缩包放到在Linux服务器上,解压,用./activemq启动activemq,这个就是我刚才所说的消息中转服务器,我们还可以访问一个管理界面,能够查看收发消息的状态。
在maven项目,我们需要在pom文件中配置activemq的jar包信息
在发送端的springmvc的配置文件中配置mq的连接工厂,指定消息服务器的ip端口,配置Spring提供的JMS模板类工具类(jmsTemplate),配置发送消息的类型。在需要进行发送的代码逻辑中,直接使用spring提供的模板类jmsTemplate.send就可以了,至于发送的内容,可以自己指定。是文本类型,还是消息对象消息,按需求指定就可以。
同样的,在Springmvc配置工厂,服务ip端口,还需要额外指定一个监听器,这个监听器就是自己定义的一个类,实现MessageListener,当收到消息时,就会触发里边的一个回调方法,把消息取出来,执行相应逻辑就可以。
Redis是一个非关系型的数据库,以key-value的形式存储在内存中的,
存储的数据类型有字符串,列表类型还有散列表型,项目中常用string和hash这两种类型;redis还可以将数存储到磁盘中,
有两种形式rdb和aof两种,
rdb是以快照的形式来存储数据的,
redis默认也是这种存储形式,性能较好
aof是即时存储,每个一秒存储一次,性能比较差;
Reids存在的问题就是内存中的数据还没有保存到磁盘上时,服务器宕机或者断电,就会发生数据丢失,
解决的途径是提高存储的频率。
Redis是一个继memcached后的又一个第三方缓存数据库,他比memcached强大很多,支持更多的数据类,它作为数据库和应用程序直接的中间层来使用,已减轻数据库压力,提高运行效率。
代码中,我们一般都通过spring整合redis官方提供的jedis工具包来操作redis。可以是单机版,也可以是集群。Redis本身就支持集群操作redis_cluster,另外redis还支持主从复杂,还有他独特的哨兵模式,在主服务器宕机时,从服务器可以自动转换为主服务器。另外,他也有他的分片机制,就像mysql的水平分表设计,数据量大时,可以把数据存储到不同的库中,来减轻redis负担。
快照(RDB)方式,默认方式,文件以二进制方式保存到RDB文件。
文件追加(AOF)方式,文件以协议文本的方式write到AOF文件。
作用,重启后的数据恢复。当两种方式都启用时,redis会优先载入AOF文件,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
注意优先是指载入AOF文件就不再加载RDB了,不管AOF是不是空文件。
5.Redis和memcached的区别
1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;
2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;redis支持事务
4、过期策略--memcache在set时就指定,例如setkey1008,即永不过期。Redis可以通过例如expire设定,例如expirename10;
5、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;
6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);
8、Redis支持数据的备份,即master-slave模式的数据备份;
我了解的有
字符串类型、
list,我们可以向list的两端添加数据
集合set,存放的数据是无序的,集合中的数据是不重复的,由于它是无序的,所以不能通过下标来获取制定元素、
orderset有序集合、
hash
实际上我们常用的也就是string和hash
redis是通过key-value存储的setkeyvaluestring
hsetkeyvaluehgetkeyvalue
答案:RDB,AOF俩种,RDB是一种快照的方式来存储的,这也是redis的默认的持久化方式,每隔一段对数据进行一次存储,默认是15S。
AOF是即时性的持久化方式,这种方式对数据的保存完整性比较高,但是性能比较差。
而RDB存在的问题主要是服务器宕机或者断电,就会造成数据丢失,我们可以适当的把存储间隔缩短一些
IDEA,Eclipse,MyEclipse,数据库操作用nvacat或者sqlyong,还有数据库建模用powerDesner
ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。
ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(Listl)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
Solr是一个基于Lucene开发的全文搜索引擎,项目中一般用它做首页的全文搜索或者做文件管理系统中的文件检索,因为他提供了分词的支持,同时采用文件存储数据,所以无论是查询速度还是匹配精确度方面,都比数据库的like查询方便了很多。比如:电商网站上,用户想买手机,输入“苹果手机”,但是系统中录入的是ipone手机,那么用like查询就很难匹配到,但lucene就可以解决这个问题。
使用时,Lucene官方紧紧提供了核心实现的jar包,我们只能通过api文档,自己实现创建索引和查询的逻辑,并进行优化处理,开发比较繁琐,但比较基础,更灵活,做文档的检索时可能相对更好点。而solr是Apache开发的一个开源的web工程,他帮我们实现了创建索引、查询等操作,经内部进行了一定的优化,然后以restful风格对外提供了接口。并且提供了solrj的sdk工具包,方便Java开发者直接使用。一般做电商等网站的全文搜索,我们使用时,只需要官方下载到solr工程的war包,根据我们的实际情况,修改solrhome、solrconfig.xml和schema.xm文件,简单配置一下使用的数据库和创建索引的sql和字段,然后把war包进行部署就可以了。可以通过他提供的页面进行创建和查询索引的操作。也可以在项目中集成solrj的jar包,直接调用他的方法,进行创建索引和查询的操作。
另外由于solr查询时,不是直接查询数据库,而是开始时,先把数据库中的数据同步到索引文件中,查询时,直接查询索引文件。索引数据库数据修改时,需要同时同步到solr的索引文件中,也就是创建索引。创建索引分为全量创建和增量创建。可以通过配置文件实现自动增量更新,自动增量更新可定时将数据库中的数据导入到solr索引库中,并可定时重建索引库,合并小索引文件为大的索引文件。除了solr以外,最近又出了一个搜索引擎叫ElasticSearch,我简单了解了一下,他和solr一样,也是一个基于Lucene的,rest风格的,分布式搜索引擎。Solr特点是:查询快,但更新索引时慢(即插入删除慢),对用于电商等提前录入好数据,之后查询特别多的应用;而ElasticSearch简称ES建立索引快、查询相对慢点,但综合上表现为实时性查询快,用于新浪了,facebook了等搜索。
1、zookerpper的作用动物园管理员;
配置管理。名字服务,集群管理
2、solr、Lucene、es的区别;
3、solr集群搭建主要步骤,和集群方案;
4、solr高亮和分页
高亮显示查出的字段和高亮的颜色大小啥的分页是先获得条数还有除以条数的到页数
5、solr权重配置;
6、索引创建;全局索引和增量索引;
7、solr部署主要步骤;
8、solrhome
9、solrconfig.xml,主要定义solr的处理程序(handler)和一些扩展程序;
solrconfig.xml文件不仅指定了Solr如何处理索引、突出显示、分类、搜索以及其他请求,还指定了用于指定缓存的处理方法的属性,以及用于指定Lucene管理索引的方法的属性。
10、schema.xml,主要定义索引的字段和字段类型。
fieldtype、Fields、copyField、dynamicField
答案:基本工资4000、岗位工资4000、绩效工资2000,我们公司12薪,扣税750,保险折现了给了500
1.按劳动合同,必须得提前一个月提出离职申请(官方)
实际说法:手头工作交接一下,大概一个星期左右就可以离职.
泛型还有接口、方法等等,内容很多,需要花费一番功夫才能理解掌握并熟练应用。
限制性:
1、泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
3、泛型的类型参数可以有多个。
4、泛型的参数类型可以使用extends语句,例如
简单介绍:
全>左右>内
内联接(INNERJOIN)
仅将两个表中满足连接条件的行组合起来作为结果集。在内连接中,只有在两个表中匹配的行才能在结果集中出现
左外连接(LEFTJOIN)
左表的所有数据和右表符合条件的数据
右连接相对应(RIGHTJOIN)
全外连接(FULLJOIN)
返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列用null代替。如果表之间有匹配行,则整个结果集行包含基表的数据值。
文件上传后返回一个路径信息和文件名,拿到路径信息我们就可以存到数据库或调用了。
我比较有成就感的项目是一个手机APP叫小象优品
它是一款以网络购物为核心业务的app,一共分为两大模块,分别是客户端和后台管理系统。
它的客户端有商品搜索,商品展示,购物车,支付等这些功能,对于客户来说,可以浏览并找到自己满意的商品,这样客户会获得便捷的购物方式和放心的服务。
而后台管理系统有用户管理,商品管理,订单管理,店铺管理等功能,对于卖家来说可以通过简单的操作,就能实现商品的售卖和管理,非常大的便捷,简单;
我主要负责商品模块,包括搜索商品和商品的展示。
我主要用到的技术有solr,它实现所有商品的搜索功能,Solr它是一个全文检索服务器,我们可以通过solr设置条件查询,还有高亮显示啦这些功能,现在不是都用solr来做嘛,它的查询效率是比较高的;,我还使用ActiveMQ这个消息队列它可以实现索引库和缓存的同步,比如我们做商品添加时,用activeMQ可以把数据同步到solr上,还搭建了nginx+FastDFS服务器来管理我们项目中图片和文件的上传及下载;
那个接口开发,我们就是这么做的,就是用的那个springMVC结合swgger来做的那个接口开发,swgger提供一些注解,可以把接口文档通过网页的形式可以展示出来,上面能标清楚他的url,参数,返回类型什么的,比较方便,原来我们没有用swgger的时候,用的都是那个word文档,但是用容易丢,不好维护,后来才用的swgger,现在同类型的产品也挺多的,我们公司反正用的都是swgger。
(01)选择最有效率的表名顺序(笔试常考)数据库的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表放在最后,如果有3个以上的表连接查询,那就需要选择那个被其他表所引用的表放在最后。1)如果三个表是完全无关系的话,将记录和列名最少的表,写在最后,然后依次类推2)如果三个表是有关系的话,将引用最多的表,放在最后,然后依次类推
(02)WHERE子句中的连接顺序(笔试常考)数据库采用自右而左的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之左,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的之右。
(04)用TRUNCATE替代DELETE
(05)尽量多使用COMMIT因为COMMIT会释放回滚点
(06)用WHERE子句替换HAVING子句WHERE先执行,HAVING后执行
(07)多使用内部函数提高SQL效率
(08)使用表的别名
一般得看需求因为controller不是一个的有可能pc端的是返回页面移动端的是返回json数据格式根据实际的需求而定
开发时侯跨域调用这块还用到过HttpClient这个技术,把它放到工具类里变用的时候直接调用就行了,项目开发中也用到过一些其他这样的技术,像遇到C语言向java语言这种跨语言的通信,就用到WebService技术,它的底层通信用的是soap协议,用的是cxf方式来发送的。
JDK1.8的新特性
一、接口的默认方法
Java8允许我们给接口添加一个非抽象的方法实现,只需要使用
default关键字即可,这个特征又叫做扩展方法。
二、Lambda表达式
在Java8中你就没必要使用这种传统的匿名对象的方式了,
Java8提供了更简洁的语法,lambda表达式:
Collections.sort(names,(Stringa,Stringb)->{
returnb.compareTo(a);
});
三、函数式接口
Lambda表达式是如何在java的类型系统中表示的呢?每一个lambda表达式
都对应一个类型,通常是接口类型。而“函数式接口”
是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式
都会被匹配到这个抽象方法。因为默认方法不算抽象方法,
所以你也可以给你的函数式接口添加默认方法。
四、方法与构造函数引用
Java8允许你使用::关键字来传递方法或者构造函数引用,
上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:
converter=something::startsWith;
Stringconverted=converter.convert("Java");
System.out.println(converted);
五、Lambda作用域
在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。
你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。
六、访问局部变量
可以直接在lambda表达式中访问外层的局部变量:
七、访问对象字段与静态变量
和本地变量不同的是,lambda内部对于实例的字段以及静态变量是即可读又可写。
该行为和匿名对象是一致的:
八、访问接口的默认方法
JDK1.8API包含了很多内建的函数式接口,在老Java中常用到的比如Comparator
或者Runnable接口,这些接口都增加了@FunctionalInterface注解以便能
用在lambda上。
给不同类型的用户设置不同的状态码,通过状态码匹配角色表,再通过角色表匹配权限表从而实现URL权限赋予功能
由业务来定。比如说做商品检索时,时搜索商品的名称,卖点,描述。以这些业务域进行所搜的
URL重写,对所有页面涉及的连接都使用url重写方式。从而将JsessionID
以参数的方式链接到URL后面。保证每次页面提交时服务器都能获得sessionID从而维持和客户端的状态。
countmaxminsumavg
”==”与”===”是不同的,前者是判断值是否相等,后者是判断值及类型是否完全相等。
1.PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
2.PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
3.PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
5.PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。
传统方式:接口文档三要素:URL、参数、返回值
需求文档:客户做需求调研的时候写过,根据客户的需求我们来写文档。画流程图、写开发步骤、主要功能点的介绍等
系统设计:有哪些功能点、规定了具体方法、类、字段,涉及数据库表、字段,后期编码
互联网项目:采用敏捷式开发,利用swagger设计文档,生成文档的URL、参数、返回类型。
还有就是热销商品的商品详情页面也做了静态化处理,首页我们是通过定时器每天凌晨一点,去重新生成;商品详情我们是在商品信息修改以后,给定时器表(id,业务id、type,remark)中推送一条信息,到第二天凌晨一点时,定时任务扫描表,发现有需要重新生成的页面,就调用freemarker模板,重新生成html页面,以商品id作为html页面名称,然后删除任务表中的数据。为了预防大量静态页面给服务器造成压力,我们把html页面直接生成到Nginx的静态页面服务器上。访问时,不用经过Tomcat,直接通过Nginx访问。
sKU是库存量单位,区分单品,.另外还有SPU,是标准化的产品单元,区分品种,
例如iphon8这是一个SPU苹果8(64G黑色移动)这就是一个SKU.
我们用的是SpringDataSolr来操作的Solr索引库.
我们项目在第一次上线的时候,会手动往solr索引库导入一批数据,后期就不用人工干预了,我们后台添加了相应的商品之后,商品审核通过的时候,用的ActiveMQ往里面发送一条消息,商品的ID,然后在solr这个search这个工程中,我们会接收到这个id,然后把这个id从数据库里面查询出来该商品信息,把数据添加到我们的索引库里边去。维护大概就是这样。
你是说的项目版本管理,还是项目进度管理,我们项目版本管理用的是SVN,我们项目进度管理项目经理用的是禅道,还有那个project软件管理的进度.
项目中的多线程,线程池是怎么回事
多线程:解决多任务同时执行的需求,合理使用CPU资源。多线程的运行是根据CPU切换完成,如何切换由CPU决定,因此多线程运行具有不确定性。
(1)打个比方,假设有P1和P2两个进程,都需要A和B两个资源,现在P1持有A等待B资源,而P2持有B等待A资源,两个都等待另一个资源而不肯释放资源,就这样无限等待中,这就形成死锁,这也是死锁的一种情况。给死锁下个定义,如果一组进程中每一个进程都在等待仅由该组进程中的其他进程才能引发的事件,那么该组进程是死锁的。
(2)竞争不可抢占资源引起死锁
(3)也就是我们说的第一种情况,而这都在等待对方占有的不可抢占的资源。
(5)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
(6)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
(7)环路等待条件:指在发生死锁时候,一定存在一个进程相当于资源的环形链,也就是进程的集合像{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源
(1)检测死锁
这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源,然后采取适当措施,从系统中将已发生的死锁清除掉。
(2)解除死锁。
这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施,有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。
它们的主要区别是:io是面向流,阻塞io,而nio是面向缓冲,非阻塞的io;
io的话每次从流中读取一个或多个字节,直到读取完所有的字节,没有缓存到任何地方.nio读取的是数据是有缓存,就是说他读取的数据是在缓冲里读的.
另外的话,java中的各种io是阻塞的.就是说一个线程调用read或者write()时,这个线程就已经被阻塞了,直到读取到一些数据为止,或者是完全写入.在此期间不能干其他的
另外NIO还有一个selector(选择器),它是可以管理多个输入输出的通道.大概就是这样
原来我们公司做某某某项目的时候呢,用的是5张表的联查,然后用sql语句来写的话,比较慢,比较麻烦,然后我们把这5张表的联查创建了了视图,然后就直接查找的是视图,查询速度快,这个视图就是只能做查询,而不能做增删改操作。还有就是Oracle里面视图用的是CREATEVIEW后面跟视图的名字,然后跟上sql语句
其实视图就是当成一张表进行操作了。
这就集思广益了,按照自己简历上的项目,然后针对性的找出自己要说哪几点,首先介绍这个是干什么的,然后这个是怎么用的,然后在哪里用的。
首先呢,不推荐在web框架下在消息,效率低,可以使用一个开源的消息服务器,jmq,mqtt,xmpp协议都可以。
以下了解:
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
<
《大型网站系统与Java中间件实践》作者曾宪杰:它是淘宝的技术总监
这本书主要突出的重点是中间件三个字,中间件是分布式系统中一个非常重要的东西,它最重要的作用应该就是降低模块与模块之间的那种强依赖,然后不同的模块之间的依赖度降低了,就可以各自独立地开发自己的功能,这也可以说是软件工程发展的目标和驱动力。
这本书适合对分布式系统比较熟悉并且想要往中间件方面有一定研究的读者。
solrCloud是solr提供的分布式搜索方案solrClund是基于solr和zookeeper的分布式搜索方案,主要思想是使用zookeeper作为集群的配置中心特色功能:1.集中式的配置信息2.自动容错3.近实时搜索4.查询时自动负载均衡。SolrCloud结构需要由多台服务器共同完成索引和搜索任务实现的思路是将索引数据进行shard(分片)拆分,每个分片由多台的服务器共同完成。当一个索引或搜索请求过来时会分别从不同的shard的服务器中操作索引。solrCloud需要solr基于zookeeper部署,zookeeper是一个集群管理软件,由solrCloud需要由多台服务器组成。由zookeeper来进行协调管理
我们的项目采用分布式的架构,每一个模块都可以作为一个项目,每一个项目都可以分为服务端和消费端,按照其功能分可以分为7个,分别是e3-web-manager,cart,item,portal,
Search,sso,order.这几个项目组成
根据项目的需求来做一般是用在线的需求文档就是用的石墨文档是支持云端实时协作的企业办公软件我们一般是这上头写需求改需求的。
有dubbosolrRedis都是我们自己搭建的这些都是最基本的
有我们有专门测试的服务专门测试的服务有一个测试的版本有一个环境比如说连接数据库测试环境无非就是把配置变一下,一般都是有生成环境开发环境还有测试环境一般都是这么分的咱们公司是这样的吗测试是怎么做的呢?
都是通信协议
Tcp:tcp跟udp都是传输协议主要区别是tcp协议连接需要3次握手断开需要四次握手是通过流来传输的就是确定连接后一直发送信息传完后断开
Udp:udp不需要进行连接直接把信息封装成多个报文直接发送所以速度更快
Rpc:一种通过网络从远程计算机程序上请求服务不需要了解底层网络技术的协议
Jms:(javamSSessagingservice)是java的消息服务jms的客户端之间通过jms服务进行异步的消息传输
答:一般我们都是去,恩,就是说当我们每次做完出库后,都会有一个计算,比如说当我们的库存量小于100,或者是小于50,然后说就是会有相应的短信提醒,告诉库管这个商品少了,或者就是专门有一个预存信息的功能,就是定时的点击那个就可以知道哪些库存少了,就应该及时的去补充这个库存,其实就是查询库存数量小于多少的库存数就行
我们之前做过权限管理,我们做的时候使用的五张表去做的这样的权限管理,有一张用户表,一张角色表,一张权限表,还有一张用户角色的桥表和角色权限的桥表。
我们是通过用户的id查询它所对应的角色,通过角色查询他所对应的权限,通过权限找到相对应的url.不知道咱们公司关于权限管理这块是怎么做的?
单链索引是指在表的某一列上创建索引,联合索引是在多个列上联合创建索引。单一索引可以出现在where条件的任何位置,而联合索引需要按照一定的顺序来写。在多条件查询的时候,联合索引的效率更高。我大概就了解这么多了。
索引并不是时时都会生效的,比如以下几种情况,将导致索引失效:
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
此外,查看索引的使用情况
showstatuslike‘Handler_read%’;大家可以注意:handler_read_key:这个值越高越好,越高表示使用索引查询到的次数
handler_read_rnd_next:这个值越高,说明查询低效
1.内存分配
静态变量在应用程序初始化时,就存在于内存当中,直到它所在的类的程序运行结束时才消亡;
而非静态变量需要被实例化后才会分配内存。
2.生存周期
静态变量生存周期为应用程序的存在周期;
非静态变量的存在周期取决于实例化的类的存在周期。
3.调用方式
静态变量只能通过“类.静态变量名”调用,类的实例不能调用;
非静态变量当该变量所在的类被实例化后,可通过实例化的类名直接访问。
4.共享方式
静态变量是全局变量,被所有类的实例对象共享,即一个实例的改变了静态变量的值,其他同类的实例读到的就是变化后的值;
非静态变量是局部变量,不共享的。
5.访问方式
静态成员不能访问非静态成员;
非静态成员可以访问静态成员。
静态变量在类装载的时候分配内存,以后创建的对象都使用的该内存,相应的操作也就是对这块内存进行操作。也可以看作是另类的全局变量。
在WebSerivice中想只进行一次初始化,而不用每次都进行初始化这样占用大量资源。还可以对调用的服务进行管理,比如想把每次调用的服务进行排队执行,可以将想应信息放到Arraylist中,静态时钟中排队执行。
我们常用的有ActiveMQ、Redis
了解:RabbitMQ、ZeroMQ、Jafka/Kafka
ActiveMQ:它是apache下的一个子项目,类似于ZeroMQ,是以点对点的技术实现队列,又有点类似于RabbitMQ,可以高效实现高级应用场景
有两种消息传递类型:
作用:为了解决高并发
好处:支持多种语言和协议的,支持多种传送协议,提供高速消息持久化
怎么配置以及安装调用
安装:基于jdk,把ActiveMQ的压缩包上传到Linux系统上,进行解压,使用bin目录下的./activemqstart命令启动
配置:springMVC.xml文件中引入activeMQ的xml文件
activeMQ.xml文件中配置JMS工具类,进行消息的接收发送等,再配置队列目的地已经订阅方式
Redis:以key-value形式存在的非关系型数据库,本身支持MQ功能,我们可以把它当做一个轻量级队列服务;
安装:复制redis压缩包到Linux系统是哪个,进行解压,调用bin目录下./redis-serverredis.conf./redis-cli进行启动。
配置:commons工程下配置xml文档连接redis单机/集群版,导入工具包
RabbitMQ:开源的消息队列,支持很多协议,所以会非常重量级,适用于企业级的开发,对路由,负载均衡或者数据持久化有很好的支持。
ZeroMQ:具有独特的非中间件模式,最快的消息队列系统,主要是针对大吞吐量的需求场景,能实现复杂队列。
缺点:非持久化,电脑宕机数据会丢失。需要开发人员自己组合技术框架
Jafka/Kafka:apache下子项目,轻量级的高性能跨语言分布式消息队列系统
特性:快速持久化;高吞吐;完全分布式;支持Hadoop数据并行加载
我们在开发项目时主要用到IDEA、JDK1.7、Maven、Solr、nginx、Tomcat7.0、MySql、redis等开发工具或环境搭建,那么我们在开发同一项目的时候开发环境必须统一,
公司项目的开发主要还是基于maven管理的聚合工程,分布式架构项目,我们每个人负责的功能模块都不相同,如果开发环境不统一,可能导致我们项目合并时候出现版本冲突,或者jar包等不兼容之类的事
a)表结构
1、横表:主键、字段1、字段2……
如:姓名语文英语……
优点:一行表示了一个实体记录,清晰可见,一目了然。
缺点:如果现在要给这个表加一个字段,那么就必须重建表结构。
2、纵表:主键、字段1/2/3、字段值。
如:姓名课程成绩
优点:如果现在要给这个表加一个字段,只需要添加一些记录。
缺点:数据描述不是很清晰,而且会造成数据库数据很多。另如果需要分组统计,要先groupby,较繁琐。
b)方法一:
聚合函数(max或者sum)配合case语句
例子:select姓名,sum(case课程where’语文’then成绩end)as语文from表名groupby姓名
方法二:
使用pivot
select*from表名pivot(max(成绩)for课程in(语文,数学,英语))临时表
c)oracleSQL实现竖表转横表
方法一:
--用decode实现,SELECT姓名,SUM(DECODE(课程,'语文',成绩))语文FROM表名GROUPBY姓名
方法二:--用casewhen实现SELECT姓名,SUM(CASE课程WHEN'语文'THEN成绩ELSE0END)语文FROM表名GROUPBY姓名
区别:如果条件是单一值时,用decode比较简便,如果判断条件比较复杂是用casewhen实现
[修饰符]interface接口名[extends父接口名列表]{
[public][static][final]常量;[public][abstract]方法;}修饰符:可选,用于指定接口的访问权限,可选值为public。如果省略则使用默认的访问权限。接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标识符。一般情况下,要求首字母大写。extends父接口名列表:可选参数,用于指定要定义的接口继承于哪个父接口。当使用extends关键字时,父接口名为必选参数。方法:接口中的方法只有定义而没有被实现。
synchronized关键字主要解决多线程共享数据同步问题。ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。当然ThreadLocal并不能替代synchronized,它们处理不同的问题域。Synchronized用于实现同步机制,比ThreadLocal更加复杂。
减轻服务器压力,降低项目之间的耦合度(解耦),是做异步的.
索引可以理解为数据1的查询目录,建索引的目的就是提高对表的查询速度;没有索引时,查询时全表检索,有了索引就可以根据索引快速查找需要的数据;但是索引也不能乱建,因为索引需要维护,会导致增删改的效率降低。会使数据的维护变的复杂,影响开发的效率,索引也会占用数据库的物理空间;所以我们一般在项目的开发阶段、测试阶段、试运行阶段都很少去创建索引,因为有了索引,系统bug造成垃圾数据特别不好删除。只有在项目正式上线后才去增加索引,以提高项目运行速度。索引我们一般都创建在经常作为查询条件的字段、排序的字段和作为关联关系的字段上边。尽量避免在大文本字段、数据量比较小的字段(比如性别),增删改性能大于检索性能的字段上边;另外,有些情况,即使增加了索引,索引也不会生效,比如:索引字段使用了不等于(!=或者<>)符合,用了函数、进行了运算,使用了isnull或isnotnull,
和不匹配的数据类型进行比较、like查询时两边都用了%等;还有一个要注意的地方是,如果在多个字段上建立联合索引,那么组合索引的第一个列被where子句引用时,索引才会起作用。因为想要使用索引增加查询效率,必然要牺牲增删改效率,为了解决这个问题,我们经常对数据库做主从复制,读写分离。同时创建两个数据库,一主一从,两个数据库数据完全一致,主的数据库用来进行写的操作,操作后数据库会自动把数据同步到从的数据库,从的数据库用来执行读的操作。这样我们建立索引时,就可以只在读的数据库创建就可以了。这样就索引即能增加查询效率,有不影响增删改效率。这样做了之后,我们还可以对他进一步优化,比如数据库引擎的优化,主数据库因为执行增删改操作,所以用事务型引擎Innodb,
读的数据库,不需要事务,就可以用效率更高的MyIASM引擎。同时根据实际情况,也可以配置一主多从或者多主多从。索引的创建常用的有2中方式:CREATE【UNIQUE】INDEXindex_nameONtable_name(column_list);或者ALTERTABLEtable_nameADDINDEXindex_name(id,name);修改用:ALTERTABLEtable_nameREBUILDINDEXindex_name(column_list);删除用:DROPINDEXindex_nameONtalbe_name
或者:ALTERTABLEtable_nameDROPINDEXindex_name
查看用:select*fromall_indexeswheretable_name='student';
Conlum_list中多个字段用”,”号分割。
1.使用支持mysql主从复制的版本
2.在使用MySQL时使用索引
3.优化sql语句
4.优化MySQL服务,修改MY.INI文件,根据服务器配置缓存的大小
5.根据服务器配置索引的缓存
6.使用视图,将冗余字段放在一张表里
7.使用第三方技术mycat,对数据库拆分,水平拆分和垂直拆分,我们用的水平拆分
8.设置表内存放数据上限,同时通过mycat配置读写分离
1.方法区(原数据区,永久区)应用程序所有的类,常量(不会变化的量)
2.栈:调用方法的里面有方法的形参和局部变量方法的返回值
3.堆:new出来的对象
里面分为新生代和老年代
新生代:edenfromto三个区from和to是存活区刚new出来的对象都放在eden区
from和to用来转储的内存
老年代:被垃圾回收很多次都没有回收(有没有被引用)
4.本地方法栈:虚拟机使用Native方法服务
5.Pc寄存器:当前执行的方法的地址,内存中速度最高的位置
1>代码上尽量避免不必要的全局变量的使用,避免多层循环迭代,去除不必要的jar包,避免封装太多不必要的类的封装
2>JDK中自带的JMap查看内存信息,下载GC日志信息,,查看宕机信息,在Linux上设置tomcat上面catalina.bat文件设置Xms初始化堆的大小(128m)和XMx最大允许分配对内存(按需,一般根据我们项目的需要和内存的80%大小,如果不是强需修改,一般设置这两个参数大小相等)。在eclips上preferences-tomcat-jvmSettings中添加JVM参数,或者windows采用service.bat中installTomcat命令里面有JVM的参数设置。
这个我们项目中使用MyCat来做的,在mycat里配置好主库和从库,做增删改的时候是对主库进行操作,查询的时候是对从库进行操作,其实mysql本身从5.6以后的版本就带主从复制的功能了,他们是利用mysql里的log文件进行的数据同步.
线程就是一段可执行的代码块。
因为线程要服务于进程,一个进程有多个线程。
main方法就是主线程。多个线程一起执行就是多线程。
我们处理每一个请求就是一个线程,处理完请求就要被销毁。如果说有好多个请求,那么就要不停的创建并销毁。比较浪费资源。
那我们就用到了线程池,把准备就绪的线程放到线程池里面。需要处理请求的时候就调用线程。用完后再放回去,这样就可以防止高并发节省资源。
可以通过collections集合工具类对不安全的线程进行包装,使其变成线程安全的,也可以在使用其时加synchronized关键字进行同步
括号附带:话术中没有
(在网络爬虫的系统框架中,主过程由控制器,解析器,资源库三部分组成。
控制器的主要工作是负责给多线程中的各个爬虫线程分配工作任务。
解析器的主要工作是下载网页,进行页面的处理,主要是将一些JS脚本标签、CSS代码内容、空格字符、HTML标签等内容处理掉,爬虫的基本工作是由解析器完成。
资源库是用来存放下载到的网页资源,一般都采用大型的数据库存储,如Oracle数据库,并对其建立索引。
常见的反爬策略主要有:
IP限制
UA限制
Cookie限制
资源随机化存储
动态加载技术
……
对应的反爬处理手段主要有:
IP代理池技术
用户代理池技术
Cookie保存与处理
自动触发技术
抓包分析技术+自动触发技术)
一个有三年工作经验的人,一定要说设计过,(实际工作经验的程序员:在系统设计、需求文档,数据建模都应该有所涉及)数据库建模就是使用PowerDsiger工具,先分析项目需求,前端先出相应的原型,根据原型,我开始做相应的表,设计初期的时候表会有些小浮动修改等,再根据需求设计详细字段。如果后期客户需求改变时,表结构后期跟着调整,就是这样使用工具不断完善过程就是建模。
Java中的锁就是线程同步的锁,一般是在方法上面加一个synchroized关键字,锁的对象就是监视器,将当前对象作为锁定的对象,如果在代码块上进行加的话,自己可以指定自己要锁定的对象,比如说自己可以指定一个字符串,可以当做一个锁,指定一个类的class可以当做一个锁,只要这个锁的对象是不变的就行了。比如说指定一个类的class来当做一个锁,那么一个类的class本身就是不变的,当你在创建对象的时候就需要加载一个类,加载完成类肯定是不变的了。一般可以锁三种内型:当前对象,放在当前对象的方法上,第二种就是给一个字符串,第三种就是类.class。放在类上可以锁住一个对象,但是放在对象上肯定不能锁住一个类。
首先要介绍项目的背景,项目的技术所用的技术架构,项目中使用的第三方插件要给人介绍。项目后期的维护测试发布运维是怎么做的,这些都要与人说清楚。
比如说这个爱普停车系统,他的背景就是现在的北京不仅堵车,而且找一个停车的地方也不好停,所以我们公司就有这个愿景,让用户用了我们这个爱普的软件后不管走在北京的哪一个角落,都能找到停车位。
我们前端是用appcan写的。这样写的好处是,能在ios和安卓运行。
接口文档也叫接口api,三要素:url,参数,返回值。
需求文档写过吗?当然写过啊。客户在做需求调研的时候,我们也写过的。需求文档大概是这样写的。比如客户的那些需求呢理出来,理出来以后呢。
就根据一个功能点来说吧,就拿商品添加这个功能点来说吧,首先有个流程图要画出来,就用那个瑞搜,
有开始结束标签,中间有判断,首先开始,点击进入到登陆到我们的系统,然后点击新增商品的这个链接,然后有那么一个操作符,下一步点击这个商品
分类,这是一个操作符,接下来把这个商品分类显示出来,等等一系列的这个操作,我们要在需求文档里面写出来。流程图画完了,我们再说这个过程,
过程呢是分一二三四五六七八这样的步骤写下来的,写完这些步骤以后呢,还有产品得截图,什么样得截图呢?就是输出画面一,输出画面二这样得截图。
系统设计的写法是:首先要归纳商品中有哪些功能点,也有系统设计的流程图,这个流程图呢就不是需求文档那个页面逻辑的流程图了。是代码的流程图。里面
有规定到我们具体使用的哪个方法,类都要写清楚了。里面包括了有哪些字段。比如商品中设计到十几个字段,那么这十几个字段都得写。以及涉及到的数据库
表,数据字段都要写清楚了。
但这是我们原来传统的项目这样写。现在要做的是敏捷是开发,客户那边直接派人来我们公司驻扎,一些需求啥的我们和客户现场去定,定好之后就马上开发,叠加几个功能点测试,
测试没问题的话就很快发布了。
现在就是系统设计需求文档用的不多了,现在我们用这个现代化的管理工具了,比如springmvc里面有一些丝袜个第三方api文档,他可以生成记录文档的信息,就是前台能够显示出来的页面的
就是一中架构风格,可以直接通过URL访问controller,我们前后端分离的项目不都是采用这样的方式架构的么.
第一种用数据库配合着解决:
怎么配合呢咱们这边不是发送的商品的ID么,在发送之前把ID记录在数据库里面去,然后设置一个状态字段,0代表这个消息已经
发送成功。然后存在数据库里面,然后我们的状态就是0,然后就让往消息的队列里面去发去,就是时候我说第一种情况突然断电了
的从新发送一下消息,这样是不是就可以解决断电的问题了,第二种我们如何去接受到一个消息,确定这个消息是消费了,这样也是
用我们的数据库来解决,如果这个消息消费了我们把这个消息状态设置为1,然后根据ID去数据库里面,把他的状态设置为1,如果为0就是
他上个消息没发送的问题了,这个我的消费。如果消费失败的话,就不会改变他的状态,还是0呗。这就是消息队列如何解决消息
同步的问题,还有突然断电的问题。
第二种解决:
在发送消息的时候设置提交的方式,改成手动提交的方式,在后台改成commit状态改成手动方式,如果发送成功的话,
然后commit手动提交方式。
问:Zookeeper关掉以后还能使用?还能调用服务?调用服务的时候是不是不经过zookeeper?
答:zookeeper关掉以后还能使用,你先是一个服务,然后注册到zookeeper,服务消费者第一调用的时候要拿到服务提供者的地址跟端口号。通过地址端口号用rpc可以调用。
不使用zookeeper服务可以调用dubbo框架么?
可以,Dubbo将注册中心进行抽象,它可以外接不同的存储媒介给注册中心提供服务,有zookeeper,
问:在一个项目里引用多个服务,怎么保证你引用的那个服务就是那个服务?
答:你打开不是有监控中心,你可以看服务后台它注册了多少个服务,消费端有多少个,提供者有多少个。端口号不同,一个服务启动起来会占用一个端口,而且是一个javajvm的进程。如果一台服务分配到两三台机器,会给负载均衡策略的。
问:负载均衡是怎么实现的?
答:所谓负载均衡就是对多台服务器进行流量分发一种服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。
问:用过线程池么?
答:现在都是了解,真实项目里面我们现在使用的是中间件,基本不使用线程去完成。
问:线程池怎么配的?
答:线程池在java里面有一个Executors,通过Executors可以方便的生成不同类型的线程池。但是要更好的理解使用线程池,就需要了解线程池的配置参数意义以及线程池的具体工作机制。
对于nginx,其实内容比较多,我还专门从淘宝上看了,有专门的书籍来介绍nginx,(或者说我还专门买了一本书,研究了一下),这里呢,我就介绍个大概吧。
在nginx源码层面上呢,它使用的是linux内核提供的一个新的叫做epoll的功能。可以实现单线程支持高并发的连接和请求.nginx底层实现,也是c语言的实现,指针这块用的非常灵活.它的机制是采用了事件驱动机制.之前我们要是解决高并发的话,肯定会第一用多线程,但是这个nginx它的一个主要优势采用的是单线程异步驱动这种形式来解决高并发,当然,再里边我确实还没有看到.
咱们还是说一下nginx两大主要的功能吧,一个是反向代理,一个是负载均衡,先说一下这个反向代理,那说反向代理,咱们还得先说一下正向代理,其实咱们平时调试开发都是正向代理,只不过我们不说这个词.比如吧,我们访问一台tomcat,默认端口号是8080,那我们访问的时候可能就是localhost:8080,这样顺着来呢,就可以理解成一个正向代理,就这样理解哈,其实正向代理这个概念呢我查过,严格来说呢是位于客户端和原始服务器之间的服务器。
这个时候,如果我们想要再来一台服务器呢,我们可以配一下,把端口号改成8081,通过访问不同的端口号来访问,但是当我们项目要上线的时候,如果需要把一个项目如果部署到两台服务器上,比如淘宝,这么大,它的主界面不可能是在一台服务器上放着,就不能是访问8080或者8081这些端口了,这个时候,需要有一个代理的服务器,能够给这两台服务器做一个代理,直接不需要进行标明,就可以访问到任意一台服务器,找到这个主界面。这里呢,这个代理就可以代理这些服务器了,这个时候这个代理,我们可以理解成反向代理。反向代理严格的概念是通过代理服务器来接收网路上的请求,然后将请求转发给内部网路的服务器。而nginx可以干这个活,做这个代理,我们可以在nginx中配置端口,ip或者域名指向这些不同端口,甚至不同ip的服务器。这就是反向代理这个概念。
Nginx还有一个重要的功能叫做负载均衡,我们做服务器的集群,怎样保证集群中服务器被均等的进行访问呢,不能说我们认为搭建好了服务器的集群它就会均衡的去访问,这个时候我们可以统一的去访问nginx这个服务器,在nginx的配置信息中,去配置好这些服务器,它配置文件是这样的,只要你配上,默认访问的比率就是一样的,这个就是负载均衡,当然nginx更厉害的是可以配置权重,比如说哈,我两台服务器,其中一台性能比另外一个性能好2倍,那我是不是应该访问性能好的服务器频率更高一些,咱们就可以在nginx的配置文件中配置一个weight属性,指定权重。当然还有其他一些配置的,比如有些服务器需要整修,那咱们就可以配置某台服务器暂时down掉,这样用户访问的时候,就不会访问到这台服务器,当修好之后,我们在把这个配置信息干掉就行了。
其实,在公司里开发,我经历的这几家都配置了nginx的服务器,按照规范的做法的话,我们公司里边应该是有两台nginx服务器,一主一备,在这两台服务器上呢,都安装一个keep的软件,弄一个脚本,通过keepalive来检测服务器是否运行,主机挂了就把服务切到备用的这台上,这样的话基本就不会出问题了。当然,有的小公司就直接搞一台。挂了就挂了,不过nginx服务器很少挂,因为它高负载下cpu消耗依然很低
对于nginx配置的话,上家公司倒是配置过一次,我简单说一下吧。
首先是在服务器上安装nginx,这个按照文档来就行,网上有好多安装资料,自己也整理了好多安装文档,解压,make编译,makeinstall安装,然后./nginxstart启动,nginx安装算是比较简单。
然后配置nginx,nginx的配置其实就是配一个核心文件,在nginx中的conf下有一个nginx.xml,主要是修改这个配置文件,比如咱们配置反向代理和负载均衡服务器,配置一个proxy_pass指向代理服务器,配一下upstreamserver指向要访问的ip和端口,这个可以配置多个ip,可以设置weight权重。
nginx就是一个反向代理服务器么,当时我们做的时候就是做的一个集群,就是前台一个页面配置了6个服务器,用n做的反向代理,当时我们还配了权重,就是使用n的权重,就是根据服务器的配置的高低给它设置权重的大小,后期我们设置了一个session共享的一个问题,因为我们项目不是分布式的嘛,我们用的是redis缓存保存的那个用户信息,然后把配置保存到本地去,然后去本地去配置,再去redis去数据信息,n大概就是这些东西
如果说的更深入一点的话就是听运维那边说的,n也有可能挂掉,当时我们搭建了两个n,takelaireber发送的一个贮备的n,它是发送的sintill协议,然后实时的去监控主服务器,互相监控,看这个服务器是否存活,一旦主服务器挂掉的话,它的备用服务器就会马上启动起来,我听运维的说的就是用的这个套路
当时我搭建的时候就是搭建了一个单机版,没有去搭建主备,你们要是搭配贮备n的话我跟我原来公司的运维要一下那个安装文档,然后过来给你搭一个这个主备的,你们公司用到内个nginx了吗
SpringBoot是我们最近的项目开始启用的。我个人觉得SpringBoot比以前的SpringMVC更好用,因为他的配置文件少了。原来SpringMVC的SSM整合的配置文件特别多,用了SpringBoot之后配置文件特别少了。我们用SpringBoot时结合的MyBatis去做得,SpringBoot基本上是一些YML文件,properties文件,MyBatis全程用的注解方式开发。SpringBoot和SpringMVC用法上大同小异,无非就是少了一些配置文件。启动SpringBoot服务器的时候是他自带的Tomca和Jetty服务器,可以通过main方法启动。配置上越来越简单。
线程就是可执行的代码段,线程要服务于进程,一个进程有好多个线程,main方法就是主线程,多个线程同时执行就是多线程,线程池就是把准备好的线程放到线程池里,如果处理请求需要调用线程的时候,就从线程池里去调用,用完以后再放回到线程池里,这样就防止高并发节省资源。
我们公司有要求做单元测试,但是都是后期补的,有的补全了,有的没补全,主要是我们公司里没有QA,所以这一块要求的不严,其实断言就是断定结果的,就是符合我们预期输出的结果就返回true不符合返回false给出错误信息
@Before
初始化方法
@After
释放资源
@Test
@Ignore
忽略的测试方法
@BeforeClass
针对所有测试,只执行一次,且必须为staticvoid
@AfterClass
@RunWith
指定测试类使用某个运行器
@Parameters
指定测试类的测试数据集合
@Rule
允许灵活添加或重新定义测试类中的每个测试方法的行为
@FixMethodOrder
指定测试方法的执行顺序
我们公司的项目边界都是架构师和项目经理定的,这个我没参与过.
项目边界其实就是针对整个项目要完成到什么程度的一个定义,就是至少需要哪些个功能点啦,达到什么样的要求,都可以称之为项目边界。
用的zookeeper,我们开发的时候用的是1台服务器,然后上线的时候用的是3台。
我们开发的时候用的是windows版本的redis,然后是部署的时候是部署在linux系统上的,搭建了一个集群,是搭建了有6台服务器,6个节点。这6个节点是3主3备。Redis那边是有一个运行原理,是有一个那个乒乓协议,他们之间是可以发送心跳包,检测之间的节点是否存活。如果不存活的话,他内部是有一个投票选举机制,超过半数说这个节点死亡的话,就直接把这个节点排除出去了,然后让他的从节点工作,之后运维的人员把主节点修复好了,重新部署好了。然后redis会重新发送心跳协议包。差不多就是这个样子。
我们当时搭建的时候是搭建了一个Solr集群,我们搭建的这个集群的节点是靠的Zookeeper管理的,我们当时搭建的时候是搭建了三个zookeeper,四台Solr服务器来完成分片式的处理---solrcloud,当其中的一个Tomcat出现异常的时候,其他备用的Tomcat就会启动,继续工作,运维再去修复主节点的Tomcat,这样就不会出现互联网项目无法访问的情况,是我们开发的时候主备服务器的策略,
MyCat一个新颖的数据库中间件产品支持mysql集群,或者mariadbcluster,提供高可用性数据分片集群。MyCat分片根据其切分规则的类型,分为垂直切分和水平切分我们在项目中用的是水平切分。前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。
它支持MySQL、SQLServer、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,当我们的应用只需要一台数据库服务器的时候我们并不需要Mycat,而如果你需要分库甚至分表,这时候应用要面对很多个数据库的时候,就需要对数据库层做一个抽象,来管理这些数据库,而最上面的应用只需要面对一个数据库层的抽象或者说数据库中间件就好了,这就是Mycat的核心作用。所以也可以这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象。
用过,Docker就是为了缩短代码从开发、测试到部署、上线运行的周期,能让项目具备可移植性,易于构建,并易于协作。(通俗一点说,Docker就像一个盒子,里面可以装很多物件,如果需要这些物件的可以直接将该大盒子拿走,而不需要从该盒子中一件件的取。比如说我们可以在这个容器里装好zookeeper,redis,mysql,tomcat等软件,用的时候直接用就可以,项目部署的时候,直接把当前的Docker给测试组就可以,或者是运维项目组就行.)
当然有了,因为我们项目比较大访问用户也比较多,我们把表都用mycat进行拆分了,我们当时拆分的方式是(说下第29题),我们在支付的时候,和下单的时候都用到了分布式事务.比如实时支付吧,一笔支付,是对买家账户进行扣款,同时对卖家账户进行加钱,这些操作必须在一个事务里执行,要么全部成功,要么全部失败。而对于买家账户属于买家中心,对应的是买家数据库,而卖家账户属于卖家中心,对应的是卖家数据库,对不同数据库的操作必然需要引入分布式事务。还有就是用户下单买家在电商平台下单,往往会涉及到两个动作,一个是扣库存,第二个是更新订单状态,库存和订单一般属于不同的数据库,需要使用分布式事务保证数据一致性。我们使用的解决方案是使用支付宝用得那个TCC补偿性分布式事务解决方案.
TCC是三个英文单词的首字母缩写,分别对应Try、Confirm和Cancel三种操作,这三种操作的业务含义如下:
Try:预留业务资源
Confirm:确认执行业务操作
Cancel:取消执行业务操作
1、Try:尝试执行业务。
完成所有业务检查(一致性)
预留必须业务资源(准隔离性)
2、Confirm:确认执行业务。
真正执行业务
不做任何业务检查
只使用Try阶段预留的业务资源
3、Cancel:取消执行业务
释放Try阶段预留的业务资源
我给你用这个账务拆分为说一下TCC吧,比如说我们账务拆分的业务场景是,分别位于三个不同分库的帐户A、B、C,A账户和B账户一起向C账户转帐共80元:
完成所有业务检查(一致性):检查A、B、C的帐户状态是否正常,帐户A的余额是否不少于30元,帐户B的余额是否不少于50元。
预留必须业务资源(准隔离性):帐户A的冻结金额增加30元,帐户B的冻结金额增加50元,这样就保证不会出现其他并发进程扣减了这两个帐户的余额而导致在后续的真正转帐操作过程中,帐户A和B的可用余额不够的情况。
真正执行业务:如果Try阶段帐户A、B、C状态正常,且帐户A、B余额够用,则执行帐户A给账户C转账30元、帐户B给账户C转账50元的转帐操作。
不做任何业务检查:这时已经不需要做业务检查,Try阶段已经完成了业务检查。
只使用Try阶段预留的业务资源:只需要使用Try阶段帐户A和帐户B冻结的金额即可。
释放Try阶段预留的业务资源:如果Try阶段部分成功,比如帐户A的余额够用,且冻结相应金额成功,帐户B的余额不够而冻结失败,则需要对帐户A做Cancel操作,将帐户A被冻结的金额解冻掉。
Github上有他们的源码,我们直接把源码挡下来,安装到我们本地的仓库里,用的时候我们把需要使用分布式事务的代码,上加上@Compensable注解,里面还有一些其他的属性配置上就可以了
日志处理我们使用的是log4j,有一个log4j的配置文件,可以配置log输出的位置以及log的输出形式,并指定内容拼接方式。
对于整个项目,设置了一个全局异常,当出现异常信息的时候,将异常信息记录到log中
Loggerlogger=LoggerFactory.getLogger(GloableException.class);
logger.error("-------------出错了------------------");
当有些需要记录内容的信息,也可以通过日志文件进行记录。
对于用户登陆日志记录,我们需要自己封装一个日志记录的工具类,可以将用户登陆的信息记录到数据库中。(具体操作步骤看如下链接)
悲观锁思路
解决线程安全的思路很多,可以从“悲观锁”的方向开始讨论。
悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。
乐观锁思路
这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。
有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。
对于不可逆的加密算法有
MD5和SHA,通过散列算法进行加密SHA加密比MD5安全性更高,常用SHA-256加密算法。
DES加密算法,对称加密,客户端和服务端公用一个key,该key最好是随机生成,对于这种加密算法加密效率高,但是据说24小时以内可以破解。
AES加密算法,不对称加密算法,通过公钥加密,私钥解密,私钥加密,公钥验证签名。(支付宝)是目前比较安全的加密算法,但效率偏低。安全性是DES加密算法的1000多倍数。
(1)MySQL:中小型数据库,开源免费,轻便简单
Orcale:大型数据库,价格高昂,性能好,支持大并发,大访问量
(2)MySQL:主键自增
Orcale:不能主键自增
(3)mysql:可以用双引号包字符串
Orcale:要用单引号
(4)MySQL:分页关键字limit实现
Orcale:用ROWNUM,实现复杂
ERP是一种企业资源管理与业务流程管理的计算机系统,对企业内部所有的经营活动,包括采购,财务,人力资源,物料等等的整合,最终达成高效化经营的目的。
前后端交互会用到接口,三要素:URL,参数,返回值类型,请求方式get,post
大概有几百个,涉及到接口三要素的就是接口
就是解决项目中的问题,solr,redis,等等。
产品经理:沟通一些业务逻辑、功能点。
测试人员:把一些bug提交到BugFree的平台,有哪些bug然后改一下
一般都是项目经理定的,规定一下项目工作日,根据功能点来估计一下工作日
比方说公司要用redis,买一些关于redis实战的书进行学习,网上也找找关于redis方面的资料进行学习,遇到一些问题问问我们项目组长,技术总监,他们有什么响应的解决方案,然后自己去解决去。
内存溢出指的是jvm内存溢出,通过调整堆,栈的大小来解决。
代码中出现死循环或递归调用也会造成内存溢出。
内存泄漏(MemoryLeak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果
再说算法之前,我们来先说一下JVM中的新生代和老年代,新生代就是用来存放刚被new出来的对象,一般情况下占堆的1/3空间。而新生代中又分为
3个区:Eden区java新对象的出生地,当内存不够的时候就会带有调用MinroGC,对新生代进行回收。
ServivorTo:保留MinroGC一次的幸存对象
ServivorFrom:上次的幸存者,被这次gc的对象
老年代:存放应用程序中生命周期长的内存对象
然后,我们的JVM回收算法有4种
第一种:标记-清除法
分为:标记,请除
标记阶段:直接在内存里标记无用的对象,然后清除阶段直接回收被标记的对象;
缺点:形成内存碎片,一些大的对象无法找到足够的空间而触发新的垃圾收集动作。
第二种:复制算法:
将内存划分为大小相等的两块,当一块的内存用完了,就讲还存活的对象复制到另外一块上面,然后将之前的那块清理掉
缺点:浪费内存太多(对老年代的使用,效率低)
第三种:标记-整理算法
将存活的对象都向一端移动,然后直接清理掉这端边界以外的内存
第四种:分代收集算法:(当前商业虚拟机都采用这个)
根据对象的存活中期的不同将内存划分为几块,一般Java堆分为新生代和老年代
新生代:用复制算法老年代用标记整理算法进行回收
1、由于移动端app一般时不能直接访问数据库的,所以需要我们Java后台开发接口,供移动端去调用;
2、App接口的开发一般都是restful风格的接口。就是不需要跳转页面,都是直接返回需要的数据。所有的方法上都需要@ResponseBody注解,把返回结果转换成json。所以我们一般用@RestController代替@controller;
3、因为app接口如果获取不到想要数据,就很可能发生闪退,所以我们需要在controller中的所有方法中,用trycatch捕获异常,把异常也返回。
4、为了让用户识别异常,我们一般需要定义一组错误编码。
5、由于接口比较多,为了方便客户端处理接口返回数据,我们定义了一个统一的返回对象类。里边主要包含三个参数:Booleansuccess,Stringcode,Objectdata;
7、在接口的拦截器里边,采用对称加密的方式,进行签名认证。对称加密就是服务端给调用端一个appid和一个appsecret;
8、接口文档:接口说明、接口的url,传入参数、响应参数。
9、接口自己测试:一般在浏览器上安装一个restclient的插件,用这个插件就可以测试。
接口的调试:方法一:手机连接公司的内外;方法二:通过Nginx把自己的ip代理到外网。
我之前接触过一个B2B的电商,他们由于交易金额比较大,第三方支付无法实现,所以是直接和银行对接。大体上是,首先平台和银行签订合同,银行为平台开设一个总账号,当企业在平台注册以后,平台会为企业调用银行接口,创建一个子账号,这个子张号是挂在总账号下边的,也是一个在银行实际存在的账号,但是,只能通过外部银行卡给里边转账,而不能给外部银行卡转出。可以在子行号直接互相转账。
关系型数据库是表与表之间有关系比如一对多,多对一,等值连接什么的,非关系型数据库就是里面没有多张表,没有什么关联
@Autowired默认的是按照类型进行注入,如果没有类型会按照名称(红色字体)进行注入.
如果想直接按照名称注入需要加入@Qualifier("gatheringDao")
@Autowired
@Qualifier("gatheringDao")privateGatheringDaogatheringDao;
@Resource默认的会按照名称注入,名称找不着会按照类型来找,如果这里写了名称,就直接按照名称找了不会按类型找@Resource(name="aaa")
@ResourceprivateGatheringDaogatheringDao;
我们使用springdatamongodb
mongodb是非关系型数据库最像关系型数据库的一种数据库,我们一般还是用它当存储去用,但是Redis是key和value方式存储的,我们可以把他用来优化项目,把一些频繁访问的数据存到redis中,不用频繁的访问数据库了,给mysql数据库减轻压力.
所谓热词就是用户经常搜索到的词语,我们给他放到自己的分词器里当成一个词进行搜索,比如说经常说的”大吉大利今晚吃鸡”,这样的词就可以当做是热词,我也没在项目里实际的做过,但是我知道在大数据里有一个wordcount技术可以实现这个热词分析,就能给你添加到自定义词典中.
Ogstash本来就很吃资源,如果你做数据同步的服务器,配置必须得高,内存怎么也得几十个G,现在银行里的数据几乎都是TB级别的内存了,所以这个可以用硬件去解决这个问题.还有就是这个数据不一定非得是实时.
笑。大家在面试过程中一定要学会笑。笑可以减少紧张情绪,笑可以缓解尴尬,微可以拉近和面试官的距离。大家记住一点,面试官都讨厌总是面试,他非常希望你能成功。所以不要因为回答不上问题而苦着脸,不要尴尬,尴尬时就傻笑。
面试过程中,要对自己有信心,还要让面试官对你有信心。所有的答案都要给面试官肯定的回答。坚决不能说,可能、或许、好像这样的词语。
一句话:“技术不行,业务补”,针对你的第一个项目,多想想,仔细想想,打好草稿,你的项目是做什么的,主要业务流程是什么,你的模块的独特性在哪里,项目主要有哪些用户,项目的亮点在哪里,赢利点在哪里,同类竞争网站有哪些。项目的主要架构是什么样的,开发过程中遇到了哪些问题,有哪些问题是遗留没有解决的。等等。首先给自己定一个目标,打一份草稿,这份草稿,可以保证你,面试官一句话不说,你自己介绍项目就能介绍30分钟以上。可能面试的时候,很多面试官不给你说业务的机会,但是你一定要有所准备,当技术说不上来的时候,就说业务,用业务来描述技术。当然在描述业务的时候,也不能光说业务,在业务中引出技术,只有说出为什么在这块要使用这个技术,使用这个技术做什么,用它有什么好处就可以了。
银行创想,长期招聘不招人;
公司不会一直招人,招够了就不招了
1、项目架构
2、项目框架
面试中,成功的最佳办法,就是不断给面试官传递正能量,告诉面试官,
1、我能吃苦,我能加班,我能出差。
2、给我分配了任务,我就会积极去解决,不会逃避,不找理由,不找借口,方法总比问题多。只要用心,就没有解决不了的问题。
3、我有很强的学习能力,经常喜欢去网络上自己学习。
4、我有很多同行业的朋友,我们经常交流,互相帮助。
5、我认为技术没有难不难,只有会不会,我们这一行业新技术层出不穷,关键在于学习力,我对我的学习力还是非常自信的;
6、这个技术点,如果让我做,我肯定能做,就是不知道该如何表达。
1、那么为什么面试官总是比你懂呢?胆大、心细、脸皮厚;
面试时,一定要自信,你掌握的知识点是最新的,是很高大上的,你的知识面是非常广的,已经站在了市场上开发程序员的80%以上。那么为什么面试官总是比你懂呢?不是面试官比你懂,而是他在问,你在答,他可以不懂装懂。所以只要你自信点,把你的话术说出来就OK了。面试官听你说的自信,他就认为你懂了,看你说的不自信,就会认为你也就懂点皮毛。
2、总是有几个问题,被追问,一问就不知道怎么回答了怎么办?
3、技术在精,不在多。
如果你的能力有限,记忆力不行,就可以在项目里少写几个技术,但是功能模块不能少,有很多人,在企业里边3-5年,只做了1-2个项目,用的还知识SSH框架,从来没有用过springmvc,redis、solr、工作流等,但是他再找工作时,也非常自信,因为他在企业里边真正工作过了几年,他觉得自己的能力就值这个钱。所以如果你的学习能力、记忆能力差,那么大部分技术,掌握个基础就可以了,知道他是做什么的,用它有什么好处就OK了,只要找一个技术点,可以掌握的很扎实就可以了。
4、总时被问到底层怎么办?
5、吹的这么厉害,到了公司做不了怎么办?
实际的经验告诉我们,面试时的问题,和你在工作中遇到的技术,差别大部分时候是差别很大的。之前毕业的学长都告诉我们,面试时问了一大堆,结果到了公司,做的项目中没有用到几个高大上的技术,即使使用了,也都是别人已经封装配置好了,你只需要直接使用就可以了,并且还有使用的例子。
6、总是被查学历怎么办?
问;“你这个学历是14年的本科,但是我网上查到,你这个学校是15年才从大专转成本科的啊”?
学生答;“您是百度查的吧”;
面试官:“是”;
学生答;“那就对了”;
面试官:“嗯,怎么就对了?”;
学生官:“之前也有人问过我这个问题,我也不知道怎么回事,学校申请升本很多年了,有些专业是本科,有些是专科的,我也不知道怎么回事,我读大学时,学校告诉我本科比专科会多次2000元学费,我肯定就学本科了啊”;
面试官:"还能这样,你怎么上的大学";
学生答;“考上的啊,我也不知道怎么回事”;
之后这个学生就收到了offer,入职时,学生办理入职手续。hr给了学生一张表,让学生填写,hr直接上网去查学生的学历,问学生:“你的学历怎么差不到呢”?
学生答:“您是不是查错了,再查查”;
hr:"还是查不到,你自己查过吗?";
学生答:“没有啊,都是国家给的,我也不太清楚”;
hr:“那你明天把原件带过来吧?”;
学生答:“好”;
结果几个月过去了,学生一直没有带原件过来,hr也没有再问过。
7、面试了很多家,还是没有成功?我是不是该降低标准呢?
降低标准可以,但是不能太离谱了,简历相应要进行修改。工作是自己争取来的,绝对不是请求别人施舍过来的,做软件的公司都不缺钱,但是绝不会施舍。你简历包装1年,企业不给你面试机会,很正常,企业不需要初级的开发人员,企业不缺钱,是希望能招到能干活的人,而不是不能干活,还会拖慢进度的人。但是你包装了3年,有面试机会了,你本来说的还可以,问你要多少钱,你说我要8k,那么你作为一个面试官你会怎么想,10K以下的程序员都是初级的,工作3年了,还是一个初级,你敢相信吗?你会怀疑吗?。第二个问题,问你期望多少,你说15k,面试官问,能谈吗,10K接受吗?你说可以。这时候面试官怎么想?你会相信这是真的吗?所以,万事一定要把握一个度。
8、白天面试了一天很累,面试回来就回去休息了,或者打几把游戏。背话术时总是走神,心里总是惦记着游戏、小说或者电视剧,这样能被会吗?所以面试时,一定不能分心。白天去面试,面试必录音,面试结束后就回学校,回教室,找同学、找老师、百度、听录音,把自己面试中遇到的问题,总结一下,弥补自己的不足。这样,你第二天再去面试时,肯定会更有信心。如果能坚持这样,面试一次学到至少1个技术点,面试10家以后,还有什么理由不成功呢。10个技术点不够,面试20家,是不是就能学到20个知识点,还不够30、40、50、呢?只要我们坚持,不放弃,认证对待。那么世上无难事,只怕有心人。
9、有些人有说了,老师我非要找工作吗?找不到这个工作,我就不行了吗?
最后送大家一句话:学校就是你们的家,我就是你们的后盾,面试过程中,一定要经常回学校来做复盘,工作中遇到问题,也要首先想到学校,想到
穆总。没有任何一所学校能向八维这么对每一个学生负责,希望大家学会感恩,穆志军
1、面试中,切忌怀疑自己:即使说错了,也要坚持。只能说,可能是我理解的不够深,不太理解您的意思,不过这个使用肯定是没有问题。
2、面试中,切忌靠大牛:千万不要说,这个问题是我和另一个大牛一起做的,他主要我辅助这种话。如果不太懂,可以直接说,这个不太理解,之前项目中只是根据网上的一些方法或者api直接copy做的,或者直接网上找的一个工具类,直接调用。还没有来的及去深入了解。
3、面试中,切忌太多的可能、好像、不肯定语句:面试过程中,你一定要给面试官肯定的答案,会就是会,不会就是不会。不要说太多可能、好像等话。除非你是在说思路。
4、面试中,不要因为怕自己理解的太浅,而不说:面试过程中,一定要懂多少,就要尽可能的说出来,不要怕说错,更不要怕追问。被质疑了或者追问了,再说可能理解的不够深,最好能反过来向面试官请教;
5、面试中,切忌一问一答方式:把面试一定要当成一场聊天,每个问题就是一个话题,不是面试官在问,你在答,你也可以反问,可以转移话题,最好的方式是把问题展开来聊,不要局限于问题本身,加入一些业务,加入一些开发中间遇到问题、解决问题的过程。你只要把面试官聊开心了,你的面试也就成功了。哪怕面试过程中,都是你在请教面试官在答。
6、面试中,切忌和面试官较真:当然如果你能在面试中,和面试官因为一个问题争吵起来,那么说明你离面试成功已经很近了,只要稍微注意谦虚点,让一让面试官就OK了。
7、面试中,切忌怀疑自己说的太low,而不好意思说:面试过程中,要把面试官当成小孩,耐心的给他讲解你这个知识点的开发过程,不要把面试官想的太高大上,等面试官的思想和你同步。一定要多说,不厌其烦的说,等面试官不想听了,去打断你。
如果面试官说:3天内或者一周内,那么就说:“这个能不能稍微快点呢,我之前面试了一家,让我明(后)天就去入职,就是离我家太远了,我也不想再多面试了”;