网站后台网站管理员可以看到浏览者的什么见用户是通过哪个域名访问的吗?

注意事项1.关于跨域的说明跨域测试 同源策略 跨域方式:jsonp(get请求) corsjsonp:注意url格式,拼接回调函数名callback 浏览器缓存策略 随机数jsopp优化—通过Ajax封装后发送请求spring提供的针对jsonp返回特定格式的数据需要手动拼接字符串 优化----通过一个Api对象拼接字符串cors本质是Ajax,主流浏览器都支持需要定义配置类。2. 京淘单点登录系统(没有页面,打jar包)登录/注册 通用页面跳转—resful风格在注册页面输入用户名,光标离开会自动效验是否存在数据业务–静态代码块根据url快速定位页面单点登录接口文档-----之检查数据是否可用修改全局异常处理类3 HttpClient概念:可以再java代码内部使用httpClient发起http请求访问服务器获取资源的工具Api案例测试:服务器和服务器之间通讯2种跨域:解决简单地业务,查HttpClient:复杂的业务HttpClient的缺点。1.关于跨域的说明(重要)1.1 跨域访问测试1.1.1 测试1: 同服务器测试(通域)分析:1.浏览器的网址信息: http://manage.jt.com/test.html2. jax请求的地址信息: http://manage.jt.com/test.json结论:当浏览器地址与ajax请求的地址(协议://域名:端口)相同时,可以实现正常的业务调用。问题:网站地址为什么通常是用域名而不是用ip进行访问?在互联网中,每个机器设备都会有唯一的标识符,IP地址。但是记忆IP地址和身份号码类似也是一串长长的数字,十分不方便人们记忆。于是,出现了域名,来代替复杂的IP地址,方便我们快速访问网址。所以,企业网上建站时,最先需要购买域名。而关于域名为什么要付费使用,是因为域名统一由域名管理局管理,管理是需要成本的,如技术成本、人力成本等。测试步骤:1).页面代码分析.<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<!--引入js函数类库-->
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<!--引入类库之后执行的js代码-->
<script type="text/javascript">
/*文档就绪事件函数*/
$(function(){
$.get("http://manage.jt.com/test.json",function(data){
alert(data.name);
})
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
{"id":"1","name":"tom"}
2).访问效果.1.1.2 测试2: 不同的服务器测试(跨域)说明:1.浏览器的网址信息: http://www.jt.com/test.html2.ajax请求的地址信息: http://manage.jt.com/test.json结论:域名地址不相同时请求不能正常获取响应的结果.步骤:把相同的页面(test.html)放到前台系统,启动前台系统再次进行访问测试(前后台都要启动)可以看出不能发送Ajax请求。1.2 浏览器同源策略介绍说明:浏览器在解析ajax时,如果发现请求的协议名称://请求的域名:请求的端口号与网址的地址都相同的时满足同源策略的规定,浏览器可以正确的解析返回值,该访问称之为同域访问,该策略叫做同源策略。但是如果违反了同源策略中的任意一条,则叫做跨域访问,浏览器出于安全性的考虑,不予解析返回值。概括: 浏览器解析ajax时,由于请求违反了同源策略则称之为跨域请求,反之称为同源策略。注意:1).2个关键词 : 浏览器 Ajax2). 重定向是服务器解析所以不是跨域.1.3 常见跨域实现方式1–JSONP1.3.1 JSONP实现跨域的原理(有难度)思路:1.利用javascrpit中的src属性实现跨域请求.2.自定义回调函数 function callback(xxxx);3.将返回值结果进行特殊的格式封装 callback(json);4.由于利用src属性进行调用 所以只能支持get请求类型.测试步骤:1).页面js编辑:<!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>
</body>
</html>
2). json数据hello({"id":"1","name":"tom"})
3). 启动前台 后台再次测试----成功发送ajax请求,跨域成功。步骤说明:1.javaScript中的src属性不受同源策略的约束.可以获取远程服务器数据.<!--该json一直保存到浏览器中等待调用,但是没有函数名称无法调用
即,通过src调用想要别人调的通必需有名字
-->
<script type="text/javascript" src="http://manage.jt.com/test.json"></script>
2.自定义回调函数 名称任意 后期这个函数有人帮你封装好了./*定义回调函数
*/
function hello(data){
alert(data.name);
}
3.将返回值结果进行特殊的格式封装 callback(JSON); callback:回调函数hello({"id":"1","name":"tomcat猫"})
1.3.2 JSONP概念JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的1.3.3 JSONP优化–通过Ajax进行封装说明:利用js的script标签的src属性发起请求不方便,需要自定义回调函数,封装特殊格式的返回值等太过麻烦,如何简化步骤呢?答:可以封装为ajax调用方式(底层原理没有变)。1.3.3.1 编译页面发送ajax请求Ajax调用方式分析:使用和普通的ajax方式相同。1).页面js<!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("测试访问开始!!!!!")
$.ajax({
url:"http://manage.jt.com/web/testJSONP",
type:"get",
//jsonp只能支持get请求
dataType:"jsonp",
//dataType表示返回值类型(必须要指定为jsonp,不然变为普通的Ajax调用)
//jsonp: "callback",
//指定参数名称
//jsonpCallback: "hello",
//指定回调函数名称
success:function (data){
//data经过jQuery封装返回就是json串
console.log(data);
//alert(data.id);
//alert(data.name);
//转化为字符串使用
//var obj = eval("("+data+")");
//alert(obj.name);
}
});
})
</script>
</head>
<body>
<h1>JSON跨域请求测试</h1>
</body>
</html>
2).请求url的2个特殊参数分析。callback:指定回调函数名,需要和封装的特定的返回值的名称保持一致,实现步骤为:在url地址后多拼接一个参数,代表回调函数名,默认名为callback=xxxxxxxxxxxx随机生成。并且把这个动态生成的名字当作参数传到后台服务器,之后在进行数据获取的时候动态解析这个参数名字,最后进行拼接成callback+json的结构。随机数:因为浏览器缓存策略的原因,如果第二次方送相同的请求会走缓存。但是如果第二次业务数据有改动执行的请求还是原来的缓存显然不合适,所以一般会在js中拼接一个不影响业务逻辑的随机数来区分不同的请求。3).callback=xxxxxx参数名和value的值可以自己指定。1.3.3.2 编辑后台Controller返回数据这是web发送过来的请求访问manage服务器package com.jt.web.controller;
import com.jt.pojo.ItemDesc;
import com.jt.util.ObjectMapperUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JSONPController {
/**
* 测试跨域访问是否成功
* url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
* 参数:没有可以不接,因为每次都会自己拼接一个callback,而返回值恰好也需要方法名封装,所以可以当做参数直接传递。
* 返回值的应该是经过特殊格式封装的数据.
callback(JSON)
*/
@RequestMapping("/web/testJSONP")
public String
jsonp(String callback){
ItemDesc itemDesc = new ItemDesc();//编译返回值数据
itemDesc.setItemId(100L).setItemDesc("跨域测试成功!!!!");
String json = ObjectMapperUtil.toJSON(itemDesc);//对象转化为json
return callback+"("+json+")";
}
}
1.3.3.3 优化字符串拼接----重新编辑Controllerpackage com.jt.web.controller;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.ItemDesc;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JSONPController {
/** 优化手动拼接写发:
* 测试跨域访问是否成功
* url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
* 返回值的应该是经过特殊格式封装的数据.
callback(JSON)
* JSONPObject参数说明:
*
1.function 回调函数名称
*
2.返回的对象之后可以被转化为JSON
*/
@RequestMapping("/web/testJSONP")
public JSONPObject jsonp(String callback){ //spring提供的
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("API测试!!!");
return new JSONPObject(callback, itemDesc);
}
}
1.3.3.4 访问测试控制台输出:1.3.4 原理1.4 常见跨域实现方式2–CORS跨域方式1.4.1 CORS跨域说明说明:当下的主流的浏览器默认支持cors跨域的形式,但是需要服务器添加响应的信息,否则浏览器不支持数据的获取。HEAD、GET、POST1.4.2 编辑CORS配置类(common)谁想要跨域就放在那个项目,因为用的比较多所以放在common中。package com.jt.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CORSConfig implements WebMvcConfigurer {
/**
* 在后端 配置cors允许访问的策略
* 方法说明:
*
1.addMapping(/**) 允许什么样的请求可以跨域: /*代表一级目录
/**代表所有请求的所有目录
*
2.allowedMethods("*") 定义允许跨域的请求类型: *代表所有
*
3.allowedOrigins("*")允许那个网址可以访问:*代表可以允许任意的域名,写具体的网址只能代表一个
*
4.allowCredentials(true) 跨域时是否允许携带cookie等参数
*
5.maxAge(1800)设定请求长链接超时时间(跨域之前会先进行询问是否允许跨域)
*/
@Override
public void addCorsMappings(CorsRegistry registry) {//允许策略的标识符
registry.addMapping("/**")
.allowedMethods("GET","POST")
.allowedOrigins("*")
.allowCredentials(true)
.maxAge(1800);//30分钟
}
}
1.4.3 cors跨域测试在web前台发送请求到后台,如果能够访问代表跨域成功。1).页面js2).JSON数据格式3).访问测试1.4.4 关于跨域的总结1).jsonpjsonp本质利用javaScript中的src属性的get请求实现的跨域.返回值必须经过特殊的格式封装.2).corscors本质是Ajax,服务端策略。需要在服务端添加响应头信息,指定哪些服务器允许访问。2. 京淘单点登录系统2.1 通用页面跳转2.1.1 业务分析需求说明:说明:当用户点击登录/注册按钮时 需要跳转到指定的页面中.1.登录的url地址http://www.jt.com/user/login.html
2.注册的url地址http://www.jt.com/user/register.html
2.1.2 编辑UserController(web项目中)package com.jt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller //由于设计到页面跳转功能.
@RequestMapping("/user")
public class UserController {
/**
* 通用页面跳转实现
* 1.http://www.jt.com/user/login.html
login.jsp页面
* 2.http://www.jt.com/user/register.html
register.jsp页面
* restFul方式: 1.动态获取url中的参数,之后实现通用的跳转.
*/
@RequestMapping("/{moduleName}")
//resful风格需要加上这个注解
public String module(@PathVariable String moduleName){
return moduleName;
}
}
2.1.3 页面效果展现再次点击登录 注册2.2 创建JT-SSO项目2.2.1 JT-SSO项目说明作用:主要为jt-web的服务器提供用户的数据的支持,但凡涉及到user的CRUD操作都应该由该系统完成.打包方式: jar包程序,此项目里面没有页面支持。注意事项: 继承jt/ 依赖jt-common 添加插件.端口号: 80932.2.2 创建项目(Maven)2.2.3 编辑pom.xml配置文件<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>jt-sso</artifactId>
<!--默认打包方式就是jar 所以不写也没有关系-->
<!--添加继承-->
<parent>
<artifactId>jt</artifactId>
<groupId>com.jt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<!--添加依赖项-->
<dependencies>
<dependency>
<groupId>com.jt</groupId>
<artifactId>jt-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--添加插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2.4 编辑User的POJO对象(common)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;
//密码 需要md5加密
private String phone;
//电话
private String email;
//邮箱 注册页面没有这个选项 暂时使用电话代替邮箱
}
2.2.5 实现JT-SSO代码结构需求:通过sso.jt.com/findUserAll的请求,获取所有的用户表中的记录json串返回。1).添加主启动类:
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);
}
}
2).配置文件server:
port: 8093
servlet:
context-path: /
spring:
datasource:
#引入druid数据源
#type: com.alibaba.druid.pool.DruidDataSource
#driver-class-name: com.mysql.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: root
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).控制层:package com.jt.controller;
import com.jt.pojo.User;
import com.jt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
/**
* 完成测试
* 1.url地址:findUserAll
* 2.参数:null
* 3.返回值:List<User>
*/
@RequestMapping("/findUserAll")
public List<User> findUserAll(){
return userService.findUserAll();
}
}
4).service接口package com.jt.service;
import com.jt.pojo.User;
import java.util.List;
public interface UserService {
List<User> findUserAll();
}
5).service接口实现类package com.jt.service;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public List<User> findUserAll() {
return userMapper.selectList(null);
}
}
6).mapper接口package com.jt.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.User;
public interface UserMapper extends BaseMapper<User> {
}
2.2.6 通过域名sso.jt.com实现访问1).修改nginx之后重启nginx服务器.#搭建jt-sso服务器
server {
listen 80;
server_name sso.jt.com;
location / {
proxy_pass http://localhost:8093;
}
}
2).编辑hosts文件3).配置主启动类访问测试2.3 用户数据校验的分析2.3.1 业务需求说明:当用户在注册时,如果输入用户名,则应该向jt-sso单点登录系统发起请求,校验用户数据是否存在,如果存在则提示用户。2.3.2 单点登录业务接口文档说明:这是单点登录业务接口文档中的关于检查数据是否可用的业务。2.3.3 页面url分析说明:有接口文档已经可以开发代码了,但是这里作为学习前台也需要了解。1).当输入完用户名后光标离开,会发送请求进行效验。2).URL说明2.3.4 检索页面JS说明:通过url写死的地址定位到具体哪个页面发送的请求步骤:1).复制url中固定不变的地址。2).在idea项目中进行检索:ctrl+h eclipse键位之后在想要跳转的行数+enter键2.3.5 页面JS分析 $.ajax({
url : "http://sso.jt.com/user/check/"+escape(pin)+"/1?r=" + Math.random(),
dataType : "jsonp",
success : function(data) {
//状态信息:200 成功
状态信息:201 失败
checkpin = data.data?"1":"0";
if(data.status == 200){
if (!data.data) {
validateSettings.succeed.run(option);
namestate = true;
}else {
validateSettings.error.run(option, "该用户名已占用!");
namestate = false;
}
}else{
//标识后台服务器运行异常
validateSettings.error.run(option, "服务器正忙,请稍后!!!(我后台报错了我也不知道啥错!!!)");
namestate = false;
}
}
});
2.2.6 编辑jt-sso的UserController说明:1).由web中的页面发送请求到单点登录服务器sso中获取数据。2).SysResult对象已经在common中的vo写过了。package com.jt.controller;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/user")//业务名称最好写类上
public class UserController {
@Autowired
private UserService userService;
/**
* 业务说明: jt-web服务器获取jt-sso数据 JSONP跨域请求
* url地址: http://sso.jt.com/user/check/{param}/{type}
* 参数:
param: 需要校验的数据
type:校验的类型
* 返回值:
SysResult对象
* 真实的返回值: callback(SysResult的JSON)
*/
@RequestMapping("/check/{param}/{type}")//参数写在路径上 resful风格获取
public JSONPObject checkUser(@PathVariable String param,
@PathVariable Integer type,
String callback){
/**
* 接口文档要求返回值为:
* {
*
status: 200
//200 成功,201 没有查到
*
msg: “OK”
//返回信息消息
*
data: false
//返回数据true用户已存在,false用户不存在,可以
* }
* 而系统vo---SysResult原来返回结果格式为:
* {
*
status:
//200成功
201 失败
*
msg:
//服务器提示信息
成功
失败
*
data:
//服务器返回值数据.
* }
*
可以看出这里要求data返回一个boolean类型的值而不是数据。
*/
boolean flag = userService.checkUser(param,type);
SysResult.success(flag);
//因为跨域需要特殊的返回值格式,所以需要进一步的封装
spring的优化字符串拼接写发:直接通过这个对象来接
return new JSONPObject(callback, SysResult.success(flag));
}
/**
* 完成测试
* 1.url地址:findUserAll
* 2.参数:null
* 3.返回值:List<User>
*/
@RequestMapping("/findUserAll")
public List<User> findUserAll(){
return userService.findUserAll();
}
}
2.2.7 编辑jt-sso的UserServicepackage com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
//定义map集合通过静态代码块赋值。
private static Map<Integer,String> columnMap = new HashMap<>();
static {
columnMap.put(1, "username");
columnMap.put(2, "phone");
columnMap.put(3, "email");
}
/**
* 判断依据:
根据用户名查询 如果结果>0 用户已存在.
* 即:如果根据用户名进行查询返回值为查询的记录就代表
* 这个数据存在,而不在乎是谁.
* @param param
需要校验的数据
* @param type
校验的类型 1username 2phone 3 email 6789910
* @return
*/
@Override
public boolean checkUser(String param, Integer type) {
/**
* 1.需要将type类型转化为 具体字段信息
1=username
2=phone
3=email
* 解释:因为用户传递进来的是 1 2 3这样具体的数字,而数据库库存的是这些数字对
* 应的字段,所以需要进行转换查询。
* 2.如何高效率的转化???
* 如果采用普通的if判断 switch判断性能太低----可以用静态代码块,在类加载时就存在了。
*
* */
String column = columnMap.get(type);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(column, param);
Integer count = userMapper.selectCount(queryWrapper);//得到的结果 有值就是1 没值就是0
return
count > 0 ? true :false;// 是1大于0代表有值返回true已存在 是0不大于0代表没有值返回false不存在用户
}
@Override
public List<User> findUserAll() {
return userMapper.selectList(null);
}
}
2.2.8 页面效果测试说明:启动web sso服务器,因为admin123在数据库存在所以只要光标离开就会提示用户已被占用。2.2.9 修改全局异常处理机制问题说明:当后端(不是后台,代表所有的服务器)服务器执行出错时,会执行全局异常的处理.但是JSONP的请求的调用要求 返回值类型 callback(JSON)结构.所以需要重构全局异常处理的返回值结构类型.重构前:重构后:package com.jt.aop;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.vo.SysResult;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
//@ControllerAdvice
//拦截controller层(因为mapper层和service层异常最终抛给controller层,所以拦截控制层最合适。)
//@ResponseBody 与页面交互都是json型的数据
@RestControllerAdvice
//定义全局异常的处理类
AOP=异常通知(底层封装好了)
public class SystemAOP {
/**
*
定义全局异常的方法
当遇到了什么异常时,程序开始执行
参数一般class类型
*
如果一旦发生异常,则应该输出异常的信息,之后返回错误数据即可.
*
*
解决跨域全局异常处理的规则: 京淘项目的跨域都是使用JSONP.
http://xxxx?callback=xxxxx
*
所以如果请求中携带了callback参数 则认为是JSONP跨域请求.
*
难点: 如何获取callback参数呢??
*
一般在控制层可以通过HttpServletRequest(请求头对象)获取url中携带的参数。
*
思路:
*
因为整个项目一旦出现异常就会走这个类,所以可以根据url是否携带callback进行判断,
*
如果有callback应该返回跨域失败的异常处理方法,如果没有callback参数代表返回普通请求异常处理失败的方法。
*/
@ExceptionHandler({RuntimeException.class}) //多个不同类型的异常(如io,sql),写法:{RuntimeException.class,xxx,xxx}
public Object systemAop(Exception e, HttpServletRequest request){
e.printStackTrace();
String callback = request.getParameter("callback");
if (StringUtils.isEmpty(callback)) {
//常规方法调用方式
return SysResult.fail();
} else {
//证明是jsonp跨域请求
return new JSONPObject(callback, SysResult.fail());
}
}
}
访问测试:因为修改的是common所以后端服务器都要重启。3 HttpClient3.1 业务需求业务说明:当做某些操作时可能会对数据进行业务加工,之后由服务器和服务器之间形成通讯。eg:用户在网上买东西需要付款,付款的后台执行流程是,用户通过浏览器访问支付页面的服务器对数据进行加工,再把数据传给银行的服务器,最后由银行服务器返回结果。为什么要对数据进行加工??因为银行服务器再进行一些数据接收时对一些参数的格式有要求。直接通过跨域方式这些数据都写死在js里不方便。解决:用户通过浏览器发送请求交给后台服务器去处理,而后台服务器在内部把数据进行加工,然后在远程传给银行服务器。跨域能解决吗??不能,跨域是通过浏览器解析ajax请求,即通过浏览器直接访问银行服务器,对数据不能加工,银行对这些普通的数据格式没办法接收,所以跨域不能解决问题。跨域因为不能对数据进行加工,账户密码都会在传输过程中暴露,不安全。总结:1).跨域访问只能解决一些简单地问题如:查执行流程:前端服务器发送ajax请求(通过页面js),经过浏览器解析发送给后端服务器进行调用(controller—service----mapper层级调用在返回数据)。2).httpClient远程调用更加安全,可以对数据加工后再发送请求执行流程:前端代码发送的ajax请求先经过本地服务器进行参数加工(controller–service),将加工好的参数在传给后台服务器进行调用(controller–service–mapper)。3.2 HttpClient介绍HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为 HttpClient 4.5 .6(2015-09-11)总结: 在java代理内部可以使用httpClient发起http请求访问服务器获取资源.(工具API)3.3 HttpClient入门案例注意:将来在SpringCloud中会有更高级的Api对HttpClient的Api进行封装,这个更高级的Api底层就是HttpClient的Api.3.3.1 导入jar包<!--添加httpClient jar包 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
3.3.2 入门案例(web里面)package com.jt.test;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
public class TestHttpClient {
/**
* 要求:在java代码内部,获取百度的页面.
* 实现步骤:
*
1.确定目标地址: https://www.baidu.com/
*
2.创建httpClient客户端对象
*
3.创建请求类型
*
4.发起http请求.并且获取响应的结果.之后判断状态码是否为200 如果等于200则请求正确(因为请求不一定成功)
*
5.如果请求正确则动态获取响应值信息.之后进行数据的再次加工....
*
*/
@Test
public void test01(){
//1.确定地址
String url = "https://www.baidu.com/";
//2.创建一个默认的请求对象
注意导包apache
HttpClient httpClient = HttpClients.createDefault();
//3.创建请求类型
发送get请求:HttpGet
post:HttpPost
put:HttpPut
HttpGet get = new HttpGet(url);
try {
//3.1执行请求,因为请求不一定能‘发送’成功,所以需要处理异常 try-catch/throws,返回值为HttpResponse
HttpResponse httpResponse = httpClient.execute(get);
//4.判断状态码是否正确 因为请求不一定能成功
int statusCode = httpResponse.getStatusLine().getStatusCode();//4.1获取状态码
if(statusCode == 200){
//4.2表示请求正确
//4.3获取服务器的全部响应信息(json/html/xml/xxxx)
HttpEntity httpEntity = httpResponse.getEntity();
//4.4 一般会把这个实体对象转化为字符串使用,转换的时候需要指定编码 否则会乱码
String result = EntityUtils.toString(httpEntity,"UTF-8");
//5.获取之后可以执行业务处理......
System.out.println(result); //获取的应该是一个页面,页面的本质是html
}else{
//如果请求不成功打印一下状态码信息。
System.out.println(httpResponse.getStatusLine().getStatusCode());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行的结果:3.4. HttpClient加强案例3.4.1 需求说明:用户通过网址 http://www.jt.com/getItems 要求采用httpClient方式,获取jt-manage中的商品信息,后json串的形式展现.jt-web服务器访问jt-manage时的网址 http://manage.jt.com/getItems.3.4.2 编辑前台 HttpClientController(web)package com.jt.controller;
import com.jt.pojo.Item;
import com.jt.service.HttpClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class HttpClientController {
@Autowired
private HttpClientService httpClientService;
/**
* 获取后端manage中的商品数据信息
*/
@RequestMapping("/getItems")
public List<Item> getItems(){
return httpClientService.getItems();
}
}
3.4.3 编辑前台 HttpClientService(web)package com.jt.service;
import com.jt.pojo.Item;
import com.jt.util.ObjectMapperUtil;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Service
public class HttpClientServiceImpl implements HttpClientService{
@Override
public List<Item> getItems() {
//前端访问后端在java代码内部只能通过httpclient的方式
List<Item> itemList = new ArrayList<>();//准备集合转化为对象
//1.定义远程访问网址
String url = "http://manage.jt.com/getItems";
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
String result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
/**
* result是jt-manage为jt-web返回的List<Item>的JSON串,
* 而现在需要返回的是List<Item>类型的集合所以需要转换
*/
if(!StringUtils.isEmpty(result)){//不为空才进行处理
itemList = ObjectMapperUtil.toObject(result, itemList.getClass());
}
}
} catch (IOException e) {
//把异常信息输出到控制台
e.printStackTrace();
//把检查型异常转化为运行时异常抛出
throw new RuntimeException(e);
}
return itemList;
}
}
3.4.5 编辑后台 HttpClientController(manage)package com.jt.web.controller;
import com.jt.pojo.Item;
import com.jt.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class HttpClientController {
@Autowired
private ItemService itemService;
/**
* url请求地址: http://manage.jt.com/getItems
*/
@RequestMapping("/getItems")
public List<Item> getItems(){
return itemService.getItems();
}
}
3.4.6 编辑后台 HttpClientService(manage) @Override
public List<Item> getItems() {
return itemMapper.selectList(null);
}
3.4.7 页面效果展现3.5 HttpClient调用缺点缺点:代码调用的层级很多,如何简化呢?答: SOA(面向服务的架构)。}
这是一个很经典的面试题,主要是考察程序员是否对网络请求的整个步骤有一个比较详细的了解,整体上来讲是对OSI七层模型理解的考验。这个问题还有一个问法: 你在浏览器中输入百度的域名到你看到了百度的页面,中间经过了哪些步骤。如图,我们到底是怎么能看到这个百度的页面的呢?OSI七层模型
请求的封包是从应用层一直到物理层(从上往下)。其中,应用层、会话层、表示层合并为了应用层,物理层和数据链路层合并为了物理层,所以图上只画了四层结构。相反的,请求的拆包是从物理层一直拆包验证到应用层,每个层都有自己对应的协议,如果请求的内存不符合协议规范,那么服务端会拒绝请求。
应用层我们使用浏览器请求,那么请求使用的是Http协议,从应用层发起}
新版本搭建教程请看这里---> 包月版本,可测试抖音跳转微信/QQ/网页H5源码程序-附搭建教程功能抖音卡片跳转 微信抖音卡片跳转 qq抖音卡片跳转 微信公众号抖音卡片跳转 指定网页链接抖音小风车 跳微信抖音星图小风车跳微信抖音直播小风车跳微信快手跳转 微信快手跳转 qq快手跳转 微信公众号快手跳转 指定网页链接小红书跳转 微信小红书跳转 qq小红书跳转 微信公众号小红书跳转 指定网页链接h5浏览器跳转 微信h5浏览器跳转 qqh5浏览器跳转 微信公众号h5浏览器跳转 指定连接微博跳转 微信微博跳转 qq微博跳转 微信公众号微博跳转 指定连接先上图,看效果(后面有源码和搭建教程)后台管理界面手机上跳转效果抖音跳转微信 源码搭建教程准备工作域名,服务器(如果服务器是中国大陆的,需要备案)程序服务端后台项目代码小程序项目代码如果需要跳转到加微信,需要以下资料企业资质认证的微信小程序域名需要备案,因为微信小程序用的域名必须备案附加:如果你只是想跳转到自己一个人的微信二维码,可以不用企业资质(这个没单独开发,如果有这个需求的个人,可以单独联系我)代码下载服务端后台代码下载地址下载地址 https://gitee.com/dot2-com/douyin-kapian小程序端代码(如果不跳转微信,可以不用安装小程序代码)下载地址 https://gitee.com/dot2-com/qrcode-mini安装步骤如果嫌麻烦不想自己动手安装,可以使用钞能力找我,打骨折价100一次。购买服务器选购阿里云服务器 保姆级图文教程 https://blog.noxue.com/tutorial/d9a11d02e76742baa38796be957bb0f3.html购买域名并备案记得购买域名在阿里云,备案也要在阿里云,因为服务器是阿里云的。如果不想备案,可以联系我们,使用我们的域名。我们免费提供备案的域名。(业务一定要合法)连接服务器后,安装宝塔如果服务器上已经安装宝塔,忽略这一步注册宝塔账号 https://www.bt.cn/?invite_code=MV95a2lvcWk=宝塔安装地址 https://www.bt.cn/new/download.html滚动条下拉,找到这个位置,输入服务器ip,密码,即可自动安装。
服务器ip在阿里云ecs页面可以获取到,密码在购买的时候设置过
点击安装后,一直等到出现这个界面为止 登录宝塔,安装程序根据上方安装之后的登录地址和账号密码登录宝塔如果无法访问,可能是没开8888端口 点击这个教程打开端口 https://blog.noxue.com/tutorial/f5695d53807a4f409707978d7f786590.html登录后输入你前面注册的账号登录宝塔 进入服务器 /root 目录 上传文件到服务器 上传成功后关闭弹出框 登录服务器命令行(第一次登录需要密码) 登录后大概这个效果 解压文件的命令tar zxvf qrcode.tar.gz解压命令执行后的效果 进入到代码所在目录 查看项目代码文件 运行命令 安装项目 到此未知,程序运行起来了,接下来我们创建网站,让用户可以访问到解析域名到服务器,再创建网站,用户可以通过域名访问在阿里云后台找到域名管理面板 找到域名 点击解析 解析域名到ip
填写完毕后点击右下角确认解析之后效果如下 在宝塔后台创建网站,这是最后一步了创建网站 申请 ssl 证书,让网站支持 https 请求 申请中,不用操作 搞定ssl证书 创建反向代理 登录后台,默认密码 dot2.com 修改后台密码 总结准备服务器,域名,程序安装宝塔上传后台程序,运行解析域名到服务器安装ssl创建反向代理,让用户可以访问}

我要回帖

更多关于 网站管理员可以看到浏览者的什么 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信