1 课程补充
1.1 分片高级
1.1.1 如何理解分片多个key
说明:
分片对外的统一的整体,内部由多个redis共同维护,维护的内存是多台redis的内存之和.
1.1.2 如果set(Key),通过haxi计算只能落入到唯一的一个node节点中,所以即使通过非法的操作手动为某一个节点set(key).它也不违反哈希一致性.因为取值时该key永远不会被获取.
1.2 工厂介绍
1.2.1 静态工厂
- 编辑配置文件
<!--静态工厂 --> <bean id="calendarA" class="java.util.Calendar" factory-method="getInstance"/> //测试静态工厂 @Test public void test01(){ //创建spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("/spring/applicationContext-factory.xml"); System.out.println("容器创建成功"); Calendar calendar = (Calendar) context.getBean("calendarA"); System.out.println(calendar.getTime()); }
说明:静态工厂的使用:
当类不能直接实例化时,采用静态工厂的方式.其调用的方法其实就是Class.静态方法.
1.2.2 实例化工厂
说明:实例化工厂其实就是先创建工厂对象,之后代用工厂的方法创建需要对象
NewFacotry factory = new NewFactory();
Item item = factory.getItem();
<!--实例化工厂 1.会创建工厂对象 2.通过对象调用工厂方法 --> <bean id="newFactory" class="com.jt.manage.factory.NewInstanceFactory"/> <bean id="item" factory-bean="newFactory" factory-method="getItem"/>
测试类:
@Test public void test02(){ //创建spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("/spring/applicationContext-factory.xml"); System.out.println("容器创建成功"); Item item = (Item) context.getBean("item"); System.out.println(item); }
1.2.3 Spring工厂模式
说明:Spring工厂模式需要实现指定的接口FacotryBean<T>接口,那么当Spring容器在解析bean时,会自动的调用接口方法创建对象
public class ItemFactory implements FactoryBean<Item>{ @Override public Item getObject() throws Exception { System.out.println("我是spring工厂开始实例化对象"); return new Item(); } @Override public Class<?> getObjectType() { // TODO Auto-generated method stub return Item.class; } //是否为单例对象 @Override public boolean isSingleton() { // TODO Auto-generated method stub return false; } }
代码测试:
2 京淘项目的前台搭建
2.1 前台搭建
2.1.1 项目说明
说明:前台系统只负责数据的展现.获取商品数据时需要通过远程调用从后台系统中获取Item数据.
框架的选择:SpringMVC/Spring
2.2 创建前台项目
2.2.1 创建项目
1.选择骨架
- 编辑名称
- 修改JDK 补齐文件包
- 继承jt-parent 之后保存
- 依赖工具类
2.2.2 引入tomcat插件
<!--引入tomcat插件 将原有的build删除 第8行 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8092</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
- 配置tomcat启动
2.2.3 引入配置文件
2.2.4 引入静态资源文件
说明:将课前资料中的webapp文件导入
2.2.5 修改web.xml文件
1.将spring监听器的方式注释或删除
2.修改前端控制器的文件
2.2.6 修改springMVC的配置文件
2.2.7 修改spring的配置文件
将多余的properties删除.
2.3 京淘首页跳转
2.3.1 编辑Controller
@Controller
public class IndexController {
//实现京淘前台页面跳转 localhost:8092/index.html
@RequestMapping("/index")
public String index(){
return "index";
}
页面展现效果:
2.4 Nginx管理京淘前台
2.4.1 修改nginx配置
#京淘前台管理
server {
listen 80;
server_name www.jt.com;
#页面转向 转向的是一个具体的url
location / {
proxy_pass http://localhost:8092;
}
}
2.修改hosts文件
# 京淘电商环境
127.0.0.1 image.jt.com
127.0.0.1 manage.jt.com
127.0.0.1 www.jt.com
127.0.0.1 sso.jt.com
127.0.0.1 cart.jt.com
127.0.0.1 order.jt.com
127.0.0.1 solr.jt.com
2.5 跨域问题
2.5.1 跨域的测试
说明:
根据url的不同,会生跨域的问题.跨域问题是Http协议的禁止访问的,出于安全性的考虑.
说明:通过图上所示,浏览器不能直接解析跨域的文件.
2.5.2 用域和跨域
同域:
域名相同
端口号相同
通信协议相同
案例:
1.访问文件不同
http://www.a.com/a.js
同域
2.访问路径不用
同域
3.端口号不同
4.通讯协议不同
http://www.a.com/b.js
2.6 解决跨域
2.6.1 原理说明
说明:利用javaScript中src属性实现跨域访问.因为src浏览器没有限制.
根据js调用的函数的名称,对指定的JSON数据进行包装 函数名({JSON数据}).
通过该方式实现跨域访问.
<title>测试JSON跨域问题</title>
<script type="text/javascript">
/*引用src中的JS函数 */
function tarena(data){
alert(data.name);
}
</script> <!-- hello({"id":"1","name":"tom"}) -->
<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>
远程JSON数据
2.7 JSONP
2.7.1 介绍
2.7.2 用法
说明:
- 采用JSONP的调用返回的格式是一个JSON
- JSONP在进行数据传参时会添加callback=函数名称.该名称需要服务端动态获取后,动态的拼接JSON数据=函数名称({JSON数据})
案例:
url:
localhost:8092/findUser?callback=findUser
服务端编辑JSON数据
public String findUser(String callback){
User user = userService.findUser();
String JSON = User的json串
Return “callback+”(”+JSON +”)”
}
2.8 三级商品分类菜单实现
2.8.1 分析页面
说明:京淘的前端页面是web前端开发工程师完成.都是需要和后端工程师配合一起完成.
2.8.2 JSON数据的分析
分析:
- 最外层只有一个属性的对象 属性类型 List<?> data
- 分析:根据图中所示.一级商品的分类菜单中需要包含3个属性 u:n:i.
3.二级商品分类菜单和一级相同
4.三级商品分类用字符串编辑
2.8.3 编辑后台Controller
2.8.4 编辑Service
/* * 分析: 由于商品的分类信息较多,如果按照1级查询2级查询3级这样的结构 * 会查询很多次,数据库压力较大 * 解决: * 首先查询全部的商品分类信息.之后进行数据的整理 * Map<parentId,List<ItemCat> itemcatLists> * parentId 表示父级的Id * itemCatLists.表示的是当前父级Id下所有的子级菜单 * * 步骤: * 1.封装一级商品分类信息 * 2.封装二级商品分类信息 * 3.封装三级商品分类信息 * */ @Override public ItemCatResult findItemCatAll() { //查询全部的商品分类信息 ItemCat tempItemCat = new ItemCat(); tempItemCat.setStatus(1); //查询正常的商品分类信息 List<ItemCat> itemCatLists = itemCatMapper.select(tempItemCat); //整理数据 Map<Long, List<ItemCat>> itemCatMap = new HashMap<Long, List<ItemCat>>(); for (ItemCat itemCat : itemCatLists) { if(itemCatMap.containsKey(itemCat.getParentId())){ //表示已经含有parentId,做数据的追加操作 itemCatMap.get(itemCat.getParentId()).add(itemCat); }else{ //为父级创建List集合 List<ItemCat> itemCatList = new ArrayList<ItemCat>(); itemCatList.add(itemCat); itemCatMap.put(itemCat.getParentId(), itemCatList); } } //构建返回对象 ItemCatResult itemCatResult = new ItemCatResult(); //封装一级商品分类菜单 List<ItemCatData> itemCatDataList = new ArrayList<ItemCatData>(); for (ItemCat itemCat1 : itemCatMap.get(0L)) { //定义一级商品分类对象 ItemCatData itemCatData1 = new ItemCatData(); itemCatData1.setUrl("/products/"+ itemCat1.getId()+".html"); itemCatData1.setName ("<a href='"+itemCatData1.getUrl()+"'>"+itemCat1.getName()+"</a>"); //封装商品分类的二级菜单 List<ItemCatData> itemCatDataList2 = new ArrayList<ItemCatData>(); for (ItemCat itemCat2 : itemCatMap.get(itemCat1.getId())) { ItemCatData itemCatData2 = new ItemCatData(); itemCatData2.setUrl("/products/"+itemCat2.getId()); itemCatData2.setName(itemCat2.getName()); //准备三级商品分类菜单 List<String> itemCatDataList3 = new ArrayList<String>(); for (ItemCat itemCat3 : itemCatMap.get(itemCat2.getId())) { itemCatDataList3.add("/products/"+itemCat3.getId() + "|" +itemCat3.getName()); } //将三级分类的集合注入到二级对象中 itemCatData2.setItems(itemCatDataList3); itemCatDataList2.add(itemCatData2); } itemCatData1.setItems(itemCatDataList2); itemCatDataList.add(itemCatData1); //封装参数 多余的直接跳出 if(itemCatDataList.size() >13) break; } //封装一级商品分类的菜单 itemCatResult.setItemCats(itemCatDataList); return itemCatResult; }
2.8.5 工具类方法操作JSONP
/** * 利用工具类直接返回JSONP的对象 callback({JSON}) * @param callback * @return */ @RequestMapping("/web/itemcat/all") @ResponseBody public Object findItemCat(String callback){ ItemCatResult itemCatresult = itemCatService.findItemCatAll(); //负责JSONP对象返回 构造方法中添加返回的数据 MappingJacksonValue jacksonValue = new MappingJacksonValue(itemCatresult); //设定返回值方法 jacksonValue.setJsonpFunction(callback); return jacksonValue; }