1.SpringBoot整合Redis
- 编辑redis.properties
redis.nodes=192.168.126.129:7000,192.168.126.129:7001,192.168.126.129:7002,192.168.126.129:7003,192.168.126.129:7004,192.168.126.129:7005
- 编辑RedisConfig类
package com.jt.config;
import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
@Configuration //我是一个配置类 一般都会与@Bean联用
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@Value("${redis.nodes}")
private String redisNodes; //node,node,node
/*整合分片实现Redis内存扩容*/
@Bean
public JedisCluster shardedJedis() {
String[] nodes =redisNodes.split(",");//节点数组分隔
Set<HostAndPort> nod = new HashSet<HostAndPort>();
//动态获取Redis节点信息
// List<JedisShardInfo> list=new ArrayList<JedisShardInfo>();
for (String node : nodes) {//node= host:port ---->[host,port]
String host=node.split(":")[0];
int port =Integer.parseInt(node.split(":")[1]);
//list.add(new JedisShardInfo(host,port));
nod.add(new HostAndPort(host,port));
}
return new JedisCluster(nod);
}
}
- 编辑CacheAOP
//1.将对象交给容器管理
@Component
//2.定义AOP切面
@Aspect
public class CacheAOP {
@Autowired(required=false)
//private Jedis jedis; //单台注入
//private JedisShardInfo jedis; //多台注入
private JedisCluster jedis; //集群注入,可以实现高可用
2.京淘分布式架构-jt-web服务器
2.1 项目架构图设计
2.2 JT-WEB项目构建
2.2.1 新建项目
打war包
2.2.2修改pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jt</groupId>
<artifactId>jt</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>jt-web</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--跳过测试类打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2.3将src导入
/**
* Failed to configure a DataSource: 'url' attribute is not
* specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
* @author pc
* springBoot项目 特点:开箱即用
* 该springBoot启动时,不需要添加数据源
*/
@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)
public class SpringBootRun {
public static void main(String[] args) {
SpringApplication.run(SpringBootRun.class,args);
}
}
2.2.4修改nginx文件
#配置前端服务器 www.jt.com:80 转向到http://localhost:8092服务器中
server {
listen 80;
server_name www.jt.com;
location / {
proxy_pass http://localhost:8092;
}
}
ps:注意HOST文件
# 京淘环境配置
127.0.0.1 image.jt.com
127.0.0.1 manage.jt.com
#测试Linux项目发布
#192.168.126.129 image.jt.com
#192.168.126.129 manage.jt.com
127.0.0.1 www.jt.com
127.0.0.1 sso.jt.com
2.2.5 关于JT-WEB服务器发布问题
问题1: 访问http://www.jt.com时,访问报错
问题2: 访问http://www.jt.com时,跳转的是国外的网站
解决方案1: 让谷歌浏览器禁止将http自动的转化为https
地址栏中输入
chrome://net-internals/#hsts
键入之后,点击delete,之后清楚缓存,重启浏览器即可.
解决方式2: 如果改完hosts/nginx服务器之后依然跳转国外网站,则需要检查谷歌浏览器是否开启了VPN(翻墙工具)
3前端
3.1页面通用跳转
3.1.1添加UserControllor
package com.jt.controllor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/user/")
public class UserControllor {
/**
* 实现用户页面跳转
* http://www.jt.com/user/register.html //register.jps
* http://www.jt.com/user/login.html //login.jps
* 重点为了实现业务功能,拦截.html结尾的请求
*/
@RequestMapping("register.html")
public String register() {
return "register";
}
@RequestMapping("login.html")
public String login() {
return "login";
}
}
3.1.2开启匹配后缀型配置
package com.jt.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfigurer implements WebMvcConfigurer{
//开启匹配后缀型配置
@SuppressWarnings("deprecation")
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(true);
}
}
可以不加.html后缀了
(ps:因为没有设置加什么后缀都可以)
3.1.3为什么用.html为后缀呢?
因为更容易被搜索引擎找到
说明: .html结尾的请求更容易被搜索引擎收录.增强网站的曝光率.
倒排索引: 根据关键字检索文件的位置
搜索引擎工作原理:
3.1.4 伪静态
伪静态是相对真实静态来讲的,通常我们为了增强搜索引擎的友好面,都将文章内容生成静态页面,但是有的朋友为了实时的显示一些信息。或者还想运用动态脚本解决一些问题。不能用静态的方式来展示网站内容。但是这就损失了对搜索引擎的友好面。怎么样在两者之间找个中间方法呢,这就产生了伪静态技术。伪静态技术是指展示出来的是以html一类的静态页面形式,但其实是用ASP一类的动态脚本来处理的。
总结: 以.html为结尾的展现动态页面的技术称之为伪静态.
redis缓存
前提:在高并发的条件下由于引入缓存但是可能会引发如下的问题,导致数据库服务器宕机,影响用户的体验.
缓存-穿透
特点: 用户高并发的环境下,访问一个数据库中不存在的数据就叫缓存穿透!!!
解决方案: 限制用户单位时间内的访问次数 , 封禁IP地址. 网关过滤.
缓存-击穿
特点: 某些高频的访问数据由于操作不当导致缓存失效.从而使得大量的用户直接访问数据库. (一个)
解决方案: 配置多级缓存
缓存-雪崩
特点: 由于redis中的高频key在同一时间内大量的失效.导致用户的请求直接访问数据库,导致宕机的风险. (flushAll)
解决方案: 配置多级缓存
3.2创建jt-sso
选jar包
3.2.1编辑pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.jt</groupId>
<artifactId>jt</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>jt-sso</artifactId>
<dependencies>
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--跳过测试类打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.2.2在jt-common创建User
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
@TableName("tb_user")
@Data
@Accessors(chain = true)
public class User extends BasePojo{
@TableId(type = IdType.AUTO)
private Long id;
private String username; //用户名
private String password; //密码要加密处理
private String phone; //电话
private String email; //邮箱
}
3.2.3在sso中建立好以下文件
package com.jt;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.jt.mapper")
public class SpringBootRun {
public static void main(String[] args) {
SpringApplication.run(SpringBootRun.class, args);
}
}
package com.jt.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jt.service.UserService;
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/getMsg")
public String getMsg() {
return "单点登录";
}
}
package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.User;
public interface UserMapper extends BaseMapper<User>{
}
package com.jt.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jt.mapper.UserMapper;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
}
package com.jt.service;
public interface UserService {
}
还有application.yml
server:
port: 8093
servlet:
context-path: /
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
#driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: 密码
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush配置
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.jt.mapper: debug
3.2.4修改nginx的conf文件
server{
listen 80;
server_name sso.jt.com;
location / {
#代理的是服务器地址
proxy_pass http://localhost:8093;
}
}
3.3 跨域实现
3.3.1 跨域访问测试
案例1:
页面网址:http://manage.jt.com:80/test.html
ajax请求: http://manage.jt.com:80/test.json
结论: 当请求协议://域名:port端口号都相同时 访问正常的.
案例2:
页面网址: http://www.jt.com:80/test.html
ajax请求: http://manage.jt.com:80/test.json
结论: 当浏览器的地址与ajax地址不同时,请求不能正常执行.
3.3.2 同源策略说明
说明:浏览器在发起AJAX请求时,必须遵守同源策略的规定.否则数据无法正常解析.
策略说明: 发起请求时,必须满足 协议://域名:端口都相同(和当前页面对比)时.满足同源策略要求.浏览器可以正确的发起请求,并且解析结果.,
但是如果上述的三项中有一项不同,则表示跨域访问.浏览器不予解析返回值结果.
3.3.3 什么是跨域
定义: 当浏览器解析ajax时,ajax发起请求的地址如果与当前页面所在的地址违反同源策略时,则称之为跨域(请求)
3.4 JSONP(难)
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的
3.4.1 JSONP跨域实现原理
//1.利用javascript中的src属性实现跨域
<script type="text/javascript" src="http://manage.jt.com/test.json"></script>
//2.自定义回调函数 function callback(){}
function hello(data){
alert(data.name);
}
//3.将返回值结果 进行特殊的格式封装 callback(JSON数据)
hello({"id":"1","name":"调用成功"})
在/jt-manage/src/main/webapp/test.json
hello({"id":"1","name":"sky6666"})
在/jt-web/src/main/webapp/testJS.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript">
/*JS是解释执行的语言 */
/*定义回调函数 */
function hello(data){
alert(data.name);
}
</script>
<!--该json一直保存到浏览器中等待调用,但是没有函数名称无法调用 -->
<script type="text/javascript" src="http://manage.jt.com/test.json"></script>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
</head>
<body>
<h1>JS跨域问题</h1>
</script>
</body>
</html>
3.4.2 JSONP测试
/jt-web/src/main/webapp/JSONP.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
alert("测试访问开始!!!!!")
//网址位置 http://www.jt.com/JSONP.html
$.ajax({
url:"http://manage.jt.com/web/testJSONP",
type:"get", //jsonp只能支持get请求,src不支持post提交
dataType:"jsonp", //dataType表示返回值类型
jsonp: "callback", //指定参数名称
jsonpCallback: "hello", //指定回调函数名称
success:function (data){ //data经过jQuery封装返回就是json串
alert(data.id);
alert(data.password);
//转化为字符串使用
//var obj = eval("("+data+")");
//alert(obj.name);
}
});
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
com.jt.web.controller.JSONPcontroller
package com.jt.web.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.User;
@RestController
public class JSONPcontroller {
/**
* http://manage.jt.com/web/testJSONP?callback=jQuery111109358763051531354_1595324608793&_=1595324608794
*
* @return
* 注意事项:返回值结果必须经过特殊的封装 callback(JSON数据)
*/
@RequestMapping("/web/testJSONP")
public JSONPObject jsonp(String callback) {
//准备返回数据
User user =new User();
user.setId(100L).setPassword("我是密码");
return new JSONPObject(callback,user);
}
}