SSO單點登入redis配置
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. 實現購物車新增的功能
功能描述:
通過查詢商品詳細頁展現商品資訊.當點選加入購物車時實現該業務邏輯
根據介面文件的規範完成.