6. springmvc的工作流程是什么?
SpringMVC流程
1、 用户向服务端发送一次请求,这个请求会先到前端控制器DispatcherServlet(也叫中央控制器)。
2、DispatcherServlet接收到请求后会调用HandlerMapping处理器映射器。由此得知,该请求该由哪个Controller来处理(并未调用Controller,只是得知)
3、DispatcherServlet调用HandlerAdapter处理器适配器,告诉处理器适配器应该要去执行哪个Controller
4、HandlerAdapter处理器适配器去执行Controller并得到ModelAndView(数据和视图),并层层返回给DispatcherServlet
5、DispatcherServlet将ModelAndView交给ViewReslover视图解析器解析,然后返回真正的视图。
6、DispatcherServlet将模型数据填充到视图中
7、DispatcherServlet将结果响应给用户
7. mybatis的工作原理是什么? mybatis的缓存的理解?
Mybatis工作原理
1.通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件中构建出SqlSessionFactory。
2.SqlSessionFactory的实例开启一个SqlSession
3.SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交以及事务失败的回滚,之后关闭Session。
mybatis的缓存的理解?
当一个查询发生的时候,Mybatis 会在当前会话中查找是否已经有过相同的查询,有的话就直接拿缓存,不去数据库查了,线程执行完毕,缓存就被清掉了。二级缓存是进程级别的,通过在 mapper 文件中增加节点来启用,一个mapper可以含有多个会话。
8. mybatis中#{}和${}的区别?
#{}是预编译处理,${}是字符串替换;
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}时,就是把${}替换成变量的值;
使用#{}可以有效的防止SQL注入,提高系统安全性。
9. springboot的异常处理?
SpringBoot中有一个ControllerAdvice的注解,使用该注解表示开启了全局异常的捕获,我们只需在自定义一个方法使用ExceptionHandler注解然后定义捕获异常的类型即可对这些捕获的异常进行统一的处理。
10. spring中如何配置拦截器、过滤器?
创建一个拦截器,实现HandlerInterceptor接口,重写此接口的三个方法,preHandle、postHandle、afterCompletion,只有第一个方法返回true时,才会进入Controller,否则不会处理Controller内容,也不会执行后边两个方法。
然后在xml文件里配置拦截路径
过滤器:定义一个类实现Filter接口
这一接口含有三个过滤器必须执行的方法:
doFilter(ServletRequest, ServletResponse, FilterChain):这是一个完成过滤行为的方法。这同样是上游过滤器调用的方法。引入的FilterChain对象提供了后续过滤器所要调用的信息。如果该过滤器是过滤器链中的最后一个过滤器,则将请求交给被请求资源。也可以直接给客户端返回响应信息。
init(FilterConfig):由Web容器来调用完成的初始化工作。它保证了在第一次doFilter()调用前由容器调用。您能获取在 web.xml 文件中指定的初始化参数。
destroy():由Web容器来调用来释放资源,doFilter()中的所有活动都被该实例终止后,调用该方法。
配置过滤器:在web.xml配置文件里配置filter和filter-mapping的<url-pattern>/*</url-pattern>属性即可
11.spring管理的bean是否会存在并发?
Spring的bean默认scope属性为singleTon,即单例的,有线程安全问题
如果设置@Scope(“prototype”),则每次都会创建新对象,不存在线程安全问题
12.spring-session的原理是什么?
Spring Session是为了解决多进程session共享的问题
原理:拦截请求,将之前在服务器内存中进行 Session 创建销毁的动作,改成在 Redis 中创建。
13. spring的类加载器是什么?
ClassLoader即常说的类加载器,其功能是用于从Class文件加载所需的类,主要场景用于热部署、代码热替换等场景。
从java虚拟机的角度讲,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),由C++实现,另一种就是所有其它的加载器,是由java实现的,独立于虚拟机外部,并且全都继承自java.lang.ClassLoader。
从java开发人员来讲,类加载器还可以划分的更细致一些:
1、 启动类加载器(Bootstrap ClassLoader):这个类加载器负责将存放在<JAVA_HOME>\lib目录中,或者被-XbootClasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法直接被java程序引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可。
2、 扩展类加载器(Extension ClassLoader):这个加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量所指定的路径中的类库,开发者可以直接使用扩展类加载器。
3、 应用程序类加载器(Application ClassLoader):这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器,它负责加载用户类路径(classpath)上指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中的默认类加载器
14. springCloud的组件有哪些?作用分别是什么?
eureka (提供服务注册与发现功能)
ribbon(提供负载均衡功能)
Feign(整合了ribbon和Hystrix,具有负载均衡和熔断限流等功能)
Ribbon 和 Feign 的区别
Ribbon基于http和tcp的客户端负载均衡工具,通过restTemplate模拟http请求 步骤相当繁琐
Feign在ribbon的基础上进行过改进,使用起来更加方便 并且他默认集成了ribbon的负载均衡机制
Hystrix (提供了熔断限流,合并请求等功能)
Zuul (提供了智能路由的功能)
Hystrix Dashboard (提供了服务监控的功能,提供了数据监控和友好的图形化界面)
Hystrix Turbine (Hystrix Turbine将每个服务Hystrix Dashboard数据进行了整合。也是监控系统的功能)
spring cloud config (提供了统一配置的功能)
Spring Cloud Bus (提供了配置实时更新的功能)
15. dubbo和 springcloud的区别和优缺点?
dubbo由于是二进制的传输,占用带宽会更少
springCloud是http协议传输,带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大
dubbo的开发难度较大,原因是dubbo的jar包依赖问题很多大型工程无法解决
dubbo的注册中心可以选择zk,redis等多种,springcloud的注册中心只能用eureka或者自研
16. Gateway的动态路由如何实现?
配置Nacos监听器,监听路由配置信息的变化
创建配置类
添加Nacos路由配置
测试
启动网关通过 /actuator/gateway/routes 端点查看当前路由信息
17.鉴权框架的了解和使用?
一般有shiro和spring-security
第一步:
构建一个spring boot工程,这个利用idea的Spring Initializr很容易就构建了
第二步:
引入spring boot为spring security的包装的起步依赖,也就是上面提到的spring-boot-starter-security
spring security和shiro的异同
相同点
1、认证功能2、授权功能3、加密功能4、会话管理5、缓存支持
6、rememberMe功能
不同点
1、Spring Security 基于Spring 开发,项目若使用 Spring 作为基础,配合 Spring Security 做权限更加方便,而 Shiro 需要和 Spring 进行整合开发;
2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;
3、Spring Security 社区资源相对比 Shiro 更加丰富;
Spring Security对Oauth、OpenID也有支持,Shiro则需要自己手动实现。而且Spring Security的权限细粒度更高
spring security 接口 RequestMatcher 用于匹配路径,对路径做特殊的请求,类似于shiro的
抽象类 PathMatchingFilter,但是 RequestMatcher 作用粒度更细
4、Shiro 的配置和使用比较简单,Spring Security 上手复杂些;
5、Shiro 依赖性低,不需要任何框架和容器,可以独立运行.Spring Security 依赖Spring容器;
6、shiro 不仅仅可以使用在web中,还支持非web项目它可以工作在任何应用环境中。在集群
会话时Shiro最重要的一个好处或许就是它的会话是独立于容器的。
apache shiro的话,简单,易用,功能也强大,spring官网就是用的shiro,可见shiro的强大
18. mybatis同时操作同一条数据该怎么解决并发问题?
乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。
读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
对于上面修改用户帐户信息的例子而言,假设数据库中帐户信息表中有一个version字段,当前值为1;而当前帐户余额字段(balance)为1000元。假设操作员A先更新完,操作员B后更新。
a、操作员A此时将其读出(version=1),并从其帐户余额中增加100(1000+100=1100)。
b、在操作员A操作的过程中,操作员B也读入此用户信息(version=1),并从其帐户余额中扣除50(1000-50=950)。
c、操作员A完成了修改工作,将数据版本号加一(version=2),连同帐户增加后余额(balance=1100),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录version更新为2。
d、操作员B完成了操作,也将版本号加一(version=2)试图向数据库提交数据(balance=950),但此时比对数据库记录版本时发现,操作员B提交的数据版本号为2,数据库记录当前版本也为2,不满足 “提交版本必须大于记录当前版本才能执行更新 “的乐观锁策略,因此,操作员B的提交被驳回。
这样,就避免了操作员B用基于version=1的旧数据修改的结果覆盖操作员A的操作结果的可能。
悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适
19. mybatis中传递参数有哪些方式?
方式一、顺序传递参数
mapper.java文件:
publicUserselectUser(String name,intdeptId);
mapper.xml文件:
<selectid="selectUser"resultType="com.wyj.entity.po.User">select * from user where userName = #{0} and deptId = #{1}</select>
注意:里面的数字代表你传入参数的顺序,不是特别建议使用这种方法传递参数,特别是参数个数多的时候
mapper.java文件:
publicUserselectUser(@Param("userName")String name,int@Param("deptId")id);
mapper.xml文件:
<selectid="selectUser"resultType="com.wyj.entity.po.User">select * from user where userName = #{userName} and deptId = #{deptId}</select>
注意:在xml文件中就只能以在@Param注解中声明的参数名称获取参数
mapper.java文件:
publicUserselectUser(Map<String,Object>params);
mapper.xml文件:
<selectid="selectUser"parameterType="java.util.Map"resultType="com.wyj.entity.po.User">select * from user where userName = #{userName} and deptId = #{deptId}</select>
mapper.java文件:
publicUserselectUser(User user);
mapper.xml文件:
<selectid="selectUser"parameterType="com.wyj.entity.po.User"resultType="com.wyj.entity.po.User">select * from user where userName = #{userName} and deptId = #{deptId}</select>
20. spring中bean的作用域有哪些?生命周期?
Bean 的生命周期
1 单例bean对象
1 对象创建: 当应用加载, 创建spring容器时, 对象就被创建了
2 对象存活: 只要容器存在, 对象一直存活
3 对象销毁: 当应用卸载, 销毁容器时, 对象被销毁
2 多例bean对象
1 对象创建: 当使用对象时, 创建新的对象实例
2 对象存活: 只要对象在使用中, 对象一直存活
3 对象销毁: 当对象长时间不用时, 被java的垃圾回收器回收
21.怎么实现 mybatis批量插入?
包括以下两种具体方式:
1.mapping.xml中insert语句可以写成单条插入,在调用方循环1000次
2.insert标签加上foreach标签
测试xml:
<insert id="insertList">
insert intouser_info(id,user_name,age)values
<foreach collection="list"item="item"separator=",">
(#{item.id},#{item.userName},#{item.age})
</foreach>
</insert>
其实就是insert标签加上foreach标签
用来测试批量插入的数据和服务层:
@ServicepublicclassUserInfoService{@AutowiredprivateUserInfoDao userInfoDao;publicvoidinsertList(){List<UserInfo>userInfoList=Lists.newArrayList();
userInfoList.add(newUserInfo("1","jiejie","17"));
userInfoList.add(newUserInfo("2","jiejie","18"));
userInfoList.add(newUserInfo("3","jiejie","30"));
userInfoDao.insertList(userInfoList);}}
测试结果:
可以发现已经实现批量插入的功能了。
总结
通过insert标签加上foreach标签,可以实现Mybatis批量插入的功能。
22. Junit如何使用?
导入jar包 添加Test注解即可
springboot整合:
1.在pom.xml中添加junit环境的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
2.在src/test/java下建立测试类
例:
@RunWith(value = SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={app.class})
public class serviceTest {
@Autowired
private serviceImpl serviceimpl;
@Test
public void testAdd() {
this.serviceimpl.add();
}
}
说明:@RunWith:启动器
SpringJUnit4ClassRunner.class:让 junit 与 spring 环境进行整合
@SpringBootTest(classes={App.class}) 1,当前类为 springBoot 的测试类2,加载 SpringBoot 启动类。启动SpringBoot
23. spring的工厂模式如何使用?
1.把工厂假设为一个汽车制造厂
2.首先抽象出产品的父类
3.实现具体的产品类
4.实现一个工厂类,并写一个静态方法根据参数的不同返回不同的实例
24. springboot是如何对线程进行封装的?
配置类上加上@EnableAsync注解,就可以在想多线程支持的方法上加上@Async该方法就可以自持多线程了
25. springboot中 Starter种类有哪些?如何写一个springboot的 Starter组件?
spring-boot-starter-tomcat
spring-boot-starter-jdbc
spring-boot-starter-data-elasticsearch
spring-boot-starter-data-mongodb
spring-boot-starter-data-redis
如果你想要自己创建一个starter,那么基本上包含以下几步
创建一个starter项目,关于项目的命名你可以参考这里
创建一个ConfigurationProperties用于保存你的配置信息(如果你的项目不使用配置信息则可以跳过这一步,不过这种情况非常少见)
创建一个AutoConfiguration,引用定义好的配置信息;在AutoConfiguration中实现所有starter应该完成的操作,并且把这个类加入spring.factories配置文件中进行声明
打包项目,之后在一个SpringBoot项目中引入该项目依赖,然后就可以使用该starter了
26.设计一个开放接口,如何保证接口安全性?
1.签名
根据用户名或者用户id,结合用户的ip或者设备号,生成一个token。在请求后台,后台获取http的head中的token,校验是否合法(和数据库或者redis中记录的是否一致,在登录或者初始化的时候,存入数据库/redis)
2.加密
客户端和服务器都保存一个秘钥,每次传输都加密,服务端根据秘钥解密。
1.文件上传和下载如何实现?
文件上传
文件上传的本质是IO流的从操作;客户端:
1.必须使用post,post才能携带大数据
2.必须设置type=“file” name="file"必须要有名字
3.必须要设置enctype="multipart/form-data"服务器端:通过request.getInputStream()获取字节输入流,读取请求正文内容;将上传内容得到,保存在服务器端,就完成了文件上传;实际使用直接用框架中的api就可以,commons-fileupload是apache提供的一套文件上传工具;
文件下载有两种方法:
1.超链接下载:如果文件能被浏览器解析,点击就会打开文件,如果要下载,需要使用右键另存为,不能被浏览器解析的文件,点击就下载;
2.通过服务器流回写到浏览器下载;要设置MIME,即设置setcontentType(String mimeType);浏览器能解析的直接显示,不能解析的直接下载;
获取文件的mimeType类型:String mimeType=this.getServletContext().getMimeType(filename);
如果设置响应头response.setHeader("content-disposition","attachment;filename=下载的文件名称");不管浏览器能不能解析,
都是下载操作;
2.第三方的工作流有哪些?如何使用的?
常见的工作流框架
Activity5.1.3、JBPM4.4、OSWorkFlow、WorkFlow
在Java领域,JBPM和Activity是两个主流的工作流系统,而Activity的出现无疑将会取代JBPM(Activity的开发者就是从Jbpm开发者出来的)。
avtivity的基本操作:
设计流程图(各种组件,如连线、用户任务、网关)
流程定义增删改查
流程变量增删改查
启动流程定义
任务增删改查
完成任务
历史信息查询
java工作流怎么用activity
常用的是:activiti-engine-5.91.jar,activiti-spring-5.9.jar;
解释:以上两个只是activiti工作流的常用包,通常会配置如spring开发的java包,还有数据库jar包等进行使用,但具体要用到什么包,这个和业务开发的逻辑有关系,也没办法进行详细说明
的,所以只需要先下载常用的两个,其余的辅助包如:日志包、spring包、数据库包、hibernate包、struts包、mybatis包等根据实际需要添加即可。
3.对 activemq、 rabbitmq、 kafka的了解和使用?消息发送失败如何处理?如何防止消息的重复消费?
ActiveMQ介绍 MQ是消息中间件,是一种在分布式系统中应用程序借以传递消息的媒介,常用的有ActiveMQ,RabbitMQ,kafka。ActiveMQ是Apache下的开源项目,完全支持JMS1.1和J2EE1.4规范的JMS Provider实现。 特点: 1、支持多种语言编写客户端 2、对spring的支持,很容易和spring整合 3、支持多种传输协议:TCP,SSL,NIO,UDP等 4、支持AJAX 消息形式: 1、点对点(queue) 2、一对多(topic)
RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。
Kafka是分布式发布-订阅消息系统,它最初是由LinkedIn公司开发的,之后成为Apache项目的一部分,Kafka是一个分布式,可划分的,冗余备份的持久性的日志服务,它主要用于处理流式数据。
消息发送失败如何处理
就回滚,捕捉异常,把预处理的这条数据给删除了,数据库就没有数据了,消费方就不会有消息执行。双方数据一致。
如何防止消息的重复消费?
1、对于需要保存到数据库的数据,我们可以设置某条数据的某个值,比如订单号之类的,设置一个唯一索引,这样的话即使重复消费也不会生效数据
2、乐观锁,也就是我们每次插入一条数据或者更新的时候判断某个版本号是不是与预期一样,如果不是,那么就不进行操作
3、使用redis进行存储,每次操作数据的时候先去redis进行判断,如果存在的话,那么这条数据就是重复消费的,然后我们可以丢弃或者做其他处理。
4.svn和git冲突如何解决?
pull一下,更新程序 同步 查看冲突代码 人工修改 保持本地最新版 提交修改 再pull一下 更新 人工合并 更新到最新版 commit提交 push
5.如何测试自己的接口?
用postman swagger等工具
6.poi导入 excel时如果数据溢出如何解决?
可以将excel的xlsx格式转换为易读取的csv格式进行读取
7. linux常用命令有哪些?
1.1 pwd命令该命令的英文解释为print working directory(打印工作目录)。输入pwd命令,Linux会输出当前目录。
1.2 cd命令cd命令用来改变所在目录。
cd / 转到根目录中
cd ~ 转到/home/user用户目录下
1.3 ls命令
ls命令用来查看目录的内容。
1.4 cat命令
cat命令可以用来合并文件,也可以用来在屏幕上显示整个文件的内容。
8.如何调用第三方的接口?
SpringBoot-RestTemplate
public User doGetWith2(String url){
User user = restTemplate.getForObject(url, User.class);
return user;
}
9.分布式、集群、微服务的理解?
分布式是指将不同的业务分布在不同的地方。分布式的每一个节点,都完成不同的业务,一个节点垮了,那这个业务就不可访问了。
而集群指的是将几台服务器集中在一起,实现同一业务,集群,有一个组织性,一台服务器垮了,其它的服务器可以顶上来。
微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。
10.分布式事务的处理逻辑?怎么实现的?
这些小操作分布在不同服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败。
现在的分布式事务实现方案有多种,有些已经被淘汰,如基于XA的两段式提交、TCC解决方案,还有本地消息表、MQ事务消息,还有一些开源的事务中间件,如LCN、GTS。
11.事务的特性?分布式如何保证数据一致性?
特性:原子性,一致性,隔离性,持续性。
原子性:事物是数据库的逻辑工作单位,事物中包括的操作要么都做,要么都不做。
一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
隔离性:一个事务的执行不能被其它事物干扰。即一个事物内部的操作及使用的数据对其它并发事物是隔离的,并发执行的各个事物之间不能互相烦扰。
持续性:也称永久性,只一个事物一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响
分布式如何保证数据一致性
当更新操作完成之后,任何多个后续进程或者线程的访问都会返回最新的更新过的值。这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。
12. docker的常用命令有哪些?
基础操作:
1.docker images查看镜像信息列表 镜像是静态的
2.docker ps -a查看运行中的所有容器
3.docker pull [images]:[version]从dockerhub拉取指定镜像
4.docker rm [containerID]删除容器
5.docker rmi [imageID]删除镜像
13.模板引擎的了解和使用?
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
使用
1、导入文件
2、定义模板
3、准备对象(需要填充的数据)
4、将数据填充到模板
template(模板ID,填坑的数据)
14.项目中定时任务怎么写的?
1、实现了Runnable接口。run方法中,先打印一个当前系统时间,然后呢,接着执行sleep方法,休眠30秒
2、实现TimerTask接口。
15.如何实现邮箱和短信的发送?
邮箱:用163或者腾讯邮箱的smtp服务 创建一个第三方邮件客户端的专用密码
在邮箱工具类里把专用密码 SMTP服务器的地址 和要发送的内容 以及发送对象的邮箱地址填上即可
短信 可以用阿里云的云通信服务 在控制台里的国内消息中设置一个短信模板
把模板code和个人中心的accesskey填进工具类即可
16.两个异构项目之间的实时数据互通你会怎么做?
ESB
17. nginx的了解和使用?
nginx是一个使用c语言开发的高性能的http服务器及反向代理服务器。
反向代理方式实际上就是一台负责转发的代理 服务器,貌似充当了真正服务器的功能,但实际上并不是,代理服务器只是充当了转发的作用,并且从真正的服务器那里取得返回的数据。
使用
下载后解压
打开cmd命令窗口,切换到nginx解压目录下,输入命令 nginx.exe 或者 start nginx ,回车即可
直接在浏览器地址栏输入网址 http://localhost:80,回车,出现以下页面说明启动成功
nginx的配置文件是conf目录下的nginx.conf,默认配置的nginx监听的端口为80,如果80端口被占用可以修改为未被占用的端口即可
18. maven如何解决jar包冲突?
1.可以借助Maven Helper插件中的Dependency Analyzer分析冲突的jar包,然后在对应标红版本的jar包上面点击execlude,就可以将该jar包排除出去
2.手动排除 在pom.xml中使用标签去排除冲突的jar包
版本锁定原则:一般用在继承项目的父项目中
正常项目都是多模块的项目,如moduleA和moduleB共同依赖X这个依赖的话,那么可以将X抽取出来,同时设置其版本号,这样X依赖在升级的时候,不需要分别对moduleA和moduleB模块中的依赖X进行升级,避免太多地方(moduleC、moduleD…)引用X依赖的时候忘记升级造成jar包冲突,这也是实际项目开发中比较常见的方法。
19.树形结构的表怎么设计的?
左右值算法
20.如何实现菜单及增删改查的功能权限管理?
在admin登录时,将登录时生成的token保存到vue组件。然后查询对应的角色信息,根据角色id查询role_permission表所关联的菜单权限信息,返回给vue里面控制管理系统左侧菜单栏导航的显示
后端使用自定义注解和AOP的方式实现增删改查权限的控制
21.开发程序需要哪些文档?
可行性研究报告、需求规格说明书、项目计划、软件测试计划、概要设计说明书、详细设计说明书、编程规范、软件测试用例、软件测试报告、用户手册、安装手册、项目总结报告
1.ajax请求方式、参数类型、状态码?
2. Jquery常用的选择器?
3.前后端是如何做数据交互的?前端怎么传给后端json数据?
1.第一种:ajax
传给后台的数据通过json封装起来,再用ajax将json传到后台
2、通过form表单的action传值
一般情况下数值在传给后台之前需要校验,可以在form中的onsubmit调用js方法进行校验,当js方法返回值为true时,触发action,当js方法返回值为false时,action不触发。这样处理的好处在于当用户输入不正确时,不会刷新页面,表单仍然会保留用户之前的输入
JS方法: JSON.stringfiy(demo);
4.前端和后台都是如何解决跨域问题的?
前端
利用反向代理实现跨域
反向代理需要用到nginx
实现原理
原理大体相同,但是处理的端不同,反向代理实在服务器端进行处理。首先修改hosts文件,将域名指向开发者的电脑本身,把自己伪装成服务端,再通过nginx对不同的请求进行转发,把静态资源指向开发者本地电脑的资源,将接口指向实际的服务器。
后台
使用cors
5.前端如何防止表单重复提交?
利用Session防止表单重复提交(推荐)
实现原理:
服务器返回表单页面时,会先生成一个subToken保存于session,并把该subToenk传给表单页面。当表单提交时会带上subToken,服务器拦截器Interceptor会拦截该请求,拦截器判断session保存的subToken和表单提交subToken是否一致。若不一致或session的subToken为空或表单未携带subToken则不通过。
首次提交表单时session的subToken与表单携带的subToken一致走正常流程,然后拦截器内会删除session保存的subToken。当再次提交表单时由于session的subToken为空则不通过。从而实现了防止表单重复提交。
6.Vue的生命周期?vue的指令?vue的双向绑定如何实现?vue如何实现自定义事件?vue如何实现监听?vue如何实现请求?vue的路由跳转方式?
生命周期:从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
vue的指令:
v-text
v-text主要用来更新textContent,可以等同于JS的text属性。
v-if
v-if可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。
v-for
用v-for指令根据遍历数组来进行渲染
v-bind
v-bind用来动态的绑定一个或者多个特性。
3 vue的双向绑定如何实现?
1 数据双向绑定(v-model)配合vue中的data
vue如何实现自定义事件
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
vue如何实现监听?
$watch
vue如何实现请求
axios
vue的路由跳转方式
router-link标签
ps : 区别
this.$router.push
跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面
this.$router.replace
跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)
this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
7.get和post有什么区别?
1. Get是不安全的,因为在传输过程,数据被放在请求的URL中;Post的所有操作对用户来说都是不可见的。
2. Get传送的数据量较小,这主要是因为受URL长度限制;Post传送的数据量较大,一般被默认为不受限制。
3. Get限制Form表单的数据集的值必须为ASCII字符;而Post支持整个ISO10646字符集。
4. Get执行效率却比Post方法好。Get是form提交的默认方法。
8. jquery如何获取当前日期?
var myDate = new Date();
var year=myDate.getFullYear(); //获取当前年
var month=myDate.getMonth()+1; //获取当前月
var date=myDate.getDate(); //获取当前日
var h=myDate.getHours(); //获取当前小时数(0-23)
var m=myDate.getMinutes(); //获取当前分钟数(0-59)
var s=myDate.getSeconds(); //获取当前秒
var now=year+'-'+getNow(month)+"-"+getNow(date)+" "+getNow(h)+':'+getNow(m)+":"+getNow(s);
9.如何给画面中所有的 checkbox标签添加一个事件?
var x = document.getElementByTagName("checkbox").
var i;
for (i = 0; i < x.length; i++) {
x[i].onclick
}
10. jquery怎么打开一个模态窗口?
SimpleModal是一个轻量级的jQuery插件,它提供了一个强大的界面模态对话框发展。
SimpleModal提供2个简单的方法来调用一个模式对话框。
(1)作为一个串连的jQuery函数,你可以调用一个jQuery元素modal()函数使用该元素的内容将显示一个模式对话框。
$("#element-id").modal();
(2)作为一个独立的功能,可以通过一个jQuery对象,一个DOM元素,或者一个普通的字符串(可以包含HTML)创建一个模态对话框。
$("#element-id").modal({options});
$.modal("<div><h1>SimpleModal</h1></div>", {options});
11.表单验证是如何实现的?
用document获取输入框的value可以判断是否为空或者是否为数字
其他类型的校验 比如手机号 邮箱之类的可以用正则表达式校验
12. readonly和 disable有什么区别?
readonly并没有对input[type="button"]产生作用,按钮效果仍然在,并没有“不可用”;
而disabled直接对input[type="button"]的按钮效果产生作用,导致按钮不可点击。
disabled属性可以作用于所有的表单元素。
readonly只对可以输入的表单元素有效
13.如何画一个表格?如何合并单元格?
在<table></table>的标签内只要有几行就要写几个<tr></tr>,而<tr></tr>内又包含着<td></td>。
在th或者td中设置rowspan属性,用于合并两行的同一列单元格
14.如何获取一个文本框的内容?
var textbox= document.getElementById("textbox");
var text = textbox.value;
15. Jquery如何获取form表单的值?
把form表单的值序列化成一个Json对象,如{username:admin,password:123}
var params = $('#searchForm').serializeObject();
把form表单的值序列化成一个字符串,如username=admin&password=admin
var params = $('#searchForm').serialize();
将字符串转换为Json对象
JSON.parse(str)
16.前端如何延时调用一个函数?
WindowsetTimeout()方法
jQuerydelay()方法
17.如何取出树形结构的数据?前端如何显示树形结构数据?
首先先遍历所有的节点数据,生成id 和parent_id的关系,然后遍历id 和parent_id的关系,因此将子节点数据放入children 这个集合当中。
通过js遍历数据对象,拼接成dom字符串,插入到html中
18.js中的this在各种情况下的指向?
情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window,但是我们这里不探讨严格版的问题,你想了解可以自行上网查找。
情况2:如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
情况3:如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象
19.如何将数据保存到前端?
虽然cookie可以存储一些数据,但是仍然存储下面一些缺点
(1)cookie需要在客户端和服务器端之间来回传送,会浪费不必要的资源
(2)cookie的存储大小有限制,对于每个域,一般只能设置20个cookie,每个cookie大小不能超过4KB
(3)cookie的安全性,cookie因为保存在客户端中,其中包含的任何数据都可以被他人访问,cookie安全性比较低
Web存储机制
接下来,我们要说一下html5中的存储啦,主要是sessionStorage和localStrorage
由于sessionStorage对象是Storage的一个实例,所以存储数据时可以使用setItem()或者直接设置新的属性来存储数据
当我们要获取某个数据的时候,可以使用getItem来获取数据
于localStorage也是Storage的实例,可以像使用sessionStorage一样来使用它
20.如何实时刷新页面?
页面自动刷新:把如下代码加入<head>区域中
<meta http-equiv="refresh" content="5">
21.什么是http协议无状态协议?怎么解决http协议无状态协议?
HTTP无状态协议是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
1、通过Cookies保存状态信息
通过Cookies,服务器就可以清楚的知道请求2和请求1来自同一个客户端。
2、通过Session保存状态信息
Session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当 程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为 session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个 session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
Session的实现方式:
1、使用Cookie来实现
服务器给每个Session分配一个唯一的JSESSIONID,并通过Cookie发送给客户端。
当客户端发起新的请求的时候,将在Cookie头中携带这个JSESSIONID。这样服务器能够找到这个客户端对应的Session。
2、使用URL回写来实现
URL回写是指服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带会服务器。如果直接在浏览器输入服务端资源的url来请求该资源,那么Session是匹配不到的。
Tomcat 对Session的实现,是一开始同时使用Cookie和URL回写机制,如果发现客户端支持Cookie,就继续使用Cookie,停止使用URL回 写。如果发现Cookie被禁用,就一直使用URL回写。jsp开发处理到Session的时候,对页面中的链接记得使用 response.encodeURL() 。
重写和重载的区别
首先是重载,重载就是在同一个类当中有多个名称相同方法,但各个相同方法的参数列表不同(无关返回值类型)。如下,在test3中三个方法名相同的add方法,第一个是两个int类型的书相加,第二个是三个int相加,第三个是两个float相加,他们的参数个数不同或类型不同就构成了重载。
重写则发生在不同的类当中,并且两者要有继承关系,重写是方法名字和参数的列表是要完全一致的,重写的意义在于父类的方法已经不能满足时,子类重写为自己需要的。如下,在父类Test3中num方法是想做两数的加法运算,而在子类Test4中我想做两数的减法运算,则继承的num方法不能满足,则重写为test4中的num方法进行减法运算
值传递和引用传递的区别
1、按值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。简单来说就是直接复制了一份数据过去,因为是直接复制,所以这种方式在传递时如果数据量非常大的话,运行效率自然就变低了
2、按引用传递:引用传递其实就弥补了上面说的不足,如果每次传参数的时候都复制一份的话,如果这个参数占用的内存空间太大的话,运行效率会很底下,所以引用传递就是直接把内存地址传过去,也就是说引用传递时,操作的其实都是源数据