Easymall项目分布式拆分整合(七) 不念不忘少年蓝@ 2022-05-01 12:51 268阅读 0赞 # Easymall项目分布式拆分整合(七) # -------------------- **目录** Easymall项目分布式拆分整合(七) 一.Easymall分布式项目结构 二.用户搭建(最基础的六部) 1.创建一个quickstart的maven工程(src/main/resources) 2.pom继承parent,依赖common 3.后台user系统需要的其他依赖 4.application.properties文件 5.启动类(MapperScan) 6.nginx和hosts文件 1.nginx配置 2.hoste文件配置 三.用户系统的功能 一.注册用户用户名校验 1.接口文件 2.UserController 3.UserService 二.注册表单数据的提交 1.接口文件 2.UserController 3.UserService 三.实现注册方法与前台系统的整合 1.调用结构 2.前台的结构搭建 3.导入一个UserController类 3.创建一个UserService等待逻辑编写 1.用户名称校验 2.打开controller对应的交互逻辑代码注册user 四.用户的登录逻辑 一.接口方法,处理登录的校验 1.登录的用户系统校验逻辑 2.接口文件 3.编写用户登录逻辑 1.UserController类 2.RedisCumUtils中添加一个超时方法 3.UserService(redisUtil)类 4.js页面发起ajax请求获取user登录的状态信息(携带cookie的值) 1.接口文件 2.UserController 3.UserService -------------------- # 一.Easymall分布式项目结构 # ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpdVk1MjE_size_16_color_FFFFFF_t_70][] # 二.用户搭建(最基础的六部) # ## 1.创建一个quickstart的maven工程(src/main/resources) ## ![2019061115054217.png][] ## 2.pom继承parent,依赖common ## ![20190611150627249.png][] ## 3.后台user系统需要的其他依赖 ## <dependencies> <dependency> <groupId>cn..tedu</groupId> <artifactId>springboot-common-easymall</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> ## 4.application.properties文件 ## * 端口8093 * datasource * mybatis * redis server.port=8093 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql:///easydb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true spring.datasource.password=root spring.datasource.username=root mybatis.configuration.mapUnderscoreToCamelCase=true mybatis.mapperLocations=classpath:mapper/*.xml mybatis.typeAliasesPackage=com.jt.common.pojo redis.nodes=10.42.60.249:6379 redis.maxTotal=200 redis.maxIdle=8 redis.minIdle=3 ## 5.启动类(MapperScan) ## * 扫描接口mapper的包 * UserMapper(重新导入User的包名,common) * UserMapper.xml(修改namespce对应新的接口全路径) * 启动类 package com.jt; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.jt.user.mapper") public class StarterUser { public static void main(String[] args) { SpringApplication.run(StarterUser.class, args); } } ## 6.nginx和hosts文件 ## ### 1.nginx配置 ### #User服务器 server { listen 80; server_name user.easymall.com; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://127.0.0.1:8093; proxy_connect_timeout 600; proxy_read_timeout 600; } } ### 2.hoste文件配置 ### <table style="margin-left:1.0833in;"> <tbody> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.0111in;"> <p style="margin-left:0in;">127.0.0.1</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:1.8847in;"> <p style="margin-left:0in;">user.easymall.com</p> </td> </tr> </tbody> </table> ![20190611152014722.png][] # 三.用户系统的功能 # # 一.注册用户用户名校验 # ## 1.接口文件 ## <table style="margin-left:.3333in;"> <tbody> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.327in;"> <p style="margin-left:0in;">请求地址</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.0388in;"> <p style="margin-left:0in;">user.easymall.com<span style="color:#ff0000;">/user/checkUserName/{userName}</span></p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.327in;"> <p style="margin-left:0in;">请求方式</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.0388in;"> <p style="margin-left:0in;">GET</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.327in;"> <p style="margin-left:0in;">请求参数</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.0388in;"> <p style="margin-left:0in;">路径传参的String userName</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.327in;"> <p style="margin-left:0in;">返回数据</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.0388in;"> <p style="margin-left:0in;">存在返回1不可用,不存在返回0表示可用</p> </td> </tr> </tbody> </table> ## 2.UserController ## public class UserController { @Autowired private UserService userService; //接收前台的请求,返回数据库用户名可用还是不可用 @RequestMapping("checkUserName/{userName}") public Integer checkUserName(@PathVariable String userName){ Integer exist=userService.checkUserName(userName); return exist; } ## 3.UserService ## @Autowired private UserMapper userMapper; public Integer checkUserName(String userName) { return userMapper.queryName(userName); } # 二.注册表单数据的提交 # # 1.接口文件 # <table style="margin-left:.3333in;"> <tbody> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1909in;"> <p style="margin-left:0in;">请求地址</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.1743in;"> <p style="margin-left:0in;">user.easymall.com/user/save</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1909in;"> <p style="margin-left:0in;">请求方式</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.1743in;"> <p style="margin-left:0in;">post</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1909in;"> <p style="margin-left:0in;">请求参数</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.1743in;"> <p style="margin-left:0in;">User user对象接收,缺少的属性type,默认0,userId使用UUID解决</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1909in;"> <p style="margin-left:0in;">返回数据</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:5.1743in;"> <p style="margin-left:0in;"><span style="color:#ff0000;">1.SysResult的结构的数据,需要前端调用之后解析数据,可以满足返回数据的丰富性(既可以传递结果,也可以传递消息)</span></p> <p style="margin-left:0in;">2.新增成功失败返回1/0</p> </td> </tr> </tbody> </table> ## 2.UserController ## @RequestMapping("save") public Integer saveUser(User user){ try{ userService.saveUser(user); return 1; }catch(Exception e){ e.printStackTrace(); return 0; } } ## 3.UserService ## public void saveUser(User user) { //user的id,type,password的加密 user.setUserId(UUID.randomUUID().toString()); user.setUserPassword(MD5Util.md5(user.getUserPassword())); user.setUserType(0); userMapper.insertUser(user); } # 三.实现注册方法与前台系统的整合 # ## 1.调用结构 ## ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpdVk1MjE_size_16_color_FFFFFF_t_70 1][] ## 2.前台的结构搭建 ## **将easymall单体项目中的UserController(包含了与页面的交互逻辑),粘贴到web前端系统** ![2019061119445547.png][] ## 3.导入一个**UserController类** ## @Controller public class UserController { @Autowired private UserService userService; //ajax查询用户是否名称存在 @RequestMapping(value="user_ajax/checkUserName" ,method=RequestMethod.POST) @ResponseBody public SysResult checkUserName(String userName){ int exist=userService.queryName(userName); //数据库如果存在,返回1,数据库如果不存在返回0 return SysResult.build(exist, "ok", null); } @RequestMapping(value="/user_ajax/regist" ,method=RequestMethod.POST) @ResponseBody public SysResult saveUser(User user){ try{ //业务层调用,插入表格数据 userService.saveUser(user); return SysResult.build(1, null, null); }catch(Exception e){ e.printStackTrace(); return SysResult.build(0, null, null); } } ## 3.创建一个UserService等待逻辑编写 ## ### 1.用户名称校验 ### private static final String url="http://user.easymall.com/user/"; //注入httpClient @Autowired private HttpClientService client; public int queryName(String userName) { //按照接口文件进行调用和传参和数据的接收 String userUrl=url+"checkUserName/"+userName; try{ String exist=client.doGet(userUrl); return Integer.parseInt(exist); }catch(Exception e){ e.printStackTrace(); return 0; } } ### 2.打开controller对应的交互逻辑代码注册user ### **编写service中saveUser方法** public void saveUser(User user) { //按照注册接口调用user系统 String userUrl=url+"save"; try{ //生成参数 Map<String,Object> param=new HashMap<String,Object>(); param.put("userName", user.getUserName()); param.put("userPassword", user.getUserPassword()); param.put("userEmail", user.getUserEmail()); param.put("userNickname", user.getUserNickname()); client.doPost(userUrl,param); }catch(Exception e){ e.printStackTrace(); } } ## 四.用户的登录逻辑 ## ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpdVk1MjE_size_16_color_FFFFFF_t_70 2][] **用户登录逻辑,需要处理session共享问题,将用户信息,存储在redis中将key作为数据返回页面时,放到cookie中,只要cookie中key,后续访问逻辑www.easymall.com系统时,都会携带这个key,从而可以处理获取redis的数据使用.** # 一.接口方法,处理登录的校验 # ## 1.登录的用户系统校验逻辑 ## * 用户名密码的校验(where userName password是否存在数据) * 如果不存在,按照接口返回不存在的数据 * 如果存在,将查询到的user作为整体数据存放到redis key值计算逻辑(公式:"EM\_TICKET"+currentTime+userId),value值就是userJson字符串 * 将ticket的key值返回给前台 ## 2.接口文件 ## <table style="margin-left:.7083in;"> <tbody> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.5548in;"> <p style="margin-left:0in;">请求地址</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.4361in;"> <p style="margin-left:0in;">user.easymall.com/user/login</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.5548in;"> <p style="margin-left:0in;">请求的参数</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.4361in;"> <p style="margin-left:0in;">User user对象接收,自动封装了userName和Password</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.5548in;"> <p style="margin-left:0in;">请求方式</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.4361in;"> <p style="margin-left:0in;">get/post</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.5548in;"> <p style="margin-left:0in;">返回数据</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.4361in;"> <p style="margin-left:0in;">将存储在redis中的当前ticket的key值返回,存储到redis中的数据表示一个用户的登录状态(userJson),所以不能是永久数据,设置超时(<span style="color:#ff0000;">做后续的逻辑</span><span style="color:#ff0000;">,</span><span style="color:#ff0000;">同一个用户最多登录一次</span>)</p> </td> </tr> </tbody> </table> ## 3.编写用户登录逻辑 ## ### 1.UserController类 ### //验证登录的用户名密码是否正确 @RequestMapping("login") public String doLogin(User user){ String ticket=userService.doLogin(user); //成功登录返回redis的key,失败返回"" return ticket; } ### 2.RedisCumUtils中添加一个超时方法 ### //封装一个带有超时逻辑的add方法 public void addOrUpdateExpire(String key,String value,Integer seconds){ ShardedJedis jedis = pool.getResource(); try{ jedis.setex(key, seconds, value); }catch(Exception e){ //异常处理逻辑 }finally{ pool.returnBrokenResource(jedis); } } ### 3.UserService(redisUtil)类 ### @Autowired private RedisCumUtils redis; public String doLogin(User user) { //查询一下数据库数据,是否存在userExist //处理用户密码加密 user.setUserPassword(MD5Util.md5(user.getUserPassword())); User exist=userMapper.selectExist(user); try{ if(exist==null){//登录失败 return ""; }else{//表示成功,存储在redis返回key值 String ticket=MD5Util.md5("EM_TICKET"+System.currentTimeMillis() +exist.getUserId()); //准备value值,mapper转化user为json字符串 String userJson=MapperUtils.MP.writeValueAsString(exist); //set数据到redis供后续逻辑使用 redis.addOrUpdateExpire(ticket, userJson, 60*30); //验证最多一个用户登录,顶替登录逻辑 //TODO return ticket; } }catch(Exception e){ e.printStackTrace(); return ""; } } ## 4.js页面发起ajax请求获取user登录的状态信息(携带cookie的值) ## **将jsp文件中head.jsp的js代码修改访问的域名,从原有的sso.jt.com换成user.jt.com** ### 1.接口文件 ### <table style="margin-left:.7083in;"> <tbody> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1777in;"> <p style="margin-left:0in;">请求地址</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.8131in;"> <p style="margin-left:0in;">user.easymall.com/user/query/{ticket}</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1777in;"> <p style="margin-left:0in;">请求方式</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.8131in;"> <p style="margin-left:0in;">get</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1777in;"> <p style="margin-left:0in;">请求参数</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.8131in;"> <p style="margin-left:0in;">redis中的key值,ticket路径接参</p> <p style="margin-left:0in;">String callback</p> </td> </tr> <tr> <td style="border-color:#a3a3a3;vertical-align:top;width:1.1777in;"> <p style="margin-left:0in;">返回数据</p> </td> <td style="border-color:#a3a3a3;vertical-align:top;width:4.8131in;"> <p style="margin-left:0in;">通过对callback的判断,实现返回数据的封装,</p> <p style="margin-left:0in;">if(callback==null)说明不是<span style="color:#ff0000;">jsonp</span>请求,返回syResult的json字符串</p> <p style="margin-left:0in;">if(callback!=null)说明是<span style="color:#ff0000;">jsonp</span>请求,返回</p> <p style="margin-left:0in;">callback(+sysResultJson+)</p> <p style="margin-left:0in;">sysResult的status==200表示成功,201表示失败</p> </td> </tr> </tbody> </table> ### 2.UserController ### //校验登录状态,查询redis数据 @RequestMapping("query/{ticket}") public String checkTicket(@PathVariable String ticket ,String callback){ try{ //走到redis校验数据 String userJson=userService.queryTicket(ticket); //封装返回的json数据,SysResult SysResult result=null; if(StringUtils.isNotEmpty(userJson)){//登录状态正常 result=SysResult.build(200, "", userJson); }else{ result=SysResult.build(201, "", null); } //将result解析成json等待返回使用 String resultJson=MapperUtils.MP.writeValueAsString(result); //判断请求需要的数据格式,callback if(callback==null){ return resultJson;//作为json字符串返回 }else{ return callback+"("+resultJson+")";//jsonp格式返回 } }catch(Exception e){ return ""; } } ### 3.UserService ### public String queryTicket(String ticket) { //TODO 超时时间延长--续租 return redis.query(ticket); } [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpdVk1MjE_size_16_color_FFFFFF_t_70]: /images/20220119/5fe9d07931d347ecbba91b15644eab93.png [2019061115054217.png]: /images/20220119/98546d4ac4cc4a9f89084918e3ca0eba.png [20190611150627249.png]: /images/20220119/e0201286f4f24e57abe6739cb4101f46.png [20190611152014722.png]: /images/20220119/85d5e03ee49241a18ad247f3fd6b0231.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpdVk1MjE_size_16_color_FFFFFF_t_70 1]: /images/20220119/4dd0b9ba24564187956eeb20ee86655a.png [2019061119445547.png]: /images/20220119/3490df8721934b919189797cc9161fb0.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0xpdVk1MjE_size_16_color_FFFFFF_t_70 2]: /images/20220119/f15a03c986b445f2a9411e3a6f6e869a.png
相关 EasyMall第七天 8.15 <%= %>可以写: 1、常量 2、变量 3、表达式 服务器发送是编码:response.setcharacte 今天药忘吃喽~/ 2022年06月09日 09:17/ 0 赞/ 267 阅读
相关 Easymall项目分布式拆分整合(七) Easymall项目分布式拆分整合(七) -------------------- 目录 不念不忘少年蓝@/ 2022年05月01日 12:51/ 0 赞/ 269 阅读
相关 Easymall项目分布式拆分整合(四) Easymall项目分布式拆分整合(四) -------------------- 目录 桃扇骨/ 2022年04月27日 19:52/ 0 赞/ 351 阅读
相关 Easymall项目分布式拆分整合(二) Easymall项目分布式拆分整合(二) -------------------- 目录 r囧r小猫/ 2022年04月27日 16:54/ 0 赞/ 354 阅读
相关 Easymall项目分布式拆分整合(六) 前台系统和后台系统的功能整合 -------------------- 目录 刺骨的言语ヽ痛彻心扉/ 2022年01月20日 08:45/ 0 赞/ 203 阅读
相关 Easymall项目分布式拆分整合(五) Easymall项目分布式拆分整合(五) 目录 Easymall项目分布式拆分整合(五) 一.搭建后台 你的名字/ 2022年01月20日 02:33/ 0 赞/ 323 阅读
相关 Easymall项目分布式拆分整合(八) Easymall项目分布式拆分整合(八) -------------------- 目录 系统管理员/ 2022年01月15日 16:43/ 0 赞/ 269 阅读
相关 Easymall项目分布式拆分整合(九) Easymall项目分布式拆分整合(九) -------------------- 一.购物车系统搭建 古城微笑少年丶/ 2022年01月15日 03:35/ 0 赞/ 310 阅读
还没有评论,来说两句吧...