• 微服务迁移记(五):WEB层搭建(1)


    WEB层是最终表现层,注册至注册中心,引用接口层(不需要引用实现层)、公共服务层。用户登录使用SpringSecurity,Session保存在redis中,权限管理没有用SpringSecurity那套,自己写了一个简单的菜单、按钮权限控制。我在虚拟机192.168.0.7中搭了一个redis服务。

    一、redis搭建

    下载redis后,在linux下启动比较简单。需要注意的是redis.config配置:

    1. 如果想配置用户名密码

     requirepass 123456

    2. 如果不bind IP地址,默认只能本机访问

    bind 192.168.0.7

    写一个批处理startredis.sh,启动redis

    ./redis-5.0.7/src/redis-server ./redis-5.0.7/redis.conf

    二、WEB层主要依赖包

     <!--依赖系统管理相关接口工程,供Feign调用,减少冗余代码-->
            <dependency>
                <groupId>com.zyproject</groupId>
                <artifactId>zyproject-api-service-system</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    <!-- 公共类工程-->
            <dependency>
                <groupId>com.zyproject</groupId>
                <artifactId>zyproject-common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    <!-- redis,需要注意的是引入commons-pool2,否则会报错 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
                <version>2.2.0.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
            </dependency>
    <!--引入feign,远程调用Service服务-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>2.2.1.RELEASE</version>
            </dependency>
            <!--整合freemarker-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
            <!--依赖系统管理相关接口工程-->
            <dependency>
                <groupId>com.zyproject</groupId>
                <artifactId>zyproject-api-service-system</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <!--spring secrity-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-oauth2</artifactId>
                <version>2.1.4.RELEASE</version>
            </dependency>

    三、FeignClient通用接口

    创建一个接口,继承自接口层ISystemService,这样就可以直接使用Feign实现RPC调用接口实现层暴露出来的http服务了。

    package com.zyproject.web.feignclient;
    
    import com.zyproject.service.ISystemService;
    import org.springframework.cloud.openfeign.FeignClient;
    
    /**
     * @program: zyproject
     * @description: RPC调用系统管理相关接口服务
     * @author: zhouyu(zhouyu629 # qq.com)
     * @create: 2020-02-11
     **/
    @FeignClient("zyproject-api-service-system") //注意这里,对应的是接口实现层在注册中心的别名。我这个别名取的有点问题,跟接口层不一样,不合适。
    public interface SystemFeign extends ISystemService {
    
    }

    然后建立一个Service包,里面调用这个Feign接口,最后Controller调用Service即可。以UserService为例:

    package com.zyproject.web.service;
    
    import com.zyproject.common.ResponseData;
    import com.zyproject.web.feignclient.SystemFeign;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.bind.annotation.RequestParam;
    
    /**
     * @program: zyproject
     * @description: 用户服务
     * @author: zhouyu(zhouyu629 # qq.com)
     * @create: 2020-02-11
     **/
    @Service
    public class UserService {
        @Autowired
        private SystemFeign systemFeign;
    
        //用户登录
        public ResponseData userLogin(@RequestParam String user_code, @RequestParam String password){
            return systemFeign.userLogin(user_code,password);
        }
    
        //根据登录名,获取用户信息
        public ResponseData findByLoginname(String login_name){
            return systemFeign.findByLoginname(login_name);
        }
    }

    有个细节需要注意:

    Feign直接调用接口实现RPC,这使得远程调用简单了很多,传递参数可以是一些Java类型,比如传Entity、List、Map等对象。最终底层应该是HttpClient,默认会报错,但可以解决。

    但从实际应用角度出发,不建议这样做,向外暴露的http接口,理论上也可以提供给其他应用程序使用,其他开发语言调用,不能限制死是java类型,建议是通过gson或fastjson,将这些类型转换为json字符串进行http参数传递,实现侧再转换回java类型。下面是一个例子:

    客户端请求:

     /**
         * 设置角色权限
         * @param role_id
         * @param tree_ids:考虑到对其他语言的兼容性,不建议传java类型
         * @param btn_ids:考虑到对其他语言的兼容性,不建议传java类型
         * @return
         */
        public ResponseData setRoleRight(@RequestParam int role_id,
                                         @RequestParam(name = "tree_ids",required = true) String  tree_ids,
                                         @RequestParam(name = "btn_ids",required = true) String btn_ids){
            return systemFeign.setRoleRight(role_id,tree_ids,btn_ids);
        }
    
        /**
         * 新增或编辑角色
         * @param roleEntity:角色信息,Feign前转换为json字符串
         * @return
         */
        public ResponseData addOrUpdateRole(RoleEntity roleEntity){
            String role = new Gson().toJson(roleEntity);
            return this.systemFeign.addOrUpdateRole(role);
        }

    服务端接收(类型转换,应该做容错判断,代码里没有做):

     @PostMapping("/setRoleRight")
        @ApiOperation("设置角色权限")
        @ApiImplicitParams({
                @ApiImplicitParam(name = "role_id",value = "角色ID",dataType = "int"),
                @ApiImplicitParam(name = "tree_ids", value = "选中的菜单",dataType = "String"),
                @ApiImplicitParam(name = "btni_ds",value = "选中的按钮",dataType = "String")
        })
        @Override
        @Transactional
        public ResponseData setRoleRight(int role_id, String tree_ids,String btn_ids) {
            Gson gson = new Gson();
            List<String> tree = gson.fromJson(tree_ids,new TypeToken<List<String>>(){}.getType());
            List<Map<String,String>> btn = gson.fromJson(btn_ids,new TypeToken<List<Map<String,String>>>(){}.getType());
            boolean result = this.roleDao.setRoleRight(role_id,tree,btn);
            return ResponseData.out(result?CodeEnum.SUCCESS:CodeEnum.FAIL,null);
        }
    
        @GetMapping("/addOrUpdateRole")
        @ApiOperation("新增或修改角色")
        @ApiImplicitParams(
                @ApiImplicitParam(name = "role",value = "角色实体json字符串")
        )
        @Override
        public ResponseData addOrUpdateRole(String role) {
            //将role转换为实体类
            boolean result = this.roleDao.addOrUpdateRole(new Gson().fromJson(role,RoleEntity.class));
            return ResponseData.out(result?CodeEnum.SUCCESS:CodeEnum.FAIL,null);
        }

    四、SpringSecurity集成

    待续

    五、FreeMarker集成

    待续

    六、权限管理

    待续

  • 相关阅读:
    go cobra Error: required flag(s) "pkg-name" not set
    Linux 防火墙及开放端口管理
    第二十九节 jQuery之新建节点操作
    Why is one loop so much slower than two loops?
    Why in the code “456”+1, output is “56”
    I want to learn Android Development, where do I start?
    UIColor
    UITextField
    UITableViewController
    NSString 字符串
  • 原文地址:https://www.cnblogs.com/zhouyu629/p/12340961.html
Copyright © 2020-2023  润新知