说明:当用户点击登录/注册按钮时 需要跳转到指定的页面中.
url地址1.:http://www.jt.com/user/register.html
url地址2: http://www.jt.com/user/login.html
package com.jt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Controller //需要进行页面跳转
@RequestMapping("/user")
public class UserController {
/**
* 实现用户模块页面跳转
* url1: http://www.jt.com/user/login.html 页面:login.jsp
* url2: http://www.jt.com/user/register.html 页面:register.jsp
* 要求:实现通用页面跳转
* restFul方式: 1.动态获取url中的参数,之后实现通用的跳转.
*/
@RequestMapping("/{moduleName}")
public String module(@PathVariable String moduleName){
return moduleName;
}
}
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@TableName("tb_user")
@Data
@Accessors(chain = true)
public class User extends BasePojo{
@TableId(type = IdType.AUTO)//设定主键自增
private Long id; //用户ID号
private String username; //用户名
private String password; //密码 需要md5加密
private String phone; //电话号码
private String email; //暂时使用电话代替邮箱
}
用户通过sso.jt.com/findUserAll 获取user表中的信息 json返回
代码结构如下:
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
*
*/
@RequestMapping("/findUserAll")
public List
return userService.findUserAll();
}
}
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
return userMapper.selectList(null);
}
}
分析:
1.浏览器地址: http://manage.jt.com/test.html
2.ajax请求地址: http://manage.jt.com/test.json
结论:
当浏览器地址与ajax请求的地址(协议://域名:端口)相同时可以实现正常的业务调用.
分析:
1.浏览器地址: http://www.jt.com/test.html
2.ajax请求地址: http://manage.jt.com/test.json
结论:
如果请求地址(协议://域名:端口)不相同则导致请求调用失败
说明: 浏览器规定 发起ajax时如果请求协议/域名/端口号如果3者有一个与当前的浏览器的地址不相同时,则违反了同源策略的规定.则浏览器不予解析返回值.
跨域问题: 违反同源策略的规定就是跨域请求.
封装返回值:
hello({"id":"1","name":"tom"})
页面js编辑
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的
package com.jt.web.controller;
import com.jt.pojo.ItemDesc;
import com.jt.util.ObjectMapperUtil;
import jdk.nashorn.internal.runtime.regexp.JoniRegExp;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JSONPController {
/**
* 实现JSONP跨域请求
* url地址: http://manage.jt.com/web/testJSONP?callback=xxxxxx
* 参数: 暂时没有可以不接
* 返回值: callback(JSON);
*/
@RequestMapping("/web/testJSONP")
public String testJSONP(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(1000L).setItemDesc("JSONP测试!!!");
String json = ObjectMapperUtil.toJSON(itemDesc);
return callback+"("+json+")";
}
}
@RequestMapping("/web/testJSONP")
public JSONPObject testJSONP(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(1000L).setItemDesc("JSONP测试!!!");
return new JSONPObject(callback, itemDesc);
}
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允许访问的策略
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET","POST") //定义允许跨域的请求类型
.allowedOrigins("*") //任意网址都可以访问
.allowCredentials(true) //是否允许携带cookie
.maxAge(1800); //设定请求长链接超时时间.
}
}
JSON数据格式
1.jsonp
jsonp本质利用javaScript中的src属性的get请求实现的跨域.
返回值必须经过特殊的格式封装.
2.cors
添加在响应头中信息.指定哪些服务器允许访问.
当用户在注册时,如果输入用户名,则应该向jt-sso单点登录系统发起请求,校验用户数据是否存在.
如果存在则提示用户.
1.url分析
2.检索JS代码
3. JS分析
$.ajax({
url : "http://sso.jt.com/user/check/"+escape(pin)+"/1?r=" + Math.random(),
dataType : "jsonp",
success : function(data) {
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;
}
}
});
/**
* 业务说明: jt-web服务器获取jt-sso数据 JSONP跨域请求
* url地址: http://sso.jt.com/user/check/{param}/{type}
* 参数: param: 需要校验的数据 type:校验的类型
* 返回值: SysResult对象
* 真实的返回值: callback(SysResult的JSON)
*/
@RequestMapping("/check/{param}/{type}")
public JSONPObject checkUser(@PathVariable String param,
@PathVariable Integer type,
String callback){
//true 表示数据存在 false 表示数据可以使用
boolean flag = userService.checkUser(param,type);
SysResult.success(flag);
return new JSONPObject(callback, SysResult.success(flag));
}
/**
* 判断依据: 根据用户名查询 如果结果>0 用户已存在.
* @param param
* @param type
* @return
*/
@Override
public boolean checkUser(String param, Integer type) {
//1.需要将type类型转化为 具体字段信息 1=username 2=phone 3=email
String column = columnMap.get(type);
QueryWrapper
queryWrapper.eq(column, param);
Integer count = userMapper.selectCount(queryWrapper);
return count > 0 ? true :false;
}
当后端服务器执行出错时,会执行全局异常的处理.但是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.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
//@ControllerAdvice //拦截controller层
//@ResponseBody
@RestControllerAdvice //定义全局异常的处理类 AOP=异常通知
public class SystemAOP {
/**
* 定义全局异常的方法 当遇到了什么异常时,程序开始执行 参数一般class类型
* 如果一旦发生异常,则应该输出异常的信息,之后返回错误数据即可.
*
* 解决跨域全局异常处理的规则: 京淘项目的跨域都是使用JSONP. http://xxxx?callback=xxxxx
* 如果请求中携带了callback参数 则认为是JSONP跨域请求.
* 难点: 如何获取callback参数呢??/
*/
@ExceptionHandler({RuntimeException.class})
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());
}
}
}
业务说明:当做某些操作时,可能会对数据进行业务加工,之后由服务器与服务器之间形同通讯.
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)
package com.jt;
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.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
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 HttpClientTest {
/**
* 要求:在java代码内部,获取百度的页面.
* 实现步骤:
* 1.确定目标地址: https://www.baidu.com/
* 2.创建httpClient客户端对象
* 3.创建请求类型
* 4.发起http请求.并且获取响应的结果.之后判断状态码是否为200 如果等于200则请求正确
* 5.如果请求正确则动态获取响应值信息.之后进行数据的再次加工....
* */
@Test
public void testGet() throws IOException {
String url = "https://www.jd.com/";
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200) {
//表示用户请求正确
//获取返回值数据
HttpEntity httpEntity = httpResponse.getEntity();
String result = EntityUtils.toString(httpEntity, "UTF-8");
System.out.println(result);
}
}
}
用户通过网址 http://www.jt.com/getItems 要求采用httpClient方式,获取jt-manage中的商品信息 之后json串的形式展现.
jt-web服务器访问jt-manage时的网址 http://manage.jt.com/getItems.
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
return httpClientService.getItems();
}
}
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
return itemService.getItems();
}
}
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
return itemService.getItems();
}
}
@Override
public List
return itemMapper.selectList(null);
}
面向服务的架构(SOA)是一个组件模型,**它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来。**接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
RPC是远程过程调用(Remote Procedure Call)的缩写形式。
总结:
1. 当完成业务时自己没有办法直接完成时,需要通过第三方帮助才能完成的业务.
2. 使用RPC时"感觉"上就是在调用自己的方法完成业务.
核心: 1.分布式思想(拆) 2.自动化(HA,自动化)
1.如果采用nginx方式 实现负载均衡,当服务数量改变时,都必须手动的修改nginx.conf配置文件.不够智能.
2.所有的请求都会通过nginx服务器作为中转.如果nginx服务器一旦宕机,则直接影响整个系统.nginx最好只做简单的反向代理即可
传统的方式 不够智能…
调用步骤:
1.将服务信息写入到注册中心(1.服务名称 2.服务IP地址 3.端口)
2.注册中心接收到服务器信息,会动态的维护服务列表数据.
3.消费者启动时会链接注册中心.目的获取服务列表数据.
4.注册中心会将服务列表数据同步给消费者,并且保存到消费者本地.以后方便调用.
5.当消费者开始业务调用时,会根据已知的服务信息进行负载均衡操作,访问服务提供者.
6.当服务提供者宕机时,由与注册中心有心跳检测机制.所以会动态的维护服务列表.
7.当注册中心的服务列表变化时, 则会全网广播 通知所有的消费者 更新本地服务列表.
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_home\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
概括: ZK主要的任务是服务的调度,提供一致性的功能.
公式: 存活节点的数量 > N/2 集群可以创建
1台: 1-1 > 1/2 假的
2台: 2-1> 2/2 假的
3台: 3-1> 3/2 正确
4台: 4-1> 4/2 正确
结论: 搭建集群的最小单位3台.
原则: myid最大值优先 myid值越大的越容易当主机. 超半数同意即当选主机
题目: 问1,2,3,4,5,6,7依次启动 问1:谁当主机 4当主机
问2:谁永远不能当选主机??? 1 2 3
预习Dubbo框架
修改代码:
修改入门案例的dubbo项目的pom.xml文件
2.修改module标签
3.导入项目
将dubbo-jt项目粘贴到工作空间 和jt平级 之后右键 add Maven…