1.数据库表你是怎么设计的?
分为员工表、用户表、分类表、菜品表、套餐表、套餐菜品对应表、口味表、购物车表、订单表、订单详细表、地址表。
为什么用逻辑外键,而不用数据库自带的外键?
数据库通过外键来保证数据的完整性一致性,外键的缺点–对海量数据,性能低,因而使用逻辑外键来保证数据的完整性和一致性,当然,如果是对安全性要求高以及对性能要求不高的场景,可以使用外键 这样更安全。
2.nginx是起到什么作用?
nginx 反向代理,就是将前端发送的动态请求由 nginx 转发到后端服务器,反向代理的好处:
提高访问速度
因为nginx本身可以进行缓存,如果访问的同一接口,并且做了数据缓存,nginx就直接可把数据返回,不需要真正地访问服务端,从而提高访问速度。
进行负载均衡
所谓负载均衡,就是把大量的请求按照我们指定的方式均衡的分配给集群中的每台服务器。
保证后端服务安全
因为一般后台服务地址不会暴露,所以使用浏览器不能直接访问,可以把nginx作为请求访问的入口,请求到达nginx后转发到具体的服务中,从而保证后端服务的安全。
3. 谈谈SpringMvc消息转换器的应用
Spring MVC消息转换器是用于在HTTP请求和响应之间进行Java对象和数据格式(如JSON、XML)之间的转换,解决前后端数据交互的问题。
在一个前后端分离的应用中,前端通过Ajax请求发送JSON数据到后端,Spring MVC消息转换器可以将JSON数据转换成Java对象,同时也能将Java对象转换成JSON数据返回给前端。
Spring MVC消息转换器的默认支持哪些数据格式?
Spring MVC消息转换器默认支持JSON、XML、表单数据等格式。
如何自定义消息转换器?
可以通过继承AbstractHttpMessageConverter
类或实现HttpMessageConverter
接口来自定义消息转换器。然后,在Spring配置中注册这个自定义的消息转换器。
你在项目中的哪些场景使用了消息转换器?
例如,在RESTful API的开发中,使用JSON格式进行前后端数据的传输。通过配置消息转换器,能够自动将Controller的方法返回的Java对象转换成JSON格式响应给客户端。
4. 你是如何利用AOP面向切面编程?
AOP是什么?解决了什么问题?应用场景?
面向切面编程AOP 的目的是将横切关注点(如日志记录、事务管理、权限控制、接口限流、接口幂等等)从核心业务逻辑中分离出来,通过动态代理、字节码操作等技术,实现代码的复用和解耦,提高代码的可维护性和可扩展性。
日志记录:自定义日志记录注解,利用 AOP,一行代码即可实现日志记录。
性能统计:利用 AOP 在目标方法的执行前后统计方法的执行时间,方便优化和分析。
事务管理:@Transactional
注解可以让 Spring 为我们进行事务管理比如回滚异常操作,免去了重复的事务管理逻辑。@Transactional
注解就是基于 AOP 实现的。
权限控制:利用 AOP 在目标方法执行前判断用户是否具备所需要的权限,如果具备,就执行目标方法,否则就不执行。例如,SpringSecurity 利用@PreAuthorize
注解一行代码即可自定义权限校验。
接口限流:利用 AOP 在目标方法执行前通过具体的限流算法和实现对请求进行限流处理。
缓存管理:利用 AOP 在目标方法执行前后进行缓存的读取和更新。
AOP应用各个通知类型以及执行时间?
分别是前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)和环绕通知(Around)。
AOP的各个关键字:
连接点(Jointpoint):表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等等,Spring只支持方法执行连接点,在AOP中表示为在哪里干;
切入点(Pointcut): 选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默认使用AspectJ语法,在AOP中表示为在哪里干的集合;
通知(Advice):在连接点上执行的行为,通知提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置通知(before advice)、后置通知(after advice)、环绕通知(around advice),在Spring中通过代理模式实现AOP,并通过拦截器模式以环绕连接点的拦截器链织入通知;在AOP中表示为干什么;
方面/切面(Aspect):横切关注点的模块化,比如上边提到的日志组件。可以认为是通知、引入和切入点的组合;在Spring中可以使用Schema和@AspectJ方式进行组织实现;在AOP中表示为在哪干和干什么集合;
引入(inter-type declaration):也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象), 在AOP中表示为干什么(引入什么);
目标对象(Target Object):需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为被通知对象;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象,在AOP中表示为对谁干;
织入(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。在AOP中表示为怎么实现的;
AOP代理(AOP Proxy):AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。在AOP中表示为怎么实现的一种典型方式。
Spring AOP和AspectJ是什么关系
AspectJ是一个java实现的AOP框架,它能够对java代码进行AOP编译(一般在编译期进行),让java代码具有AspectJ的AOP功能(当然需要特殊的编译器)
可以这样说AspectJ是目前实现AOP框架中最成熟,功能最丰富的语言,更幸运的是,AspectJ与java程序完全兼容,几乎是无缝关联,因此对于有java编程基础的工程师,上手和使用都非常容易。
动态织入的方式是在运行时动态将要增强的代码织入到目标类中,这样往往是通过动态代理技术完成的,如Java JDK的动态代理(Proxy,底层通过反射实现)或者CGLIB的动态代理(底层通过继承实现),Spring AOP采用的就是基于运行时增强的代理技术
ApectJ采用的就是静态织入的方式。ApectJ主要采用的是编译期织入,在这个期间使用AspectJ的acj编译器(类似javac)把aspect类编译成class字节码后,在java目标类编译时织入,即先编译aspect类再编译目标类。
AOP的配置方法
xml配置:
定义目标类
定义切面类及里面的通知函数
XML配置AOP
注解配置:
类定义(你要增强的类)
定义切面类(用aspect注解修饰),里面的方法有定义切入点(@Pointcut),通知函数(@before等等)
你的项目中是怎么使用的?
我的项目是把一些数据库操作的公共字段给提取出来,比如创建人,创建时间,修改人,修改时间等等。然后通过aop的方式去填入。这其中,还自定义了注解类,标识是插入方法还是更新操作。
这里还可能问你自定义注解应该注意的地方?其实就是由一些元注解组成
@Retention,用于描述一个注解的生命周期,有三个取值。分别为:SOURCE/CLASS/RUNTIME。分别为(1)在源文件中生效,也就是编译器可识别,可用。(2)在编译好的class 文件中生效,即编译器和虚拟机都可以使用。(3)在运行时生效,那么编译器、虚拟机、程序运行时都可以使用。
@Document 这个注解修饰的会被javaDoc 提取出来,形成一个文档。所以如果你想让你的自定义的注解可以被识别,那么就要加这个注解。如果不加这个注解,那么javaDoc 就不会识别。
@Target 这个元注解的意思是定义并且指定被修饰的注解类可以运用在哪些地方。比如说类或者接口、字段属性、方法、参数、构造方法、局部变量等等。
@Inherited注解继承概念跟我们理解的面向对象继承概念不一样,它只作用于子类与父类之间的继承。如果一个父类被@Inherited 注解修饰过,但是如果它的子注解类没有被任何其他注解应用,那么这个子类就可以继承父注解类的注解。所以实现了一个“继承”的关系。
5. redis常用的五种数据类型以及使用场景?
字符串: 适用于缓存、计数器、分布式锁等场景。常常用于存储简单的数据,如用户信息、配置信息、验证码、状态信息等。
哈希:适用于存储对象的属性,特别是对象的字段较多时。例如,存储用户信息、商品信息等。
列表:适用于实现队列、栈,记录操作日志,消息队列等。可以按照插入的顺序存储一系列元素,支持快速的插入和删除操作。
集合: 适用于存储唯一性的元素,例如标签、关注列表等。提供了快速判断某个元素是否存在的能力。
有序集合: 适用于需要根据某个属性排序的情况,例如排行榜、时间线等。可以根据分数范围获取一批元素。
6.微信登录是怎么实现的?
小程序端,调用wx.login()获取code,就是授权码。
小程序端,调用wx.request()发送请求并携带code,请求开发者服务器(自己编写的后端服务)。
开发者服务端,通过HttpClient向微信接口服务发送请求,并携带appId+appsecret+code三个参数。
开发者服务端,接收微信接口服务返回的数据,session_key+opendId等。opendId是微信用户的唯一标识。
开发者服务端,自定义登录态,生成令牌(token)和openid等数据返回给小程序端,方便后绪请求身份校验。
小程序端,收到自定义登录态,存储storage。
小程序端,后绪通过wx.request()发起业务请求时,携带token。
开发者服务端,收到请求后,通过携带的token,解析当前登录用户的id。
开发者服务端,身份校验通过后,继续相关的业务逻辑处理,最终返回业务数据。
7. 如何实现的微信支付功能?
完成微信支付有两个关键的步骤:
1️⃣ 就是需要在商户系统当中调用微信后台的一个下单接口,就是生成预支付交易单。
2️⃣ 就是支付成功之后微信后台会给推送消息。
8.webSocket是什么?有什么应用场景?你的项目中如何应用的?
TCP 协议本身是全双工的,但我们最常用的 HTTP/1.1,虽然是基于 TCP 的协议,但它是半双工的,对于大部分需要服务器主动推送数据到客户端的场景,都不太友好,因此我们需要使用支持全双工的 WebSocket 协议。
在 HTTP/1.1 里,只要客户端不问,服务端就不答。基于这样的特点,对于登录页面这样的简单场景,可以使用定时轮询或者长轮询的方式实现服务器推送(comet)的效果。
对于客户端和服务端之间需要频繁交互的复杂场景,比如网页游戏,都可以考虑使用 WebSocket 协议。
webSocket也有一定的缺点:
服务器长期维护长连接需要一定的成本
各个浏览器支持程度不一
WebSocket 是长连接,受网络限制比较大,需要处理好重连
我的项目在来电提醒和催单提醒中用到了。
通过WebSocket实现管理端页面和服务端保持长连接状态
当客户支付后,调用WebSocket的相关API实现服务端向客户端推送消息
客户端浏览器解析服务端推送的消息,判断是来电提醒还是客户催单,进行相应的消息提醒和语言播报
9. 你的数据统计模块是什么意思?怎么做的?
是一些营业额统计、用户统计、订单统计,销量统计等等。利用apache Echarts做的
10. 大流量下如何设计一个全局唯一的订单号?
在大流量的环境下,我们可以通过 redis 的incr
函数实现序列号自增的特性,同时搭配订单的设计规则,从而保证高并发的环境下,订单唯一性,其中的一个订单规则如下:业务编码+年的后 2 位+月+日+秒+订单数,固定长度为16
,这种订单号规则可以保证 100 年不会重复!
__EOF__
本文作者: flameHknight 本文链接: https://www.cnblogs.com/flameHkngiht/p/18069147 关于博主: 评论和私信会在第一时间回复。或者直接私信我。 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处! 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。