@MRsunhuimin
2019-11-14T15:11:10.000000Z
字数 8611
阅读 176
面试问题总结
左连接是以左表为基准,显示所有数据;内连接,只显示两个表中有联系(都存在)的所有数据,
函数名 | 描述 |
---|---|
count(expr) | 返回满足SELECT条件的记录总和数,如 SELECT COUNT(*)… |
sum(expr) | 返回数字字段或表达式列作统计,返回一列的总和 |
avg(expr) | 通常为数值字段或表达列作统计,返回一列的平均值 |
max(expr) | 可以为数值字段、字符字段或表达式列作统计,返回最大的值 |
min(expr) | 可以为数值字段、字符字段或表达式列作统计,返回最小的值 |
1. 数据类型是有规定的,必须是字符型或数字
2. expr的类型不能是空,如果是空,则不计入其中
spring boot只是一个配置工具,整合工具,辅助工具.
springmvc是框架,项目中实际运行的代码
Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都是Spring 的ioc和 aop. ioc 提供了依赖注入的容器, aop解决了面向横切面的编程,然后在此两者的基础上实现了其他延伸产品的高级功能。
Spring MVC是基于Servlet 的一个 MVC 框架主要解决 WEB 开发的问题,因为 Spring 的配置非常复杂,各种XML、 JavaConfig、hin处理起来比较繁琐。于是为了简化开发者的使用,从而创造性地推出了Spring boot,约定优于配置,简化了spring的配置流程。
说得更简便一些:Spring最初利用“工厂模式”(DI)和“代理模式”(AOP)解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个 MVC框架(一些用Spring 解耦的组件),用开发 web 应用( SpringMVC )。然后发现每次开发都写很多样板代码,为了简化工作流程,于是开发出了一些“懒人整合包”(starter),这套就是 Spring Boot。
Spring MVC提供了一种轻度耦合的方式来开发web应用。
Spring MVC是Spring的一个模块,式一个web框架。通过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易。解决的问题领域是网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。
Spring Boot实现了自动配置,降低了项目搭建的复杂度。
众所周知Spring框架需要进行大量的配置,Spring Boot引入自动配置的概念,让项目设置变得很容易。Spring Boot本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序。也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。同时它集成了大量常用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box),大部分的Spring Boot应用都只需要非常少量的配置代码,开发者能够更加专注于业务逻辑。
Spring Boot只是承载者,辅助你简化项目搭建过程的。如果承载的是WEB项目,使用Spring MVC作为MVC框架,那么工作流程和你上面描述的是完全一样的,因为这部分工作是Spring MVC做的而不是Spring Boot。
对使用者来说,换用Spring Boot以后,项目初始化方法变了,配置文件变了,另外就是不需要单独安装Tomcat这类容器服务器了,maven打出jar包直接跑起来就是个网站,但你最核心的业务逻辑实现与业务流程实现没有任何变化。
- 所以,用最简练的语言概括就是:
- Spring 是一个“引擎”;
- Spring MVC 是基于Spring的一个 MVC 框架;
- Spring Boot 是基于Spring4的条件注册的一套快速开发整合包。
Application属性文件,按优先级排序,位置高的将覆盖位置
当前项目目录下的一个/config子目录
当前项目目录
项目的resources即一个classpath下的/config包
项目的resources即classpath根路径(root)
如果在不同的目录中存在多个配置文件,它的读取顺序是:
1、config/application.properties(项目根目录中config目录下)
2、config/application.yml
3、application.properties(项目根目录下)
4、application.yml
5、resources/config/application.properties(项目resources目录中config目录下)
6、resources/config/application.yml
7、resources/application.properties(项目的resources目录下)
8、resources/application.yml
顺序可以通过实验验证:
1~8 个位置 分别定义不同的 server 端口号 9001~9008
即可验证结果顺序
注:
1、如果同一个目录下,有application.yml也有application.properties,默认先读取application.properties。
2、如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取到的。
3、创建SpringBoot项目时,一般的配置文件放置在项目的resources目录下,因为配置文件的修改,通过热部署不用重新启动项目,而热部署的作用范围是classpath下
@TestPropertySource 注解
命令行参数
Java系统属性(System.getProperties())
操作系统环境变量
只有在random.*里包含的属性会产生一个RandomValuePropertySource
在打包的jar外的应用程序配置文件(application.properties,包含YAML和profile变量)
在打包的jar内的应用程序配置文件(application.properties,包含YAML和profile变量)
在@Configuration类上的@PropertySource注解
默认属性(使用SpringApplication.setDefaultProperties指定)
roncoo.secret={random.value} roncoo.number={random.int}
roncoo.bignumber={random.long} roncoo.number.less.than.ten={random.int(10)}
roncoo.number.in.range=${random.int[1024,65536]}
读取使用注解:@Value(value = "${roncoo.secret}")
注:出现黄点提示,是要提示配置元数据,可以不配置
当application.properties里的值被使用时,它们会被存在的Environment过滤,所以你能够引用先前定义的值(比如,系统属性)
roncoo.name = www.roncoo.com
roncoo.desc = ${roncoo.name} is a domain name
端口配置
server.port=8090
时间格式化
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
时区设置
spring.jackson.time-zone=Asia/Chongqing
备注
手动加载配置文件优先级大于自动加载优先级
高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
项目打包时,只打包根目录下的src文件夹,所以根目录文件夹中的配置全部失效
两种格式。
1. 在properties文件中是以”.”进行分割的, 在yml中是用”:”进行分割;
2. yml的数据格式和json的格式很像,都是K-V格式,并且通过”:”进行赋值;
3. 在yml中缩进一定不能使用TAB,否则会报很奇怪的错误;(缩进只能用空格!!!!)
4. 每个k的冒号后面一定都要加一个空格;
5. yml中的数据是有序的,properties中的数据是无序的。在一些需要路径匹配的的配置中,顺序就显得尤为重要,此时我们一般采用yml
@SpringBootApplication 被 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解所修饰,换言之 Springboot 提供了统一的注解来替代以上三个注解,简化程序的配置。
@Configuration 是一个类级注释,指示对象是一个bean定义的源。@Configuration 类通过 @bean 注解的公共方法声明bean。
- @Bean 注释是用来表示一个方法实例化,配置和初始化是由 Spring IoC 容器管理的一个新的对象。
通俗的讲 @Configuration 一般与 @Bean 注解配合使用,用 @Configuration 注解类等价与 XML 中配置 beans,用 @Bean 注解方法等价于 XML 中配置 bean。
@EnableAutoConfiguration 注解的类所在的包有特定的意义,并且作为默认配置使用。例如,当扫描 @Entity类的时候它将本使用。通常推荐将 @EnableAutoConfiguration 配置在 root 包下,这样所有的子包、类都可以被查找到。
@ComponentScan为 @Configuration注解的类配置组件扫描指令。同时提供与 Spring XML’s context:component-scan 元素并行的支持。
- @ComponentScan 注解会自动扫描指定包下的全部标有 @Component注解 的类,并注册成bean,当然包括 @Component 下的子注解@Service、@Repository、@Controller。@ComponentScan 注解没有类似 context:exclude-filter、context:include-filte的属性。
@ComponentScan(value = {"com.hesp.controller", "com.hesp.service", "com.hesp.config","com.hesp.pojo","com.hesp.utils"})
@MapperScan("com.hesp.dao")
扫的是Dao包(com.hz.dao)
第一期
但是有二期的开发计划,因为现在平台主要面对的是个体服务人员,后期准备引进家政公司进行合作。
项目是给别的公司做的;项目大概20多万;项目从立项到结束(项目周期)大概7个月左右,开发周期(敲代码)三个月左右,
错误回答:参与了;至少200+张表
正确回答:数据库我并没有参与设计,但是参与讨论了数据库。数据库具体有多少张表我还不太清楚,因为这方面是由我们的项目经理负责的
在项目中我们有做了一个抢购优惠券的秒杀模块,技术难点是解决高并发。在那个模块里面我们用到了Redis缓存数据库。
在具体实现中,我们将准备秒杀的优惠券存放到Redis数据库里,然后当用户在适当时间点击秒杀按钮后,如果该用户抢到了优惠券,那么Redis数据库里存储的优惠券数量减一,提示给用户已抢到;当Redis数据库里的优惠券数量为0时,提示用户已告罄。
在第一次做的时候我们使用的是对Redis方法加锁和解锁,后来发现使用ActiveMQ消息队列方法更合理,能够用更少的代码去实现。同时我们使用JmsListener监听消息队列,确保一次只有一个用户能够抢到优惠券。
package com.hz.controller;
import com.hz.utils.ActiveMQUtils;
import com.hz.utils.RedisUtil;
import com.hz.vo.Message;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class QgController {
// 加锁的方法
// @Resource
// private RedisUtil redisUtil;
//
// @RequestMapping("/qg")
// public String qg(String userId,String goodsId){
//
// String lockkey = "lock_goods_"+goodsId;
// while (!redisUtil.lock(lockkey,60L)){
// try {
// Thread.sleep(2000);
// }catch (InterruptedException e){
// e.printStackTrace();
// }
// }
//
// String res = "";
// String flag = redisUtil.getStr(userId+":"+goodsId);
// if(flag!=null&&"1".equals(flag)){
//
// redisUtil.unLock(lockkey);//解锁
// return "用户"+userId+"已经抢购过此商品!";
// }
//
// String stock = redisUtil.getStr("goods_"+goodsId);
// int stockgoods = Integer.parseInt(stock);
// if(stockgoods>=1){
// stockgoods--;
// redisUtil.setStr("goods_"+goodsId,stockgoods+"");
// //添加用户购买记录
// redisUtil.setStr("qg:"+userId+":"+goodsId,"1");
// res = "用户"+userId+"抢到一个商品!";
// }else{
//
// res = "库存不足!用户"+userId+"没有抢到";
// }
// redisUtil.unLock(lockkey);//解锁
// return res;
// }
// ActiveMQ消息队列方法
@Resource
private ActiveMQUtils activeMQUtils;
@Resource
private RedisUtil redisUtil;
final String MQ_KEY = "QG_MQ_MESSAGE";
//发送
@RequestMapping("/qg")
public String qgActiveMQ(String userId,String goodsId){
Message message = new Message();
message.setUserId(userId);
message.setGoodsId(goodsId);
activeMQUtils.sendQueueMessage(MQ_KEY,message);
return "用户"+userId+",排队中........";
}
//接收,60秒失效,JmsListener监听
@JmsListener(destination =MQ_KEY)
public void qg( Message message){
String userId = message.getUserId();
String goodsId = message.getGoodsId();
String lockkey = "lock_goods_"+goodsId;
while(!redisUtil.lock(lockkey,60L)){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String res = "";
String flag = redisUtil.getStr(userId+":"+goodsId);
if(flag!=null&&"1".equals(flag))
{
System.out.println("用户"+userId+"已经抢购过此商品!!!!");
}else{
String stock = redisUtil.getStr("goods_"+goodsId);
int stockgoods = Integer.parseInt(stock);
if(stockgoods>=1)
{
stockgoods = stockgoods - 1;
redisUtil.setStr( "goods_"+goodsId,stockgoods+"");
//添加用户购买记录
redisUtil.setStr("qg:"+userId+":"+goodsId,"1");
res = "用户"+userId+"抢到一个商品!!!";
}else{
res = "库存不足!用户"+userId+"没有抢到";
}
System.out.println(res);
}
redisUtil.unLock(lockkey);//解锁
}
}
https://blog.csdn.net/qq_34237136/article/details/84560692
不能。我们给每个用户设置了权限。用户只能访问有对应权限的方法。
用户在登陆成功之后,才可以去访问一些接口,否则其他的接口都是不可以访问状态,或者校验这个用户在发起请求的时候,是否是登陆状态,同时有些接口不需要登陆也可以访问。
首先,在看到这些需求的时候,要在配置文件里面进行配置白名单,之后读取白名单的配置文件获取到白名单的列表,这样就可以拿到了哪些接口不需要判断。
其次,要做一个拦截器,在每一次前台发起请求的时候,用来拦截,之后进行比较,如果是白名单接口,则不需要进行拦截,直接放掉,如果需要拦截,则进行拦截,进行业务判断。
在之后,根据业务逻辑,判断白名单,之后,判断登陆权限,在判断角色权限,最后抛出异常,返给前台,告知前台信息。
1、读取白名单,以及设置拦截器
2、根据业务进行处理。
这个其实是可以的,但是我们这边也做了相应的对策。我们在用户登录之后会记录他的ip并且保存,当用户访问其它接口时我们会对ip地址进行校验,如果前后两次ip不匹配并且距离跨度较大,我们会像qq一样提示用户登录异常,并且会使用短信验证以确保是用户本人操作。但是这个方法也有缺点,就是ip地址范围是有一定误差的,所以如果截取了token在一定区域内还是可以正常访问的。
有用过。主要是在做登录验证(token),鉴权、缓存数据还有分布式锁。缓存的话主要是一些常用的数据,比如说我们服务类型等,另外可能要进行频繁修改的数据,比如用户发布的订单等,这样可以避免频繁的对MySQL数据库进行操作。
首先我们设置了定时任务,会在每天晚上12点的时候将Redis数据库的内容写入到MySQL数据中,因为在MySQL数据库中每个用户都有唯一的ID,所以向数据库向MySQL数据库存入内容时,只需要判断存入数据是否有ID,有ID的是进行修改,没有ID的进行新增。
阿里巴巴规范上说单表数据大概达到500或单表容量超过2G之后会严重影响性能,推荐进行分库分表。我们的数据量在100万左右。
有做数据库的优化,我们想到了如果数据量到达一个足够高的情况该如何解决?所以我们进行了分库分表策略以保证性能,我们有垂直拆分和水平拆分以及主从同步,还有使用了Mycat中间件进行读写分离,Mycat里面有分片策略,其实就是水平拆分,而垂直拆分可以在Mycat中组成一张逻辑表,配置好后对开发人员来说其实是无感的。