微博超话自动签到程序
与世界交手的这二十几年来,我没追过星,专业领域里的偶像倒是有几个,但都不是歌手或演员,这次看浪姐3是粉上于文文了,直给的酷酷的性格,再深扒她在音乐领域也很能打,烟嗓配摇滚开嗓即巅峰哈哈哈哈。后面基本天天泡在三文鱼超话里面,有一天是看到一个文文粉丝挂了一个微博自动签到的程序。
这不巧了吗,同行啊,正好看看学习下这个签到程序,里面用到的是java的SpringBoot框架,web程序的框架正好我也不熟悉,借着追星还可以学代码🤩
代码走读
AutoCheckInApplication.java 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| package com.didi.autocheckin;
import com.alibaba.fastjson.JSONObject; import com.didi.autocheckin.config.WbConfig; import com.didi.autocheckin.portConfig.StartCommand; import lombok.extern.slf4j.Slf4j; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.io.IOException; import java.util.List;
@SpringBootApplication @Slf4j public class AutoCheckInApplication {
@Resource private WbConfig wbConfig;
public static void main(String[] args) {
new StartCommand(args); # 检查可用端口 SpringApplication.run(AutoCheckInApplication.class, args); }
@Scheduled(cron = "0 0 0 * * ?") @PostConstruct public void auto(){ String cookie = wbConfig.getCookie(); List<String> pids = wbConfig.getPids();
pids.forEach(x->{ try { autoCheck(x,cookie); } catch (IOException e) { log.info(e.getMessage()); } }); }
public void autoCheck(String pid,String cookie) throws IOException { Integer scCode = 100000; log.info("开始自动签到{}",pid); OkHttpClient client = new OkHttpClient().newBuilder() .build();
MediaType mediaType = MediaType.parse("text/plain");
Request request = new Request.Builder() .url("https://weibo.com/p/aj/general/button?api=http://i.huati.weibo.com/aj/super/checkin&id="+pid) .addHeader("cookie", cookie) .build();
Response response = client.newCall(request).execute();
String data = response.body().string(); JSONObject dataJsonObject = JSONObject.parseObject(data); Integer code = dataJsonObject.getInteger("code");
if (code.equals(scCode)) { log.info("签到成功"); }else { log.info(dataJsonObject.getString("msg")); } log.info("结束"); } }
|
这个类主要是看几个注解:
@SpringBootApplication,可以看到这个启动类AutoCheckInApplication
最上面标的就是@SpringBootApplication注解,mian方法里调用run方法。这里. run方法的作用如下:
SpringApplication.run()一共做了两件事
1.创建SpringApplication对象;在对象初始化时保存事件监听器,容器初始化类. 以及判断是否为web应用,保存包含main方法的主配置类。
2.调用run方法;准备spring的上下文,完成容器的初始化,创建,加载等。会在不同的时机触发监听器的不同事件。
@PostConstruct是java5的时候引入的注解,指的是在项目启动的时候执行这个方法,也可以理解为在spring容器启动的时候执行,可作为一些数据的常规化加载,比如数据字典之类的。
被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行
WbConfig.java 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.didi.autocheckin.config;
import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.List;
@Data @Component @ConfigurationProperties(prefix = "wb") public class WbConfig { @Value("${wb.cookie}") private String cookie;
@Value("${wb.pid}") private List<String> pids;
}
|
- @Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。
补充:**@controller: controller控制器层(注入服务)**
@service : service服务层(注入dao)
@repository : dao持久层(实现dao访问)
application.yml 配置文件内容:
1 2 3 4 5 6 7
| server: port: ${auto.port}
wb: cookie: pid: 100808445c68f22a32b95efe6c3d025512d13c,1008089f1260fce8d1d56c76d01541995b2d5c
|
StartCommand.java类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| package com.didi.autocheckin.portConfig; import com.didi.autocheckin.util.ServerPortUtil; import org.springframework.util.StringUtils;
public class StartCommand {
private static final String SERVER_PORT = "auto.port";
public StartCommand(String[] args) { boolean isServerPort = false; String serverPort = ""; if (args != null) { for (String arg : args) { if (StringUtils.hasText(arg) && arg.startsWith("--server.port" )) { isServerPort = true; serverPort = arg; break; } } }
String port; if (isServerPort) { port = serverPort.split("=")[1]; } else { port = ServerPortUtil.getAvailablePort(); } System.out.println("Current project port is " + port); System.setProperty(SERVER_PORT, port); } }
|
ServerPortUtil.java类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package com.didi.autocheckin.util;
import java.net.InetAddress; import java.net.Socket; import java.util.Random;
public class ServerPortUtil {
private static final int MAX_PORT = 65535; private static final int MIN_PORT = 8000;
public static String getAvailablePort() { Random random = new Random(); int maxRetryCount = MAX_PORT - MIN_PORT; while (maxRetryCount > 0) { int port = random.nextInt(MAX_PORT - MIN_PORT) + MIN_PORT; boolean isUsed = isLocalePortUsing(port); if (!isUsed) { return String.valueOf(port); } --maxRetryCount; } System.out.println("系统暂无端口可用,运行结束"); System.exit(1); return null; }
public static boolean isLocalePortUsing(int port) { try { new Socket(InetAddress.getByName("127.0.0.1"), port); return true; } catch (Exception e) { } return false; } }
|
总结
这个签到程序,第一遍看完os:哇好混乱,这是什么注解啊!!那是什么意思啊
看第二遍os:我画画它的流程图看看。看第三遍os:好像就是两步,先检查可用port,然后设置一个定时签到任务。哈哈哈哈哈,看不懂就多看几遍就好了。
参考链接: