lcx-框架

1. spring的特性是什么?ioc和aop的原理是什么?aop的注解有哪些?

Spring拥有两大特性:IoC和AOP。IoC,英文全称Inversion of Control,意为控制反转。AOP,英文全称Aspect-Oriented Programming,意为面向切面编程

ioc:控制反转,简单点说,就是创建对象的控制权,被反转到了Spring框架上

aop:面向切面编程 将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面", 简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码, 降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

aop注解:

(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可

(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值

(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名

来访问目标方法中所抛出的异常对象

(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式

(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint

2. springboot自动装配原理是什么? springboot 配置文件中常用配置有哪些

SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration

将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到了容器中

properties文件和yml文件

3. Springboot项目如何打包、部署、运行?

用idea开发工具右侧的maven projects  intall package 然后就会出来我们需要的jar

然后到这个jar的根目录下执行java -jar smallsystem-0.0.1-SNAPSHOT.jar

4. spring是如何控制事务的?

使用注解配置

使用@Transactional注解 需要在配置文件中开启对这个注解的扫描:<tx:annotation-driven transaction-manager=“transactionManager” />,引用了事务管理器

然后就可以使用@Transactional注解,此注解可以使用在类上,也可以使用在方法上,使用在类上即对此类的所有方法都起作用,使用在方法上则表示对单个方法起作用

5. springmvc常用注解及作用?

1、@Controller

在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。

2、@RequestMapping

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

3、@Resource和@Autowired

@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。

4、@PathVariable

用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。如:

7、@ResponseBody

作用:将方法的返回值,以特定的格式写入到response的body区域,进而将数据返回给客户端。

如果返回值是字符串,那么直接将字符串写到客户端;如果是一个对象,会将对象转化为json串,然后写到客户端。

6. springmvc的工作流程是什么?

SpringMVC流程

1、 用户向服务端发送一次请求,这个请求会先到前端控制器DispatcherServlet(也叫中央控制器)。

2、DispatcherServlet接收到请求后会调用HandlerMapping处理器映射器。由此得知,该请求该由哪个Controller来处理(并未调用Controller,只是得知)

3、DispatcherServlet调用HandlerAdapter处理器适配器,告诉处理器适配器应该要去执行哪个Controller

4、HandlerAdapter处理器适配器执行Controller得到ModelAndView(数据和视图),并层层返回给DispatcherServlet

5、DispatcherServletModelAndView交给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>

注意:里面的数字代表你传入参数的顺序,不是特别建议使用这种方法传递参数,特别是参数个数多的时候

方式二、注解@Param传递参数

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注解中声明的参数名称获取参数

方式三、使用Map集合传递参数

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>

方式四、使用JavaBean实体类传递参数

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

例:

@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.加密

客户端和服务器都保存一个秘钥,每次传输都加密,服务端根据秘钥解密。



 

猜你喜欢

转载自blog.csdn.net/abu1216/article/details/112298752