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

阅读 116

2023-06-27

目录

创建小程序底部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)

0 0 举报