1 Redis集群的方式
1.1 切换redis的配置方式
1. 就用6379一个redis
Spring配置文件中 添加<bean id=”jedis”class=”Jedis.class”></bean>
@Autowired
Private Jedis jedis;
2. 采用redis的分片
a) 分别使用3台redis提供服务,.配置文件参见笔记.
1.2 其他的环境问题
Tomcat:tomcat插件
Mysql:window中的Mysql
Nginx: 检查配置文件 拷贝别人的conf
2 单点登录
2.1 SSO复习
2.1.1 单点中的要素
1. Ticket:它是一个加密后的密码(MD5),用户登录后的凭证
2. 用户信息:根据用户名和密码查询到的真实的用户信息 UserJSON
3. 如何取值
2.1.2 HttpCLient的请求方式
说明:Java操作HTTP请求的API,所以httpClient发出请求时,浏览器监听不到
2.1.3 HttpClient传参方式
3 用户登陆实现
3.1 SSO单点登录实现
3.1.1 前台Controller
//用户登陆 http://www.jt.com/service/user/doLogin?r=0.582247581950398
//通过login.jsp检测登陆的username和password是否正确
@RequestMapping("/doLogin")
@ResponseBody
public SysResult doLogin(String username,String password,
HttpServletRequest request,HttpServletResponseresponse){
//判断用户名和密码是否为null
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
return SysResult.build(201, "用户名密码不能为空");
}
//当前输入的用户名是正确的
try {
//获取用户的ticket
String ticket =
userService.findUserByUP(username,password);
//ticket不为空
if(!StringUtils.isEmpty(ticket)){
//如果ticket数据不为空 则写入cookie
//Cookie[] cookies =request.getCookies();
//Cookie的名称必须为 JT_TICKET
CookieUtils.setCookie(request, response, "JT_TICKET", ticket);
return SysResult.oK(ticket);
}
} catch (Exception e) {
e.printStackTrace();
}
return SysResult.build(201, "用户登陆失败");
}
3.1.2 编辑前台Service
//返回ticket数据
@Override
public String findUserByUP(String username, String password) {
String uri = "http://sso.jt.com/user/login";
Map<String, String> map = new HashMap<String,String>();
//注意不要有空格 为了网络中传递的速度更快 采用简单字符传递
map.put("u", username);
map.put("p", password);
try {
String resutJSON = httpClient.doPost(uri,map);
//判断数据是否有效 将其转化为Sysresult对象
//为了防止data数据为null时,返回的字符串为"null"对代码产生影响
SysResult sysResult =
objectMapper.readValue(resutJSON,SysResult.class); //判断SSO返回是否正确
if(sysResult.getStatus() == 200){
return (String) sysResult.getData();
}
} catch (Exception e) {
e.printStackTrace();
}
returnnull;
}
3.1.3 编辑单点Controller
/**
* @RequestParam作用:
* 表示参数接收时采用 u的关键字获取.将获取到的value值交给
* username属性
* @paramusername
* @parampassword
* @return
*/
//http://sso.jt.com/user/login
@RequestMapping("/login")
@ResponseBody //形成的JSON数据 {status=201,msg="",data="null"}
public SysResult doLogin(@RequestParam("u")String username,
@RequestParam("p")String password){
try {
//获取ticket信息
String ticket = userService.findUserByUP(username,password);
return SysResult.oK(ticket);
} catch (Exception e) {
e.printStackTrace();
}
return SysResult.build(201, "登录失败");
}
3.1.4 编辑单点Service
/**
* 1.验证用户名和密码是否正确
* 2.需要将用户的明文加密为密文
* 3.如果用户信息校验通过.准备redis缓存数据
* 4.生成ticket= md5(“JT_TICKET_” + System.currentTime + username)
* 5.将User对象转化为JSON数据
* 6.将ticket和UserJSON数据存入redis
* 7.return 返回ticket
*/
@Override
public String findUserByUP(String username, String password) {
//根据用户名和加密后的密码查询用户信息
String md5Password = DigestUtils.md5Hex(password);
User user = userMapper.selectUserByUP(username,md5Password);
//判断user是否为null
if(user !=null){
//准备ticket信息
String ticket = "JT_TICKET_" + System.currentTimeMillis()
+ user.getUsername();
//加密ticket
String md5Ticket = DigestUtils.md5Hex(ticket);
try {
String userJSON = objectMapper.writeValueAsString(user);
//将数据存入redis中
jedisCluster.set(md5Ticket, userJSON);
returnmd5Ticket;
} catch (Exception e) {
e.printStackTrace();
}
}
returnnull;
}
3.2 登录数据的回显
3.2.1 分析页面JS
说明:用户发出JSONP请求 实现用户信息回显
Js文件在jt.js中第一行.
说明:
该JS通过Cookie获取JT_TICKET信息.如果TICKET不为null.则会发送AJAX请求.请求USERJSON数据.用于页面展现.
如果ticket为null,则说明用户没有登陆,则不予显示.
3.2.2 用户信息的回显
//根据ticket查询用户的JSON信息
//http://sso.jt.com/user/query/" +_ticket JSNP的提交
@RequestMapping("/query/{ticket}")
@ResponseBody
public Object findUserByTicket(@PathVariable String ticket,
String callback){
//获取用户的JSON数据
String userJSON = jedisCluster.get(ticket);
MappingJacksonValue jacksonValue =
new MappingJacksonValue(SysResult.oK(userJSON));
//设定返回的方法名称
jacksonValue.setJsonpFunction(callback);
returnjacksonValue;
}
3.2.3 用户的登出
思路:
1.cookie中获取ticket信息
2.删除redis缓存
3.删除cookie信息
4.跳转页面到系统欢迎页面
实现:
//用户的登出操作 //user/logout.html
//1.cookie中获取ticket信息
//2.删除redis缓存
//3.删除cookie信息
//4.跳转页面到系统欢迎页面
@RequestMapping("/logout")
public String logout(HttpServletRequest request,HttpServletResponseresponse){
String ticket = CookieUtils.getCookieValue(request,"JT_TICKET");
jedisCluster.del(ticket);
CookieUtils.deleteCookie(request, response, "JT_TICKET");
//通过重定向的方式返回系统首页
return"redirect:/index.html";
}
4 京淘购物车实现
4.1 购物车系统
4.1.1 前台如何连接购物车
4.2 购物车创建
4.2.1 新建购物车项目
选择web骨架
定义项目名称 jt-cart
4.2.2 引入jar包和引入工具类
引入parent项目
依赖工具类文件
4.2.3 添加tomcat插件
<!--修改端口号8094 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8094</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
4.2.4 修改配置文件
1. SpringMVC的配置文件
2. 修改Spring的配置文件
3. 修改Spring-mycatis的配置文件
4.2.5 根据表设计创建tb-cart表
说明:通过PD打开表设计.通过Sql语句创建jt_cart表
1.将sql语句复制到MYsql数据库中执行即可
建表完成后添加2条测试数据即可.
4.2.6 构建POJO对象
@Table(name="tb_cart")
publicclass Cart extendsBasePojo{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id; //购物车主键信息
private Long userId; //用户的id号
private Long itemId; //商品的Id
private String itemTitle; //商品标题
private String itemImage; //商品的首图
private Long itemPrice; //商品的价格
private Integer num; //商品数量
4.2.7 构建Mapper对象
public interface CartMapper extends SysMapper<Cart>{
}
4.2.8 构建Service
@Service
publicclass CartServiceImpl implementsCartService {
@Autowired
private CartMapper cartMapper;
}
4.2.9 构建Controller
@Controller
publicclass CartController {
@Autowired
private CartService cartService;
}
4.2.10 修改nginx
#京淘购物车系统
server {
listen80;
server_namecart.jt.com;
location/ {
proxy_passhttp://127.0.0.1:8094;
}
}
修改nginx之后重启nginx
3. 修改HOST文件
# 京淘电商环境
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
5 购物车实现
5.1 根据userId查询信息
5.1.1 接口文档定义
请求方法 |
GET |
URL |
http://cart.jt.com/cart/query/{userId} |
参数 |
userId 用户ID |
示例 |
|
返回值 |
{ status: 200 //200 成功,201 没有查到 msg: “OK” //返回信息消息 data: [1] 0: { created: 1418092628000 updated: 1418092628000 id:1 userId:1 itemId:39 itemTitle: “java核心技术” itemImage: http://image.jt.com/images/2015/06/11/20150309118.jpg itemPrice: 87200 num:1 } }
|
|
|
5.1.2 购物车Controller
/**
* 任务:根据用户id查询购物车信息
* url:http://cart.jt.com/cart/query/{userId}
* 返回SysResult对象 并且data数据中保存cartList的JSON数据
*/
@RequestMapping("/query/{userId}")
@ResponseBody
public SysResult findCartByUserId(@PathVariable Long userId){
try {
//获取cartList数据
List<Cart> cartList =
cartService.findCartByUserId(userId);
String cartListJSON =
objcetMapper.writeValueAsString(cartList);
return SysResult.oK(cartListJSON);
} catch (Exception e) {
e.printStackTrace();
return SysResult.build(201, "查询失败");
}
}
5.1.3 编辑Service
@Override
public List<Cart> findCartByUserId(Long userId) {
Cart cart = new Cart();
cart.setUserId(userId);
//通过通用Mapper查询购物车信息
returncartMapper.select(cart);
}
5.1.4 模拟访问
说明:模拟正确的请求,查看代码编辑是否正确.
5.1.5 前台访问分析
说明:根据页面请求响应页面
分析页面元素:
页面中需要循环遍历CartList集合.从Reqest域中获取
5.1.6 前台Controller编辑
@Controller
@RequestMapping("/cart")
publicclass CartController {
@Autowired
private CartService cartService;
//转向到购物车页面 /cart/show.html
@RequestMapping("/show")
public String findCartByUserId(Model model){
Long userId = 7L; //暂时写死UserId后期维护
//查询购物车列表信息
List<Cart> cartList =
cartService.findCartByUserId(userId);
//将数据写入request域中
model.addAttribute("cartList", cartList);
//转向cart.jsp页面
return"cart";
}
5.1.7 编辑前台Service
@Service
publicclass CartServiceImpl implementsCartService {
@Autowired
private HttpClientService httpClient;
privatestatic ObjectMapper objectMapper = new ObjectMapper();
@Override
public List<Cart> findCartByUserId(Long userId) {
String uri = "http://cart.jt.com/cart/query/" + userId;
try {
String resultJSON = httpClient.doGet(uri);
//数据data的数据类型是Object ,需要转化为LIst集合,
//但是转化会失败
//objectMapper.readValue(resultJSON,SysResult.class);
//通过ObjectMapper 直接获取json的属性
//要求:JSON串必须是对象的JSON{id:1,name:tom}
//而不能是List/array的JSON [value1,value2]
//{id:1,name:tom}
JsonNode jsonNode = objectMapper.readTree(resultJSON);
//将JSON数据转化为String类型的字符串 [{},{},{}]
String cartListJSON = jsonNode.get("data").asText();
//将cartList的JSON数转化为List集合
Cart[] carts =
objectMapper.readValue(cartListJSON,Cart[].class);
List<Cart> cartList = Arrays.asList(carts);
returncartList;
} catch (Exception e) {
e.printStackTrace();
}
returnnull;
}
5.2 购物车数量修改
5.2.1 业务接口文档定义
请求方法 |
GET |
URL |
http://cart.jt.com/cart/update/num/{userId}/{itemId}/{num} |
参数 |
userId 用户名ID itemId 商品ID num 数量 |
示例 |
http://cart.jt.com/cart/upadate/num/001/002/2 |
返回值 |
{ status: 200 msg: “OK” data:null } |
|
|
5.2.2 编辑修改Controller
//http://cart.jt.com/cart/update/num/{userId}/{itemId}/{num}
@RequestMapping("/update/num/{userId}/{itemId}/{num}")
@ResponseBody
public SysResult updateCartNum(
@PathVariable Long userId,
@PathVariable Long itemId,
@PathVariable Integer num){
try {
Cart cart = new Cart();
cart.setUserId(userId);
cart.setItemId(itemId);
cart.setNum(num);
cartService.updateCartNum(cart);
return SysResult.oK();
} catch (Exception e) {
e.printStackTrace();
return SysResult.build(201,"修改数量失败");
}
5.2.3 编辑购物车Service
@Override
publicvoid updateCartNum(Cart cart) {
//添加修改时间
cart.setUpdated(newDate());
cartMapper.updateNum(cart);
}
5.2.4 编辑映射文件
<mapper namespace="com.jt.cart.mapper.CartMapper">
<!--根据userId和itemId修改购物车的数量 -->
<update id="updateNum">
update tb_cart set num = #{num} where
user_id = #{userId} and item_id = #{itemId}
</update>
</mapper>
5.2.5 代码模拟测试
说明:根据业务中的路径测试方法编辑是否正确
5.2.6 分析页面
url:http://www.jt.com/service/cart/update/num/1474391958/101
说明:
数量的修改不需要校验,Controller返回任意值即可.
5.2.7 编辑前台Controller
//修改购物车商品数量
//urlhttp://www.jt.com/service/cart/update/num/1474391958/101
@RequestMapping("/update/num/{itemId}/{num}")
@ResponseBody
public String updateCartNum(@PathVariableLong itemId,
@PathVariable Integer num){
Long userId = 7L; //获取userId
Cart cart = new Cart();//为属性赋值
cart.setUserId(userId);
cart.setItemId(itemId);
cart.setNum(num);
cartService.updateCartNum(cart);
return"";
}
5.2.8 编辑前台Service
@Override
publicvoid updateCartNum(Cart cart) {
//定义urihttp://cart.jt.com/cart/update/num/{userId}/{itemId}/{num}
String uri =
"http://cart.jt.com/cart/update/num/"+cart.getUserId()+
"/"+cart.getItemId()+"/"+cart.getNum();
try {
httpClient.doGet(uri);
} catch (Exception e) {
e.printStackTrace();
}
}
5.2.9 效果展现
说明:当数量增减时,价格也会跟着变化,表示测试成功
5.3 商品的删除
5.3.1 接口文档定义
请求方法 |
GET |
URL |
http://cart.jt.com/cart/delete/{userId}/{itemId} |
参数 |
userId 用户ID itemId 商品ID |
示例 |
http://cart.jt.com/cart/delete/2/6 |
返回值 |
{ status: 200 msg: “OK” data:null } |
|
|
5.3.2 编辑购物车Controller
/**
* 编辑商品的删除
*url:http://cart.jt.com/cart/delete/{userId}/{itemId}
*/
@RequestMapping("/delete/{userId}/{itemId}")
@ResponseBody
public SysResult deleteCart(@PathVariableLong userId,
@PathVariable Long itemId){
try {
cartService.deleteCart(userId,itemId);
return SysResult.oK();
} catch (Exception e) {
e.printStackTrace();
return SysResult.build(201,"删除购物车失败");
}
}
5.3.3 定义购物车Service
@Override
publicvoid deleteCart(Long userId, Long itemId) {
Cart cart = new Cart();
cart.setUserId(userId);
cart.setItemId(itemId);
//调用父类的方法规范:调用父类的方法时最好添加super
super.deleteByWhere(cart);
}
5.3.4 模拟删除操作
5.3.5 前台的删除
说明:当前台数据删除时,应该再次跳转到购物车列表页面.
5.3.6 编辑前台Controller
//删除购物车 /cart/delete/7.html
@RequestMapping("/delete/{itemId}")
public String deleteCart(@PathVariableLong itemId){
Long userId = 7L;
cartService.deleteCart(userId,itemId);
//跳转到购物车列表页面 满足springMVC的要求 *.html
return"redirect:/cart/show.html";
}
5.3.7 编辑前台Service
@Override
publicvoid deleteCart(Long userId, Long itemId) {
//定义uri 进行路径拼接
String uri = "http://cart.jt.com/cart/delete/"+userId+"/"+itemId;
try {
httpClient.doGet(uri);
} catch (Exception e) {
e.printStackTrace();
}
}
6 作业:
1. 实现购物车新增的功能
功能描述:
通过查询商品详细页展现商品信息.当点击加入购物车时实现该业务逻辑
根据接口文档的规范完成.