0
点赞
收藏
分享

微信扫一扫

Flutter Ping 检查服务器通讯信号强度

山竹山竹px 2023-06-27 阅读 116
后端

目录

创建小程序底部Tab导航

开通腾讯云对象存储服务

一、静态资源要放在网上

二、为什么不选择阿里云或者华为云的对象存储服务?

二、开通腾讯云对象存储服务

三、存储静态资源

设计首页的英雄区和栏目导航

设计人脸签到页面

实现签到自拍功能

缓存系统常量数据

一、Emos系统的常量数据

二、读取常量数据

封装检测当天是否可以签到(持久层)

一、为什么要检测是否可以签到?

二、封装持久层代码

封装检测当天是否可以签到(业务层) 

封装检测当天是否可以签到(Web层)

实现Shiro认证功能

一、认证与授权执行流程

二、查询用户信息

二、实现认证方法

实现Shiro 授权功能

一、实现授权方法

二、添加权限验证注解


创建小程序底部Tab导航

        ……

开通腾讯云对象存储服务

一、静态资源要放在网上

        微信小程序打包发布有体积限制,不能超过2M,分包加载最多不能超过8M。正因为小程序有体积限制,所以我们不能往小程序项目中放置太多的静态资源,比如体积超大的图片。我们应该尽可能的把静态资源放在网上,然后在小程序页面上引用这些静态资源。 

        网上有很多图床可以使用,这里我选择腾讯云的对象存储服务当做图床。腾讯云的对象存储服务可以免费试用6个月,并且为个人提供50GB的免费空间。即便试用结束,腾讯云的对象存储价格也不贵。10G资源包,1个月的价格仅仅0.85元。对于普通的开发者来说,10G的存储空间足够了。

二、为什么不选择阿里云或者华为云的对象存储服务?

        华为云的服务器大部分是ARM架构的,对很多Linux程序包的兼容性不好,导致我们无法正 常部署和运行程序,所以你在选择华为云的时候一定要慎重,先了解清楚,别盲目上车。

        阿里云的问题是超售严重,假设1台硬件服务器能运行200个虚拟云主机,但是阿里偏偏一 台主机跑2000个虚拟云主机,最大程度榨取硬件主机的商业价值。当硬件服务器中运行的 云主机过多,最先体现出来的是硬盘IO能力的下降。因为硬盘IO本来就比内存IO慢很多, 加之云主机共享使用硬盘IO,这就导致某个云主机分得的硬盘IO速度非常有限。

        比方说, 你在阿里云主机上面安装MySQL数据库,执行一个非常简单的SQL语句,都要登上7~10秒 钟才能获得结果,这种超慢的读写速度真让人抓狂。也许有人想说,干嘛在云主机上面安 装MySQL,直接购买数据库服务不就行了么?还真不行,运营商提供的数据库服务,最多 带了主从同步这种数据弱一致的集群方案,你想要数据强一致性的数据库集群,只能在云 主机里面自己安装。因此不是购买运营商的数据库服务就一了百了的。

        腾讯云的超售不严重,每个云主机的IO性能跟本地主机差不多。我在腾讯云主机上面安装MySQL数据库,执行SQL语句,几十毫秒就得到了结果,几乎跟本地执行SQL是同样的速度,所以我们单位 的所有产品都是部署在腾讯云上面。 

二、开通腾讯云对象存储服务

        用浏览器访问腾讯云对象存储服务的主页,根据提示开通服务即可,非常的简单。

三、存储静态资源

        首先我们要创建一个存储桶,然后才能上传静态文件。 

        有了存储桶之后,我们就可以上传各种静态文件了,比如说我们要做轮播焦点图,那么就可以把这些图片预先上传到腾讯云上面。

设计首页的英雄区和栏目导航

        ……

设计人脸签到页面

        ……

实现签到自拍功能

        ……

缓存系统常量数据

        编写SpringBoot初始化方法(SpringBoot项目启动之后,自动执行的方法)。和Java基础里面的静态语句块非常的类似。没错,静态语句块也能实现项目的初始化,但是,静态语句块没法接受SpringBoot项目注入的各种关系,还有一些值。所以我们选择SpringBoot的初始化方法,可以正常接收到 注入的各种关系,引用,值注入。

@PostConstruct
init()

一、Emos系统的常量数据

        在 sys_config 数据表中保存了Emos系统的常量配置信息,其中就包括了考勤部分的常量信息。例如每天上班考勤从几点开始,截止到几点。下班考勤从几点开始,几点结束。 

 

        因为这些常量信息跟考勤模块息息相关,所以我们要编写Java代码,在SpringBoot项目启动的时候,就去数据库读取这些常量信息,然后缓存成Java对象,全局都可以使用。

二、读取常量数据

在 SysConfigDao.xml 文件中声明查询语句 

<select id="selectAllParam" resultType="com.example.emos.wx.db.pojo.SysConfig"> 
    SELECT param_key, param_value FROM sys_config WHERE status = 1;
</select>

在 SysConfigDao.java 中声明抽象方法 

@Mapper
public interface SysConfigDao { 
    public List<SysConfig> selectAllParam();
} 

在 com.example.emos.wx.config 中创建 SystemConstants.java 常量封装类

@Data
@Component
public class SystemConstants { 
    public String attendanceStartTime; 
    public String attendanceTime;
    public String attendanceEndTime; 
    public String closingStartTime; 
    public String closingTime; 
    public String closingEndTime;
}

在 EmosWxApiApplication.java 文件中创建 init() 方法,读取常量数据并缓存

@SpringBootApplication
@ServletComponentScan
@Slf4j
public class EmosWxApiApplication { 

    @Autowired
    private SysConfigDao sysConfigDao; 

    @Autowired
    private SystemConstants constants; 

    public static void main(String[] args) {
        SpringApplication.run(EmosWxApiApplication.class, args);
    }

    @PostConstruct
    public void init() {
        List<SysConfig> list = sysConfigDao.selectAllParam();
        list.forEach(one -> {
            String key = one.getParamKey();
            key = StrUtil.toCamelCase(key);
            String value = one.getParamValue();
            try {
                Field field = constants.getClass().getDeclaredField(key);
                field.set(constants, value);
            } catch (Exception e) {
                log.error("执行异常", e);
            }
        });
    }
}

封装检测当天是否可以签到(持久层)

一、为什么要检测是否可以签到?

        上节课我们通过分装Emos系统常量信息,从而得知考勤是分为起止时间的。在考勤开始之前,用户是不能考勤签到的。同理,在当天考勤结束之后,用户也是不能考勤签到的。甚至节假日也不能考勤,只有正常的工作日才能考勤签到。 

怎么判断当天是工作日还是节假日? 

在数据库中有 tb_workday 和 tb_holidays 两张数据表,记录着哪天是工作日,哪天是休息日。 

        Emos系统默认周一至周五为工作日,周六周日为休息日。但是这两张表不是把所有的工作日和休息日都记录下来,只是记录比特殊的工作日或者休息日。比如说今年的中秋节赶上了礼拜四,于是就把周五和周六设置成休息日,跟中秋节连成三连休,然后周日正常上班。这种特殊情况我们就要记录下来。在 tb_workday 记录周日是工作日,在 tb_holidays 表中记录周五那天是休息日。这样Emos系统在中秋三连休期间不会执行考勤签到。

二、封装持久层代码

查询特殊休息日 

在 TbHolidaysDao.xml 文件中,添加查询语句 

<select id="searchTodayIsHolidays" resultType="Integer"> 
    SELECT id FROM tb_holidays WHERE date=CURRENT_DATE LIMIT 1;
</select>

在 TbHolidaysDao.java 文件中,添加抽象方法 

@Mapper
public interface TbHolidaysDao { 
    public Integer searchTodayIsHolidays();
} 

查询特殊工作日 

在 TbWorkdayDao.xml 文件中,添加查询语句 

<select id="searchTodayIsWorkday" resultType="Integer"> 
    SELECT id FROM tb_workday WHERE date=CURRENT_DATE LIMIT 1;
</select>

在 TbWorkdayDao.java 文件中,添加抽象方法

@Mapper
public interface TbWorkdayDao { 
    public Integer searchTodayIsWorkday();
}

查询当天是否已经签到

        tb_checkin 表结构如下,Emos不仅要记录考勤的人员、时间,还要记录考勤人的地理坐标,然后根据疫情实时信息,判定用户所处的地区是新冠疫情的高危地区还是低风险地区。这部分功能,后续的章节我们再实现。 

 

在 TbCheckinDao.xml 文件中,添加查询语句

<select id="haveCheckin" parameterType="HashMap" resultType="Integer"> 
    SELECT id
    FROM tb_checkin
    WHERE user_id = #{userId} AND date = CURRENT_DATE
    AND create_time BETWEEN #{start} AND #{end}
    LIMIT 1;
</select>

在 TbCheckinDao.java 文件中,添加抽象方法 

@Mapper
public interface TbCheckinDao { 
    public Integer haveCheckin(HashMap param);
}

封装检测当天是否可以签到(业务层) 

        service类将来有发送邮件的功能,邮件发送比较耗时,所以想设计成异步的。线程的异步执行就需要把service类定义为多例的@Scope("prototype")。不可以是单例的,没办法走线程的异步执行。

        DateUtil是HuTool库里自带的工具类,库里的date()可以创建一个当前的日期对象。这个日期对象类型不是Date类型,是DateTime类型。DateTime是HuTool自定义的一个Java类,是Date的子类,但是增添了更多的实用方法。

在 com.example.emos.wx.service 包中,创建 CheckinService 接口

public interface CheckinService { 
    public String validCanCheckIn(int userId, String date);
} 

在 com.example.emos.wx.service.impl 包中,创建 CheckinServiceImpl 实现类

@Service
@Scope("prototype") 
@Slf4j
public class CheckinServiceImpl implements CheckinService { 

    @Autowired
    private SystemConstants systemConstants; 

    @Autowired
    private TbHolidaysDao holidaysDao; 

    @Autowired
    private TbWorkdayDao workdayDao;

    @Autowired
    private TbCheckinDao checkinDao;

    @Override
    public String validCanCheckIn(int userId, String date) {

        boolean bool_1 = holidaysDao.searchTodayIsHolidays() != null ? true : false;
        boolean bool_2 = workdayDao.searchTodayIsWorkday() != null ? true : false;
        String type = "工作日";
        if (DateUtil.date().isWeekend()) {
            type = "节假日";
        }

        if (bool_1) {
            type = "节假日";
        } else if (bool_2) {
            type = "工作日";
        }
        if (type.equals("节假日")) {
            return "节假日不需要考勤";
        } else {
            DateTime now = DateUtil.date();
            String start = DateUtil.today() + " " + systemConstants.attendanceStartTime;
            String end = DateUtil.today() + " " + systemConstants.attendanceEndTime;
            DateTime attendanceStart = DateUtil.parse(start);
            DateTime attendanceEnd = DateUtil.parse(end);
            if (now.isBefore(attendanceStart)) {
                return "没有到上班考勤开始时间";
            } else if (now.isAfter(attendanceEnd)) {
                return "超过了上班考勤结束时间";
            } else {
                HashMap map = new HashMap();
                map.put("userId", userId);
                map.put("date", date);
                map.put("start", start);
                map.put("end", end);
                boolean bool = checkinDao.haveCheckin(map) != null ? true : false;
                return bool ? "今日已经考勤,不用重复考勤" : "可以考勤";
            }
        }
    }
}

封装检测当天是否可以签到(Web层)

在 com.example.emos.wx.controller 包中,创建 CheckinController 类

@RequestMapping("/checkin")
@RestController
@Api("签到模块Web接口")
@Slf4j
public class CheckinController {
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private CheckinService checkinService;

    @GetMapping("/validCanCheckIn")
    @ApiOperation("查看用户今天是否可以签到")
    public R validCanCheckIn(@RequestHeader("token") String token) {
        int userId = jwtUtil.getUserId(token);
        String result = checkinService.validCanCheckIn(userId, DateUtil.today());
        return R.ok(result);
    }
}

实现Shiro认证功能

一、认证与授权执行流程

之前我们在配置Shiro+JWT的时候,Shiro的认证与授权的实现功能并没有完成。 

 

        现在Controller中的 validCanCheckIn() 方法,并不是Shiro放行请求的Web方法。所以发送给validCanCheckIn() 方法的请求一定会被Shiro拦截下来,先由 OAuth2Filter 检查请求头的Token是否合法。如果没问题,接下来就要由 OAuth2Realm 中的 doGetAuthenticationInfo() 方法来颁发认证对象。请求被赋予了认证对象,那么请求才会被发送到Web方法来执行。

二、查询用户信息

        因为在认证方法里面要返回认证对象,认证对象创建的时候要传入用户信息和令牌,传入 Realm 类的名字,所以我们这里就要查询用户信息,然后判断用现在是在职还是离职状态。如果是在职状态,那就可以创建认证对象,反之就抛出异常。 

编辑 TbUserDao.xml 文件,添加查询方法 

<select id="searchById" parameterType="int" resultType="com.example.emos.wx.db.pojo.TbUser"> 
    SELECT
    id, open_id, nickname, photo, name, sex, tel, role, root, dept_id, status, create_time
    FROM tb_user WHERE id=#{userId} AND status = 1
</select>

编辑 TbUserDao.java 接口,添加抽象方法 

public TbUser searchById(int userId);

编辑 UserService.java 接口,添加抽象方法

public TbUser searchById(int userId);

编辑 UserServiceImpl.java 类,实现抽象方法 

@Override
public TbUser searchById(int userId) { 
    TbUser user = userDao.searchById(userId);
    return user; 
}

二、实现认证方法

编辑 OAuth2Realm.java 文件,修改 doGetAuthenticationInfo() 方法

/**
 * 认证(登录时调用) 
 */

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
    String accessToken = (String) token.getPrincipal();
    int userId = jwtUtil.getUserId(accessToken);
    //查询用户信息
    TbUser user = userService.searchById(userId);
    if(user==null){
        throw new LockedAccountException("账号已被锁定,请联系管理员");
    }
    SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user, accessToken, getName());
    return info;
}

实现Shiro 授权功能

        认证功能和JWT绑定在一起。只要OAuth2Filter过滤器认定客户端提交的令牌没有问题,就可以看作用户成功登录。Shiro颁发认证对象,HTTP请求才可以继续往下传递。授权和RBAC权限模型相关。

        认证对象封装了用户信息,所以授权方法中可以得到用户信息。

一、实现授权方法

        Shiro每次验证权限之前,都要执行授权方法,把用户具有的权限封装成权限对象,然后放行请求。接下来Web方法的 @RequiresPermissions 注解,会从权限对象中提取权限数据,跟要求的权限作比较。如果用户具有该Web方法要求的权限,那么Web方法就会正常执行。反之则返回异常消息。 

修改 OAuth2Realm.java 中的 doGetAuthorizationInfo() 授权方法。 

/**
 * 授权(验证权限时调用) 
 */

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection collection) { 
    TbUser user = (TbUser) collection.getPrimaryPrincipal();
    int userId = user.getId();
    //用户权限列表
    Set<String> permsSet = userService.searchUserPermissions(userId);
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.setStringPermissions(permsSet);
    return info;
}

二、添加权限验证注解

        我们创建Web方法的时候,如果希望只有满足相关权限的用户才能调用这个Web方法,我们只需要给Web方法添加上 @RequiresPermissions 注解即可。

@PostMapping("/addUser") 
@ApiOperation("添加用户") 
@RequiresPermissions(value = {"ROOT", "USER:ADD"}, logical = Logical.OR) 
public R addUser() { 
    return R.ok("用户添加成功");
}
举报

相关推荐

0 条评论