文章目录
疑惑
- springMVC返回给前端的数据到底是什么格式? text\html 与 application\json有什么本质的区别??
杂七杂八
- 版本号规则
REST与RESTful
-
REST是什么
Representational State Transfer(表述性状态转移)
Web服务的一种架构风格
轻量级(耦合性高的是重量级)、跨平台、跨语言 -
RESTful是什么
遵循REST风格的Web服务
REST式的Web服务是一种ROA(面向资源的架构) -
ROA与SOA
ROA:面向资源的架构
SOA:面向服务的架构
区别:[SOA]REST与SOA两种架构的异同比较 -
REST架构的主要原则
网络上的所有事务都可被抽象为资源
每个资源都有一个唯一的资源标志符(Resource Identifier)
同一资源具有多种表现形式(json、xml等,根据请求头返回对应格式)
所有操作都是无状态 -
URI 与URL
1.URI是抽象的定义,不管用什么方法表示,只要能定位一个资源,就叫URI,本来设想的的使用两种方法定位:1,URL,用地址定位;2,URN 用名称定位。
2.举个例子:去村子找个具体的人(URI),如果用地址:某村多少号房子第几间房的主人 就是URL, 如果用身份证号+名字 去找就是URN了。
3.结果就是目前WEB上就URL流行开了,平常见的URI 基本都是URL。=>URL就是URI、URI不一定是URL -
资源的操作
1.GET:获取一个资源
2.POST:创建一个新的资源
3.PUT:修改一个资源的状态(body无法传递参数)
4.DELETE:删除一个资源(body无法传递参数)
(主要是这四种,对应CRUD)
注意:默认情况下PUT、DELETE请求体中无法传递参数,因为tomcat对这两个请求不会解析表单 => 需在web.xml中配置过滤器
RESTful风格的资源操作
-
REST接口设计原则
-
REST响应设计原则
-
http响应状态码
重点关注:200、400、500; 以及201、204、404
SVN
-
原理
SVN是集中式; Git是分布式!!
分布式版本管理仅仅是增加了本地库这个概念,其余的概念与集中管理并无区别。 即SVN只能直接提交到中央仓库;而Git可以提交到本地仓库,本地仓库可以再与其他仓库合并 -
SVN协议
http => 客户端浏览器都可访问
https =>客户端浏览器都可访问,更安全
svn => svn自带协议,仅客户端可访问 -
SVN资源仓库
三个目录:trunk(主干)、branches(分支)、tag(标签)
最佳使用方法=>
-
冲突解决
解决冲突的核心思想:为了避免冲突,要在最新的版本之上修改(也就是说修改之前先更新),再提交。
如果没有更新就已经修改,然后发现冲突 =>应该放弃自己的修改,把本地文件更新到最新版本,在最新版本基础之上修改,并且提交。
开发流程与架构
- 电商行业技术特点
- 电商基础概念
- 架构
分布式架构存在的问题 => 系统间的调用变得复杂 => 服务注册中心解决
Maven
- maven导入依赖的原则
Nginx
- 开发阶段的环境
开发环境 => 开发人员的电脑
测试环境 => 测试人员使用的环境
生产环境 => 发布上线的环境
预发布环境 => (部分企业有)介于测试环境于生产环境之间,数据与生产环境一致 - 两类服务器
web服务器
:Apache、Nginx、IIS
web应用服务器
:tomcat、resin、jetty
普遍采用:Nginx+tomcat
区分:web服务器不能解析jsp等页面,只能处理js、css、html等静态资源。
并发:web服务器的并发能力远高于web应用服务器。 - nginx 特点与作用
高性能的http服务器; 支持反向daili,可实现负载均衡 - daili
正向daili:用户 -> daili-> csdn=> 即为客户端daili(用户知道访问的结果来自哪里,比如这里的csdn)
反向daili:用户 -> nginx ->tomcat => 即为服务端daili(用户不知道访问的结果来自哪里,因为nginx背后有一堆tomcat服务器) - server_name的匹配规则
先遍历所有配置的server_name,如果找到了(与请求中的域名相同),则执行对应的server,如果没有找到,则默认执行第一个server
Redis
- 缓存需求
经常访问的数据缓存到内部才能数据库中,查询时加快速度
缓存添加在哪里,前台系统? 还是 后台系统? — 都加。
每个团队都应该为自己的系统功能负责任,保证其性能。
(redis服务通常位于service层) - 常用缓存技术
redis、memcached
memcached:缓存命中率稍高;功能比较少;多线程实现
redis:缓存命中率稍低(不过差距不大);功能强大;单线程实现 - redis的多数据库
redis默认有16个数据库,对外以从0递增的数字命名;
数据库名不能修改;
默认选择0号数据库;
不支持为每个数据库设置访问密码(官方认为数据安全应由系统环境保证)
多个数据库间不是完全隔离的 => flushall清空所有数据库中数据(flushdb单个) - redis常用命令
keys:获取键名列表
exists:判断一个键是否存在
del:删除一个键值对
type:获得键值的数据类型
help:help+命令 查询该命令使用方法 - redis字符串数据类型
可以存储任何形式的字符串,包括二进制数据 ;
一个字符串类型最多512M(如果需要存储的数据大于512M,说明架构不对)
常用命令
set key value
get key
incr key:自增数据 => decr
incrby key increment:增加指定数据 => decrby
append key value:向末尾追加
strlen key:获取字符串长度
mset key value [key value …]:一次设置多条数据
mget key1 [key2 …]:一个查询多条数据 - redis生存时间
生存时间到期后缓存的数据会被销毁
expire key seconds:设置数据的缓存时间
ttl key:还差多长时间到期(-1:永久有效; -2:已经过期)
persist key :清除生存时间,不会被删除(修改值也会清除过期时间) - redis分片式集群
两种集群方式 => 分片式集群、官方提供的集群方式;
分片式集群示意图如上(Jedis根据key的hash值决定存储到哪个节点),jedis支持分片式集群
- 原则
缓存逻辑不能影响原有业务逻辑的执行
Solr
- 概述
本项目使用solr本质上就是将mysql中经常被查询的数据导入solr,由solr完成查询功能并返回结果数据。solr其实就是一个nosql数据库,以RESTful API的方式提供搜索服务。虽然mysql也能提供搜索与查询,但是全部直接使用mysql会加重数据库负载,而且也不如solr高效,因为选用了solr单独提供搜索服务!! - 更多参考
什么是Solr,它能为我们解决什么问题,怎么用?
消息队列(RabbitMQ)
- MQ
消息队列是应用程序和应用程序之间的通信方法(基于应用层协议AMQP
) - RabbitMQ的队列
hello模式:一个生产者对应一个队列和一个消费者
work模式:一个生产者对应一个队列和多个消费者(一条消息只能发送给一个消费者)
订阅模式:生产者将消息发送到交换机,每个消费者有一个与交换机绑定的队列,从交换机获取数据(一条消息能发送给所有消费者)。消息发送到没有队列绑定的交换机时,消息将丢失
路由模式:在订阅模式的基础上,消息队列绑定到交换机中特定类型的消息(根据key绑定),只获取需要的消息而不是所有消息
通配符模式:在路由模式的基础上,消息队列绑定交换机时key可以使用通配符 - 消息的确认方式
自动确认 => 只要消息从队列中获取,无论消费者获取到消息后是否成功消息,都认为是消息已经成功消费。
手动确认 => 消费者从队列中获取消息后,服务器会将该消息标记为不可用状态,等待消费者的反馈,如果消费者一直没有反馈,那么该消息将一直处于不可用状态。 - 持久化交换机和队列
持久化:将交换机或队列的数据保存到磁盘,服务器宕机或重启之后依然存在。
非持久化:将交换机或队列的数据保存到内存,服务器宕机或重启之后将不存在。
非持久化的性能高于持久化。
如何选择持久化?非持久化? – 看需求。 - 队列和交换机的绑定
1.在配置文件中将队列和交换机完成绑定
=> 绑定关系如果发生变化,需要修改配置文件,并且服务需要重启
2.可以在管理界面中完成绑定
=>管理更灵活,更容易对绑定关系的权限管理,流程管理
Dubbo
- 系统间服务调用的方式
1.浏览器直接访问:浏览器发起请求,通过ajax或者jsonp方式访问
缺点:只能访问对外网公开的服务
2.httpclient:系统与系统之间通过Httpclient发起http请求来请求数据
优点:浏览器可通过中间业务系统间接访问内网中的服务
缺点:http是短连接
3.RPC
优点:长连接!!
- 背景(后端架构的演进)
- 服务治理
- dubbo的系统架构
调用关系:
1.服务容器负责启动,加载,运行服务提供者。
2.服务提供者在启动时,向注册中心注册自己提供的服务。
3.服务消费者在启动时,向注册中心订阅自己所需的服务。
4.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
5.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
6.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
MySQL相关
- 商品数据库表
a.价格要以最小单位分存储 => 为了避免小数计算带来的问题
b.将商品描述和商品的基本数据分离?
1商品描述的数据量大,会导致数据文件变大,影响查询速度。
2后期会对商品描述数据的存储做改造,所以需要将描述数据分离
3.其实,经常修改和经常不修改的数据需要做分离,不应该存储在同一个表 - 富文本编辑器中的内容如何保存
富文本编辑器中的内容其实是html,数据库中保存这个html即可 - 设置主键id为null
数据存入数据库时,为了防止恶意提交的带有id的数据 =>出于安全考虑,Controller中强制设置id为null,通过数据库自增获得Id - 事务
必须同时保存的数据写在同一个事务中(同一个service或者嵌套的service) - 如何保存图片
通常图片不是保存在数据库中,而是保存在文件中,数据库中只是保存图片的路径!! - 如何保存产品规格参数
使用模板的思路=> 需要有2张表:
1.模板表,需要和商品类目关联
2.规格参数数据表,需要和商品关联
模板结构如下:
最终规格参数数据如下:
将上面所示的json结构以字符串的形式存储在目标表和规格参数表中! - 订单-商品关联表中对商品数据冗余存储的原因(易错)
=> 此处并不是为了减少表间关联,加快查询; 而是为了保存这个交易快照,防止完成交易后商家修改商品信息,用户之后查询已购买商品的时显示的信息与实际交易的信息不符(如购买商品时商家承诺有优惠,购买之后商家删除了优惠信息而不给与优惠,从未顾客无法维权。通过数据冗余即可查询交易时的真实情况) - 多字段的联合索引
注意索引字段的顺序,查询语句中只有使用了联合索引的第一个字段时,索引才会有效,否则查询不会使用索引。 - 读写分离
我们一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较大,有一个思路就是说采用数据库集群的方案:
其中一个是主库,负责写入数据,我们称之为:写库;
其它都是从库,负责读取数据,我们称之为:读库;
那么,对我们的要求是:
读库和写库的数据一致;
写数据必须写到写库;
读数据必须到读库; - mysql主从复制
存在的问题:从库拷贝主库的日志并执行,这个过程会有一定时延 => 如何解决?不能从从根本上解决,只有在架构设计的时候考虑这个问题,只要它不影响业务、数据就可以接受
注:上面图示只有一个主库一个从库,实际上更多的是一主(写)多从(读)
前端相关
- 提交数据的序列化
对提交数据进行序列化 => 防止轻易被看出来提交的数据是什么(经常看见地址栏中的乱码就是序列化的结果) - .html结尾的伪静态页面
服务端做特殊过滤,匹配以*.html结尾的请求 => 伪静态页面,有利于SEO(搜索引擎对静态页面打分较高)
- jsonp解决跨域问题
发生跨域的情况 => 协议、域名、端口只要有一个不匹配就是跨域!
script标签的src可以跨域请求资源,但是ajax请求不可以跨域请求=>能否借助script标签的src进行加载数据? – 可以的。
jsonp解决跨域请求原理
1.jsonp通过script标签的src可以跨域请求的特性,加载资源(会被当做js解析)
2.后端把json资源包裹在一个回调函数的参数中(返回整个字符串)
3.前端定义回调函数,解析返回的数据时会调用这个回调函数获取json数据
优化 => 将回调函数名传递到服务端,根据前端的回调函数构造返回的字符串
jquery的jsonp就是jquery使用上述原理,进行了一层封装 => 请求时juqery自动加上回调函数的名(后台因此需要提取出回调函数名这个参数,并在返回数据时加上回调函数名) - 商品类目侧边栏的实现方法
从后端以json数据格式读取类目树结构(后端构造类目树结构比较麻烦,代码见ItemCatService) - js代码压缩
经常看到整个js文件是一行,这是经过压缩后的代码; 压缩的目的一是减小文件大小,一是防止代码被轻易看懂
后端相关
-
上传文件/图片校验
对上传的文件通常要做校验,主要包括以下方面:
1.类型,通过文件的后缀名
2.大小
3.上传文件的内容做校验 =>通过获取文件的宽和高来判断是否是图片
注1:此项目使用了上传文件的依赖 commons-fileupload;另外使用了文件上传解析器CommonsMultipartResolver,它是spring的类
注2:上传图片使用了flash,部分浏览器可能已经不支持,这部分目前只能使用sougou、360浏览器 -
访问上传后的图片
之前的上传后,通过tomcat访问图片。
没有真实的项目是通过tomcat访问静态资源。 为什么?
Tomcat是应用服务器,作用:处理动态请求。
Nginx、Apache是web服务器,作用:处理静态资源、反向daili功能。
Web服务器的并发能力远高于应用服务器。
=>解决方法:图上上传到服务器的文件后,返回图片对应的静态资源链接,然后在前端根据这个返回的图片链接回显图片 -
spring父子容器
(这部分内容很重要,回看day03视频15-16)
Spring容器 – 父容器
SpringMVC容器 – 子容器
父子容器的关系:
1.子容器能够访问父容器的资源(bean)=> 示例:Controller(springMVC容器中)可以注入Service(spring容器中)
2.父容器不能访问子容器的资源(bean)
@Value注入值:仅在当前的所在容器中获取值,然后注入
如何在子容器中获取父容器中注入的值?=> 见PicUploadController中获取REPOSITORY_PATH的方法! -
日志的书写
1.方法的入参处需要将参数打印出
2.业务执行的状态发生变化时,需要打印(执行成功/失败)
3.异常处需要打印 -
如何获取商品数据
如果不使用Mybatis,商品的数据从何而来? – 来源于Mysql数据库
获取数据的途径:
1.从JDBC获取
a) 优点
i. 直接,获取的途径较短,简单
b) 缺点
i. 对后台系统团队而言,数据不安全(只要开放的账户是只读的账户即可)
ii. 前端系统团队需要有学习的成本,才能使用数据库
iii. 依赖、耦合度太高,后端团队将数据库结构修改,那么其他团队必须跟着修改逻辑,才能使用
iv. 直接走数据库查询,无法添加缓存逻辑
2.通过后台系统接口获取=>面向服务
前台系统不是使用Mybatis或者JDBC直接从数据库查询数据,而是调用后台其他系统的服务提供的数据
a) 优点
i. 耦合度降低,后端团队只要保证接口的返回数据格式不变化,其他团队就无需升级
ii. 数据安全
iii. 前端团队无需了解学习后端团队的底层数据库结构
iv. 后端团队可以在接口处添加缓存逻辑
b) 缺点
i. 获取的路径较长(不是真正的缺点) -
中文乱码问题
在SpringMVC中产生的响应有2类
:ModelAndView 和 返回数据响应
返回的数据响应本来是一个对象,但是经过springMVC处理后变成了字符串 => 这一任务由springMVC的消息转化器完成
乱码的原因:默认的消息转换器使用的编码不支持中文 => springMVC配置文件中解决!! (其实也可以在@RequestMapping中通过produces设置!)
-
首页广告的实现 => 内容管理
方案一
1、 在后台系统中创建一张表,存储大广告位的广告数据
2、 在后台系统中对该表进行CRUD
3、 后台系统对外提供接口服务
4、 前台系统调用后台系统的提供的接口服务,即可获取到数据
5、 前台系统获取到数据后,封装成前端所需要的数据结构,功能即可实现
方案二
1、 将首页显示的广告都抽象的看作是内容
2、 在后台系统中创建一张内容表(描述每一条广告的具体信息)
3、 创建一个内容分类表用于区分内容的分类
4、 后台系统对内容表以及分类表进行CRUD
5、 对外提供接口服务
6、 前端系统通过接口获取数据,进行封装,即可实现
对于方案一,如果广告非常多,只能每类广告分别创建一张表,非常麻烦,应该对首页的所有广告统一管理 => 采用方案二,即内容管理系统! -
创建索引的常用规则
1.经常在查询的where字句中出现的字段
2.需要排序的字段 -
前端传递json对象如何接收
方法1.后端使用一个pojo对象接收所有数据
方法2.后端将json对象中的各字段分开接收 => 更安全,防止json对象被修改,导致后端修改了本来不应该修改的字段 -
访问后端提供的接口服务的方式
方式1.js访问
a) 有跨域 – jsonp解决
b) 无跨域 – ajax解决
方式2.Java代码访问
a) Httpclient -
单例对象中如何使用多例对象
不能通过注入获取(这样只能是单例) => 单例类应该实现BeanFactoryAware接口,需要使用多例对象时通过beanFactory从spring容器中获取新创建的对象 -
jsp文件中java代码、jsp代码、js代码的执行顺序
java —> jsp —>js 前两个在后端执行,渲染出html页面然后返回给前端,之后才是js在浏览器端解析 -
关于字符串拼接的效率
A.“abc”+“cba”
B.StringBuffer
C.StringBuilder
jdk1.5以下 => C>B>A
jdk1.5以上 => C=A>B(A在低层也是按照C处理)
StringBuffer只在有线程安全问题的前提下才会使用 -
前后台系统数据同步
问题:后台系统中将商品修改,前台系统没有进行数据的同步,导致前端系统不能够实时显示最新的数据。
解决:在前台系统中开发一个接口 => 后台系统更新数据时调用前台系统的接口,删除前台系统的缓存
上述方法存在的问题 => 要更新前台系统缓存必须修改后台代码,系统间耦合严重 => 应该使用消息队列(MQ) -
sevice中的异常应该捕获还是抛出?
事务的回滚是根据是否抛出异常来进行的,如果捕获了异常(则无法检测抛出的异常),那么出现异常时将不能对事务进行回滚 => 通常有事务的service中都是抛出异常而非捕获异常 -
单点登录系统
什么是单点登录(sso)?
在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统(一个网站可能包含多个子系统,这些子系统部署在不同的tomcat中,但是只需登录一次即可访问所有子系统,无需访问每个子系统时分别进行登录)
为什么需要单点登录系统
之前实现的登录和注册是在同一个tomcat内部完成,我们现在的系统架构是每一个系统都是由一个团队进行维护,每个系统都是单独部署运行一个单独的tomcat,所以,不能将用户的登录信息保存到session中(多个tomcat的session是不能共享的=> 其实可以共享,不过是通过session复制到所有tomcat中,效率很低),所以我们需要一个单独的系统来维护用户的登录信息。
补充:sssion是由tomcat创建并保存的,无法禁用;对于分布式部署的多个子系统,通常不再使用session
传统登录流程
-
单点登录流程
与传统的登陆方式相比本质上没有变化,标志信息都需要保存到cookie中,只是前者在浏览器端保存sessionId后者保存token;单点登录使用redis代替了tomcat保存用户信息 -
静态资源的处理方式
方案1:每个子系统的webapp下分别存放该系统需要使用的静态资源(js、css、iamage等) => 简单,但是对于多个系统共享的静态资源会重复加载;而且这样是通过tomcat访问的静态资源,而tomcat不善于处理静态资源
方案2:将共享的静态资源统一放到一个专门的域名指向的地方,由nginx处理静态资源,所以子系统访问同一个地方的共静态资源 => 避免重复加载;避免携带一些无用的cookie;提高静态资源处理能力 -
SpringMVC的规定:在SpringMVC中如果请求以html结尾,那么就不会返回JSON数据,而是直接返回406状态(springMVC默认的是text格式)
=> 解决办法:多条路进入SpringMVC(比如url-pattern同时匹配:*.html和/service/* ) -
表单数据的校验
前端js代码对表单数据进行的校验比较初级,如果用户直接修改提交的请求,则前端校验规则完成没有用上 => 应该在服务端再次进行数据校验(在springMVC中校验数据,校验通过才进行数据库操作) -
私密字段的处理
返回浏览器端用户信息的时候,password等私密字段最好不要返回,可以在pojo中给相应字段加上@JsonIgnore注解,对象序列化成json字符串时便会忽略该字段 -
cookie、session、token
cookie:cookie是浏览器端存储的一组数据,不同的网站对应的cookie分开存放(因而cookie不能跨域),访问某个网站时,浏览器会将该网站对应的cookie写入请求头的cookie字段(包括sessionID以及cookie中的其他k-v信息)
session:session是服务器端存储的数据,常用于存储用户信息(不管用户是否登录),一个session由一个sessionID标志它。用户首次访问网站(尚未登录)时,tomcat会生成一个session并将sessionID写入浏览器的cookie中,用户后续登录时可以将登录用户的信息写入session方便后续使用。
cookie+session:由上可知,cookie+session可用于跟踪会话,关键点就是sessionID。tomcat将sessionID写入浏览器端cookie中,服务端根据请求中的sessionID识别用户。由于tomcat中的session不能多个服务端共享,给单点登录造成麻烦 => 改用token
token:为了方便多个服务端共享用户信息,通常使用redis缓存登录用户的信息(而不再是tomcat生成session并存储在单个服务端),redis中一个用户的信息由一个token标志。由此可见token类似于sessionID,都是用于识别用户
token与sessionID的区别个人见解
1.sessionID由tomcat生成;token由后端程序员生成
2.sessionID由tomcat写入浏览器的cookie中;token可以由后端程序员写入浏览器cookie中,也可以直接返回给前端,由前端程序员选择保存策略(如存在localStorage中等)
3.即使没有登录的客户端也会生成并写入sessionID;token只针对登录用户
4.只要没有禁用cookie,每次请求都会通过cookie字段携带sessionID;如果token保存在cookie中,自然会出现在请求头的cookie字段。如果token不是保存在cookie中,用户的身份验证则需要通过将token写入请求url或者参数中 -
如何生成订单编号
时间戳+自增id(用redis维护)
用户id+时间戳
用户id+店铺id+时间戳 -
登录拦截器
-
区分响应状态码与业务状态码
响应状态码是在报文头中,后端程序员不手动设置也会有默认的响应状态码
业务状态码是在报文体中,由前后端程序员约定,后端程序员手动设置在返回的信息中 -
ThreadLocal
可通过ThreadLocal将对象存储在当前线程,需要的时候再取出 -
购物车的业务流程
-
如何实现读写分离
应用层解决
中间件解决
目前基本都是采用应用层解决方案
项目发布
- 流程
SVN打tag => 各项目打包(只需打包war项目,jar会自动包含在其中) => 数据库脚本及初始数据 =>编写发布文档 => 实施发布 - 部署架构
- 配置tomcat集群
上图中前台系统共三个tomcat,需要使用nginx进行负载均衡,由nginx决定访问交给哪个tomcat处理(tomcat负载均衡使用轮询算法) - 一台机器上运行多个tomcat
需要修改tomcat的配置文件中的部分端口,避免冲突 =>具体百度 - 双机主备
keepalived+nginx实现双机主备
1.客户端通过虚拟IP访问(与域名绑定),主nginx机器正常时,虚拟IP绑定在主nginx对应的机器上;
2.主nginx异常时,虚拟IP绑定到nginx备份机器上;
3.nginx备份机器通过keepalived的心跳检测感知主nginx机器是否异常 - 双主热备
keepalived+nginx实现
1.图示中两个nginx同时使用,不区分主机和备份机;
2.每台机器各一个虚拟IP(即一台机器两个IP)
3.将一个域名同时绑定到两个虚拟IP
4.客户端通过域名访问时,由DNS系统通过轮询决定走哪个虚拟IP,从而决定了使用哪个nginx
5.如果一个nginx宕机,它的虚拟IP绑定到另一个nignx即可 - 负载均衡
使用lvs代替nginx的负载均衡功能(性能更好)
- 压力测试
原理 => 多线程模拟并发
工具:Jmeter
实战笔记—功能完善
- 如何处理高并发问题
如何解决高并发问题
1、HTML静态化
2、图片服务器分离
3、数据库集群和库表散列
4、缓存
5、镜像
6、负载均衡(终极方法) - GET请求的URL中有时候加上随机数的作用
中url后面接了个随机数,是为了欺骗浏览器或daili服务器用的;某些daili服务器会无视 no-cache 之类的标识,对响应结果进行强行缓存;而当url请求不改变的时候,有时候会导致浏览器不向服务器发送请求,而直接取调用缓存中的数据。加上随机数就是欺骗浏览器url改变了,要每次向服务器发送请求而不去调用缓存中的数据; - 热加载与热部署(注意二者区别)
参考:Eclipse实现热部署和热启动 - ajax,前端收到的json是对象还是字符串
1.前后端数据使用http协议,传递的报文都是字符串,因此本质上说是字符串
2.对于解决跨域的jsonp,由于收到字符串数据后底层会直接使用回调函数进行解析,因此返回给程序员的数据是json对象而不是字符串
3.前端收到json字符串通常需要JSON.parse(data)解析成json对象; 如果不想手动解析,指定dataType字段为json即可自动解析为json对象 - 什么时候才有响应状态码
实际开发中的一些tip
- 商品价格在数据库中最好使用分为单位
- 对于图片,不是直接将图片存储在数据库,而是仅仅将图片的路径存储在数据库
- 为什么要将商品描述和商品的基本数据分离?
1.商品描述的数据量大,会导致数据文件变大,影响查询速度。
2.后期会对商品描述数据的存储做改造,所以需要将描述数据分离
3.注:对表进行优化时,可以将经常修改的数据和不修改的数据分离(拆为不同的表) - 插入数据时,后端代码将自增的字段设置为null
强制设置id为null,通过数据库自增获得 => 从而避免前端提交的请求中包含自增字段值时导致错误(此时插入的是提交的值而不是自增后的值) - 使用.html结尾的伪静态页面
服务端做特殊过滤,匹配以*.html结尾的请求 => 伪静态页面,有利于SEO(搜索引擎对静态页面打分比较高)
参考:伪静态
项目中较难的点
面试时可以从中挑选作答
- 跨域
- 内容管理
将整个界面看到的所有信息抽象成内容,统一放到一张表中(不易想到) <=> 而不是界面中不同板块的东西分别建立其特定的表格
具体如下:
1.将首页显示的广告(应该是所有东西,不仅是大广告)都抽象的看作是内容
2.在后台系统中创建一张内容表
3.创建一个内容分类表用于区分内容的分类
4.后台系统对内容表以及分类表进行CRUD
5.对外提供接口服务
6.前端系统通过接口获取数据,进行封装,即可实现 - PUT、DELETE无法在请求体中传递参数
解决方案:在web.xml中配置过滤器
详见:解决Ajax中Restful风格PUT和DELETE请求传递参数无效