Service call & distributed session

Table of contents

1. Nginx dynamic and static separation

Second, service calls

Create and configure zmall-cart shopping cart module

Create and configure zmall-order order module

service call

 Four, spring session actual combat

What is Spring Session

Why use Spring Session

Configure spring-session

Five, the second-level domain name problem

user login 


1. Nginx dynamic and static separation

Step 1: Add a second-level domain name through SwitchHosts: images.zmall.com

Step 2: Copy all the static resources js/css/images of Yibuy.com in this project to the html directory in nginx

Step 3: Add a second-level domain name images.zmall.com access mapping in the nginx core configuration file nginx.conf to realize the dynamic and static separation of nginx

Note: After the modification is successful, restart the nginx service to make the configuration take effect! ! !

server{
    listen 80;
    server_name images.zmall.com;
    location / {
        root html;
        index index.html;
    }
}

Copy the styles in the project to the html folder in nginx

 

Detect the success of viewing the static resource server configuration in the browser

http://images.zmall.com/css/style.css

Step 4: Delete the static static resources under the zmall-product commodity service and zmall-gateway gateway service, and use the static resources configured in nginx instead

Step 5: Modify the zmall-product commodity service

templates/common/head.html

<#assign ctx>
    <#--域名,动态请求时需加入该前缀-->
    http://product.zmall.com
</#assign>
<#--采用H5方式的base标签,在整个页面的url地址前加入,用于访问nginx中的静态资源-->
<base href="http://images.zmall.com/"/>

Step 6: Restart zmall-product, zmall-gateway and nginx respectively and enter the request address: zmall.com/product-serv/index.html to access the product service homepage, as shown below:

 

Second, service calls

Create and configure zmall-cart shopping cart module

Step 1: Create zmall-cart shopping cart module based on Spring initializr

Step 2: Configure the zmall-order order module into the main module

<modules>
    ...
    <module>zmall-cart</module>
    ...
</modules>

Step 3: Modify pom.xml

<parent>
    <groupId>com.zking.zmall</groupId>
    <artifactId>zmall</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>
<artifactId>zmall-cart</artifactId>

<dependencies>
    <dependency>
        <groupId>com.zking.zmall</groupId>
        <artifactId>zmall-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

Step 4: Configure application.yml (port: 8030)

server:
  port: 8030
spring:
  application:
    name: zmall-cart
  datasource:
    #type连接池类型 DBCP,C3P0,Hikari,Druid,默认为Hikari
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/zmall?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
    username: root
    password: 1234
  freemarker:
    suffix: .html
    template-loader-path: classpath:/templates/
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
#mybatis-plus配置
mybatis-plus:
  #所对应的 XML 文件位置
  mapper-locations: classpath*:/mapper/*Mapper.xml
  #别名包扫描路径
  type-aliases-package: com.zking.zmall.model
  configuration:
    #驼峰命名规则
    map-underscore-to-camel-case: true
#日志配置
logging:
  level:
    com.zking.zmall.mapper: debug

Step 5: Join on Startup Class@EnableDiscoveryClient

Step 6: Import the shopping cart page and common/head.html into the templates directory, and modify the ctx local variable in head.html

<#assign ctx>
    <#--一级域名,动态请求时需加入该前缀-->
    http://cart.zmall.com
</#assign>
<#--采用H5方式的base标签,在整个页面的url地址前加入,用于访问nginx中的静态资源-->
<base href="http://images.zmall.com/"/>

Step 7: Configure the routing and forwarding rules of the shopping cart in the zmall-gateway gateway service (restart the gateway gateway service)

spring:
  application:
    name: zmall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        ...
        - id: cart_route
          uri: lb://zmall-cart # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          predicates:
            - Path=/cart-serv/**
          filters:
            - StripPrefix=1
            #此过滤器设置路由过滤器检查的请求属性,以确定是否应发送原始主机头,而不是由 HTTP 客户端确定的主机头
            - PreserveHostHeader

 Note: Here you need to configure the filter PreserveHostHeader, which is used to send requests with the original host header when processing redirection.

Step 8: Create CartController and define request method

@Controller
public class CartController {

    @RequestMapping("/cart.html")
    public String toCart(){
        return "buyCar";
    }

    @RequestMapping("/addCart")
    public String addCart(Integer pid,Integer num){
        return "redirect:/cart.html";
    }
}

Note: The redirect redirection method is used here to jump to the page. During the routing and forwarding process of Spring Cloud gateway, the domain name jump will be changed to an http request method, so relevant configuration must be performed in the Gateway gateway service. For details, please refer to the gateway gateway routing configuration in step 8

Step 9: Modify the request method of adding to the shopping cart in the zmall-product module, and direct to the shopping cart

<td><a href="http://cart.zmall.com/addCart?pid=${(product.id)!}&num=3" class="b_sure">去购物车结算</a><a href="#" class="b_buy">继续购物</a></td>

Create and configure zmall-order order module

Step 1: Create zmall-order order module based on Spring initializr

Step 2: Configure the zmall-order order module into the main module

<modules>
    ...
    <module>zmall-order</module>
    ...
</modules>

Step 3: Modify pom.xml

<parent>
    <groupId>com.zking.zmall</groupId>
    <artifactId>zmall</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>
<artifactId>zmall-order</artifactId>

<dependencies>
    <dependency>
        <groupId>com.zking.zmall</groupId>
        <artifactId>zmall-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

Step 4: Configure application.yml (port: 8040)

server:
  port: 8040
spring:
  application:
    name: zmall-order
  datasource:
    #type连接池类型 DBCP,C3P0,Hikari,Druid,默认为Hikari
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/zmall?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
    username: root
    密码: 1234
  freemarker:
    suffix: .html
    template-loader-path: classpath:/templates/
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
#mybatis-plus配置
mybatis-plus:
  #所对应的 XML 文件位置
  mapper-locations: classpath*:/mapper/*Mapper.xml
  #别名包扫描路径
  type-aliases-package: com.zking.zmall.model
  configuration:
    #驼峰命名规则
    map-underscore-to-camel-case: true
#日志配置
logging:
  level:
    com.zking.zmall.mapper: debug

Step 5: On the startup class join @EnableDiscoveryClientand@MapperScan({"com.zking.zmall.mapper"})

Step 6: Define the order interface, which can be copied directly from the public module zmall-common

Step 7: Create OrderController and define request interface

@Controller
public class OrderController {
    @Autowired
    private IOrderService orderService;

    @RequestMapping("/orderUserList")
    @ResponseBody
    public List<Order> orderUserList(){
        return orderService.list(new QueryWrapper<Order>()
                .eq("userId",18));
    }
}

Step 8: Configure the routing and forwarding rules of the shopping cart in the zmall-gateway gateway service (restart the gateway gateway service)  

spring:
  application:
    name: zmall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        ...
        - id: order_route
          uri: lb://zmall-order # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
          predicates:
            - Path=/order-serv/**
          filters:
            - StripPrefix=1
            - PreserveHostHeader

service call

Access the order service interface through openfeign in zmall-user

Define the openfeign interface

@FeignClient("zmall-order")
public interface IOrderFeignService {

    @RequestMapping("/orderUserList")
    List<Order> orderUserList();
}
  • Start class settings @EnableDiscoveryClientand@EnableFeignClients

  • Call the interface and test the interface

@Controller
public class UserController {

    @Autowired
    private IOrderFeignService orderFeignService;

    @RequestMapping("/login.html")
    public String toLogin(){
        return "login";
    }

    @RequestMapping("/order.html")
    @ResponseBody
    public List<Order> orderUserList(){
        return orderFeignService.orderUserList();
    }
}

test link

http://product.zmall.com/index.html
http://product.zmall.com/product.html?pid=733
http://cart.zmall.com/cart.html

The interface can jump directly from the commodity microservice to the shopping cart microservice

 

 ​​

  Access address: http://localhost:8010/order.html

 Call the user microservice interface to access the data of the order microservice

 Four, spring session actual combat

What is Spring Session

SpringBoot's automatic configuration of Spring-Session integration can be described as out-of-the-box, extremely concise and convenient. This article introduces SpringBoot's integration of Spring-Session. Here we only introduce the actual combat based on RedisSession.

Spring Session is a sub-project of the Spring family. Spring Session provides APIs and implementations for managing user session information. It replaces the httpSession implemented by the servlet container with spring-session, focusing on solving session management problems. The default session information is stored in Redis, which can be easily, quickly and seamlessly integrated into our applications

Spring session official website address: Spring Session

Features of Spring Session:

  • Provide API and implementation of user session management

  • Provide HttpSession to replace the session of the web container in a neutral way, such as the session in tomcat

  • Support cluster session processing, without binding to a specific web container to solve the session sharing problem under the cluster

Why use Spring Session

 

 SpringCloud microservice disassembles a complete monolithic application into independent sub-services, and each independent micro-service sub-module will be deployed to a different server, and services are independently isolated from each other. At this time, to implement session session sharing between services, you need to use the spring-session framework to solve the problem of distributed session management and sharing.

Configure spring-session

Introduce the pom configuration of spring-session in the public module zmall-common. Since spring-boot includes the starter module of spring-session, the pom depends on: Note: the public module is supported as a dependency of all microservice submodules. If it is not in each service Configuring redis support in the module will cause errors when starting other microservices.

<!--redis-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring session-->
<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-data-redis</artifactId>
</dependency>
<!--commons-pool2-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

Configure application.yml in product service zmall-product and user service zmall-user respectively

spring:
  session:
    redis:
      flush-mode: on_save
      namespace: session.zmall
      cleanup-cron: 0 * * * * *
    store-type: redis
    timeout: 1800
  redis:
    host: localhost
    port: 6379
    password: 123456
    jedis:
      pool:
        max-active: 100
        max-wait: 10
        max-idle: 10
        min-idle: 10
    database: 0

Restart zmall-user and zmall-product services, first visit: http://zmall.com/user-serv/login.html , then visit: http://zmall.com/product-serv/index.html ; Go back to the zmall-product module console to check the session acquisition.

Note: It can be accessed internally with the help of the gateway microservice, but cannot be accessed between different second-level domain names

Five, the second-level domain name problem

The test saves user information in the user module, and then reads it in the product module, but the access and reading fails using the second-level domain name

 

 Please configure this class in user service and commodity service respectively to solve the problem of invalid access session of the second-level domain name.

@Configuration
public class SessionConfig {
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("zmall.com");
        cookieSerializer.setCookieName("ZMALLSESSION");
        return cookieSerializer;
    }
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer(){
        return new GenericJackson2JsonRedisSerializer();
    }
}

test link

#1. First visit
http://user.zmall.com/login.html
#2. Then visit
http://product.zmall.com/index.html

user login 

Step 1: Create global exception handling and response encapsulation classes in the zmall-common public module

Step 2: Define IUserService and UserServiceImpl in the zmall-user module

IUserService

public interface IUserService extends IService<User> {
    JsonResponseBody<?> userLogin(UserVo user, HttpServletRequest req, HttpServletResponse resp);
}

UserServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Override
    public JsonResponseBody<?> userLogin(UserVo user,
                                         HttpServletRequest req,
                                         HttpServletResponse resp) {
        //1.判断用户账号和密码是否为空
        if(StringUtils.isEmpty(user.getLoginName())||
                StringUtils.isEmpty(user.getPassword()))
            return new JsonResponseBody<>(JsonResponseStatus.USERNAME_OR_PWD_EMPTY);
        //2.根据用户名查询数据对应的用户信息
        User us = this.getOne(new QueryWrapper<User>()
                .eq("loginName", user.getLoginName()));
        //3.判断us用户对象是否为空
        if(null==us)
            return new JsonResponseBody<>(JsonResponseStatus.USERNAME_ERROR);
        try {
            //MD5加密转换处理
            String pwd=MD5Utils.md5Hex(user.getPassword().getBytes());
            //4.判断输入密码与数据库表存储密码是否一致
            if(!us.getPassword().equals(pwd)){
                return new JsonResponseBody<>(JsonResponseStatus.PASSWORD_ERROR);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResponseBody<>(JsonResponseStatus.ERROR);
        }
        //5.通过UUID生成token令牌并保存到cookie中
        String token= UUID.randomUUID().toString().replace("-","");
        //将随机生成的Token令牌保存到Cookie中,并设置1800秒超时时间
        CookieUtils.setCookie(req,resp,"token",token,7200);
        //6.将token令牌与spring session进行绑定并存入redis中
        HttpSession session = req.getSession();
        session.setAttribute(token,us);
        return new JsonResponseBody<>(token);
    }
}

Step 3: Create UserVo class

@Data
public class UserVo {
    private String loginName;
    private String password;
}

Step 4: Define User Login Method in UserController

/**
* 用户登陆功能实现
* @return
*/
@RequestMapping("/userLogin")
@ResponseBody
public JsonResponseBody<?> userLogin(UserVo user,
    HttpServletRequest req,
    HttpServletResponse resp){
    return userService.userLogin(user,req,resp);
}

Step 5: Define the login js method in the front-end login.html page

<script>
    $(function(){
        $('.log_btn').click(function(){
            let loginName=$('.l_user').val();
            let password=$('.l_pwd').val();

            if(''===loginName){
                alert('请输入用户名!');
                return false;
            }
            if(''===password){
                alert('请输入密码!');
                return false;
            }
            console.log({
                loginName:loginName,
                password:password
            });
            $.post('http://zmall.com/user-serv/userLogin',{
                loginName:loginName,
                password:password
            },function(rs){
                console.log(rs);
                if(rs.code===200){
                    location.href='http://zmall.com/product-serv/index.html';
                }else{
                    alert(rs.msg);
                }
            },'json');
        });
    });
</script>

After successful login, jump to the product home page

http://zmall.com/user-serv/login.html

If a second-level domain name is used for testing, then cross-domain issues need to be resolved;

url: jdbc:mysql://localhost:3306/zmall?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC

Guess you like

Origin blog.csdn.net/weixin_66202611/article/details/128992932