微服务迁移记(五):WEB层搭建(1)
WEB层是最终表现层,注册至注册中心,引用接口层(不需要引用实现层)、公共服务层。用户登录使用SpringSecurity,Session保存在redis中,权限管理没有用SpringSecurity那套,自己写了一个简单的菜单、按钮权限控制。我在虚拟机192.168.0.7中搭了一个redis服务。
一、redis搭建
下载redis后,在linux下启动比较简单。需要注意的是redis.config配置:
1. 如果想配置用户名密码
1 | requirepass 123456 |
2. 如果不bind IP地址,默认只能本机访问
1 | bind 192.168 . 0.7 |
写一个批处理startredis.sh,启动redis
1 | ./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集成
待续
六、权限管理
待续
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述