0%

早就想做个自动签到脚本了,最近有空,就研究了一下

这里使用了curl:

cURL is a computer software project providing a library and command-line tool for transferring data using various network protocols. The name stands for "Client URL".

自动签到无非就两步:1.登录 2.签到 3.自动化

而签到需要用到登录后服务器提供的cookie,所以在登录后要先把cookie存起来,即存在一个文件里

一.登录

1
curl --cookie-jar cookies -d "email=myemail&passwd=mypassword" https://xxx.xxx/signin && echo

&& echo在这里的作用只是为了换行


1
2
3
4
Syntax:
command1 && command2

command2 will execute if command1 has executed successfully. This operator allows us to check the exit status of command1.

用到的curl命令参数:

参数 作用
-c filename
--cookie-jar file name 【参考】
(HTTP)完成操作后将服务器返回的cookies保存到指定的文件; 指定参数值为“-”将定向到标准输出“如控制台”;
-d -d参数用于发送 POST 请求的数据体。
使用-d参数以后,HTTP 请求会自动加上标头Content-Type : application/x-www-form-urlencoded。并且会自动将请求转为 POST 方法,因此可以省略-X POST

二.签到

1
curl --cookie cookies  -H 'content-length: 0' -X POST https://xxx.xxx/user/checkin

用到的curl命令参数:

参数 作用
-b name=data --cookie name=data 【参考】 (HTTP)发送cookie数据到HTTP服务器,数据格式为:"NAME1=VALUE1; NAME2=VALUE2"; 如果行中没有“=”,将把参数值当作cookie文件名; 这个cookie数据可以是由服务器的http响应头“Set-Cookie:”行发送过来的;

注:这里其实有个问题,那就是为什么要加上 -H 'content-length: 0'

By default, POST requests require a Content-Length header, or they result in a 411 error. The error occurs even if the POST request doesn’t contain a body and theoretically shouldn’t require Content-Length header

三.自动化

首先先编写自己的脚本,命名为mycheckin.sh

1
2
3
4
#!/bin/bash
curl --cookie-jar cookies -d "email=myemail&passwd=mypassword" https://xxx.xxx/signin && echo

curl --cookie cookies -H 'content-length: 0' -X POST https://xxx.xxx/user/checkin && echo

用crontab -e进入编辑

1
0 1 * * *  /var/spool/cron/mycheckin.sh >>  /var/spool/cron/checkin.log

每天一点的时候执行一次签到,并且返回的信息会记录在checkin.log中

参考:

https://www.geeksforgeeks.org/difference-between-chaining-operators-in-linux/#:~:text=Logical%20AND%20operator(%26%26)%3A,commands%20in%20the%20command%20line.

https://www.runoob.com/linux/linux-shell-echo.html

http://aiezu.com/article/linux_curl_command.html

https://serverfault.com/questions/315849/curl-post-411-length-required

https://salesforce.stackexchange.com/questions/76662/post-requires-content-length-error-occur-when-i-am-trying-to-call-custom-rest

https://stackoverflow.com/questions/33492178/how-to-pass-content-length-value-in-header-using-curl-command

https://techdocs.akamai.com/property-mgr/docs/allow-post

https://help.salesforce.com/s/articleView?id=000337925&type=1

https://www.runoob.com/w3cnote/linux-crontab-tasks.html

https://importcjj.github.io/jian-dan-de-acfunzi-dong-qian-dao.html

一、原码

用第一位表示符号, 其余位表示值

比如如果是8位二进制:

1
2
3
[+1]原 = 0000 0001

[-1]原 = 1000 0001

二、反码

反码的表示方法是:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

1
2
3
[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

三、补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

1
2
3
[+1] = [00000001]原 = [00000001]反 = [00000001]补

[-1] = [10000001]原 = [11111110]反 = [11111111]补

参考:https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/computercode.html

泛型用来编写工具类十分方便

​ 今天,又一次用泛型来编写工具类,通过传入一个request和一个泛型类,返回json表示的指定的类

​ 整个过程:

​ request-->获得json-->获得json表示的指定的对象

这里objectMapper.readValue(json, t.getClass());返回的是Object,很烦,本来以为java可以直接返回T的。

但是这个时候IDEA提示可以强转为T,惊喜。

强转之后,代码如下:

1
2
3
4
public static <T> T getRequestObject(HttpServletRequest req,T t ) throws JsonProcessingException {
String json = ToReadJson.readJSONData(req);
return (T) objectMapper.readValue(json, t.getClass());
}

这也是第一次知道,还能用泛型强转。

一.拦截器和过滤器的区别:

1.拦截器是基于java的反射机制的,而过滤器是基于函数回调。
2.拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5.在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6.拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

二.触发时机

1.过滤器和拦截器触发时机不一样:

过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。

总结:过滤器包裹住servlet,servlet包裹住拦截器。

如图:

2.过滤器的触发时机是容器后,servlet之前.

所以过滤器的doFilter(

ServletRequest request, ServletResponse response, FilterChain chain

)的入参是ServletRequest ,而不是httpservletrequest。因为过滤器是在httpservlet之前。

1
2
3
4
5
6
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("before...");
chain.doFilter(request, response);
System.out.println("after...");
}chain.doFilter(request, response);这个方法的调用作为分水岭。事实上调用Servlet的doService()方法是在chain.doFilter(request, response);这个方法中进行的。
3.拦截器是被包裹在过滤器之中的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}

a.preHandle()这个方法是在过滤器的chain.doFilter(request, response)方法的前一步执行,也就是在 [System.out.println("before...")] [chain.doFilter(request, response)]之间执行。

b.preHandle()方法之后,在return ModelAndView之前进行,可以操控Controller的ModelAndView内容。

c.afterCompletion()方法是在过滤器返回给前端前一步执行,也就是在[chain.doFilter(request, response)] [System.out.println("after...")]之间执行。

4.SpringMVC的机制是由同一个Servlet来分发请求给不同的Controller,其实这一步是在Servlet的service()方法中执行的

所以过滤器、拦截器、service()方法,dispatc()方法的执行顺序应该是这样的,大致画了个图:其实非常好测试,自己写一个过滤器,一个拦截器,然后在这些方法中都加个断点,一路F8下去就得出了结论。

在spring中获得request,常用的有三种

一.Controller中加参数
1
2
3
4
5
6
7
8
@Controller
public class TestController {
@RequestMapping("/test")
public void test(HttpServletRequest request) throws InterruptedException {
// 模拟程序执行了一段时间
Thread.sleep(1000);
}
}

线程安全

二.自动注入

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
public class TestController{

@Autowired
private HttpServletRequest request; //自动注入request

@RequestMapping("/test")
public void test() throws InterruptedException{
//模拟程序执行了一段时间
Thread.sleep(1000);
}
}

线程安全

在这里可能会有些疑问,spring注入的都是单例,会不会出现问题? 不会

@Autowired HttpServletRequest and passing as a parameter are the same things.

Before passing HttpServletRequest to invocation method responding to @RequestMapping function, Spring stores the HttpServletRequest into a ThreadLocal type variable.

That ThreadLocal variable is a thread-safe map that keeps HttpServletRequest in the current thread context. The @Autowired HttpServletRequest proxy bean gets the correct request from that ThreadLocal variable.

三.手动调用
1
2
3
4
5
6
7
8
9
@Controller
public class TestController {
@RequestMapping("/test")
public void test() throws InterruptedException {
HttpServletRequest request = ((ServletRequestAttributes)(RequestContextHolder.currentRequestAttributes())).getRequest();
// 模拟程序执行了一段时间
Thread.sleep(1000);
}
}

线程安全

参考:https://www.cnblogs.com/kismetv/p/8757260.html

https://stackoverflow.com/questions/48574780/autowired-httpservletrequest-vs-passing-as-parameter-best-practice

https://stackoverflow.com/questions/3320674/spring-how-do-i-inject-an-httpservletrequest-into-a-request-scoped-bean

今天写了一段这样的代码,然后报错了
1
2
3
4
5
6
7
8
9
10
11
12
public class ceshi2 {

class Student{
private String name;
private Integer age;
}

public static void main(String[] args) {
Student student=new Student();

}
}

You have to have a reference to the other outer class as well.

1
Inner inner = new MyClass().new Inner();

If Inner was static then it would be

1
Inner inner = new MyClass.Inner();
What is a static class in Java?

You cannot use the static keyword with a class unless it is an inner class. A static inner class is a nested class which is a static member of the outer class. It can be accessed without instantiating the outer class, using other static members.

参考:https://stackoverflow.com/questions/12690128/how-to-instantiate-non-static-inner-class-within-a-static-method

https://www.tutorialspoint.com/What-is-a-static-class-in-Java

JavaScript == 与 === 区别

1、对于 string、number 等基础类型,== 和 === 是有区别的

  • a)不同类型间比较,== 之比较 "转化成同一类型后的值" 看 "值" 是否相等,=== 如果类型不同,其结果就是不等。
  • b)同类型比较,直接进行 "值" 比较,两者结果一样。

2、对于 Array,Object 等高级类型,== 和 === 是没有区别的

进行 "指针地址" 比较

3、基础类型与高级类型,== 和 === 是有区别的

  • a)对于 ==,将高级转化为基础类型,进行 "值" 比较
  • b)因为类型不同,=== 结果为 false

4、!= 为 == 的非运算,!== 为 === 的非运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var num=1

var str="1"

var test=1

test == num //true 相同类型 相同值

test === num //true 相同类型 相同值

test !== num //false test与num类型相同,其值也相同, 非运算肯定是false

num == str //true  把str转换为数字,检查其是否相等。

num != str //false == 的 非运算

num === str //false 类型不同,直接返回false

num !== str //true num 与 str类型不同 意味着其两者不等 非运算自然是true啦

参考:https://www.runoob.com/note/12388

#{}和${}的区别:

1:

#{}为参数占位符?,即sql预编译

${}为字符串替换,即sql拼接

2:

变量替换后,#{}对应的变量自动加上单引号 ''

变量替换后,${}对应的变量不会加上单引号 ''

3:

#{}能防止sql注入

${}不能防止sql注入

示例:

假设传入参数为 1

第一步:

#{}:select * from t_user where uid=#{uid}

${}:select * from t_user where uid= '${uid}'

第二步:

#{}:select * from t_user where uid= ?

${}:select * from t_user where uid= '1'

第三步:

#{}:select * from t_user where uid= '1'

${}:select * from t_user where uid= '1'

一.前置知识

​ AOP包含的几个术语有Aspect,Join point,Advice,Pointcut,Introduction,Target object,AOP proxy,Weaving。

在了解这几个术语之前,首先要知道Concern,Separation of concerns和Crosscutting Concern

  • concern(关注点):A Concern is a term that refers to a part of the system divided on the basis of the functionality.

​ 简单的来说,关注点就是你所关注的功能(模块),比如支付模块

  • Separation of concerns(关注点分离):Usually the code can be separated into logical sections, each addressing separate concerns, and so it hides the need for a given section to know particular information addressed by a different section.

    将代码分成单独的部分,即可以理解为不可再分割的组件,如日志组件和支付组件;

  • Crosscutting Concern(横切关注点):The crosscutting concern is a concern which is applicable throughout the application and it affects the entire application.

    For example: logging, security and data transfer are the concerns which are needed in almost every module of an application, hence they are cross-cutting concerns.

    一个影响很多模块或者所有模块的关注点。

二.术语介绍

下面以表格的方式,来对他们进行总结:

英文名 中文名 作用
Jointpoint 连接点 程序执行过程中的一个点,表示需要在程序中插入横切关注点的扩展点,例如方法的执行或异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。
Pointcut 切入点 选择一组相关连接点的模式,即可以认为连接点的集合。
Advice 通知 在连接点上执行的行为
Aspect 方面/切面 跨多个类的关注点的模块化(即横切关注点的模块化),比如日志组件
Introduction
(inter-type declaration)
引入 也称为内部类型声明,为已有的类添加额外新的字段或方法,Spring允许引入新的接口(必须对应一个实现)到所有被代理对象(目标对象)
Target Object 目标对象 需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被通知的对象,从而也可称为“被通知对象”;由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象
AOP Proxy Object AOP代理对象 AOP框架使用代理模式创建的对象,从而实现在连接点处插入通知(即应用切面),就是通过代理来对目标对象应用切面。在Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。
Weaving 织入 织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期进行。

在AOP中,通过切入点选择目标对象的连接点,然后在目标对象的相应连接点处织入通知,而切入点和通知就是切面(横切关注点),而在目标对象连接点处应用切面的实现方式是通过AOP代理对象,如图所示

这是曾经写过的一个AOP例子:

1
2
3
4
5
6
7
8
9
10
11
12
@AfterReturning(value = "execution(* *..service.Impl.group.GroupInfoServiceImpl.createGroup(..))",returning = "result")
public void createGroupInfo(JoinPoint jp,boolean result){
if(result==true){
Object[] args = jp.getArgs();
GroupInfo groupInfo=(GroupInfo) args[0];
Long userId=(Long) args[1];
String username = dataAopDao.getName(userId);
String operation="组建了\""+groupInfo.getGroupName()+"\"队伍";
DataInfo dataInfo=new DataInfo(username,operation,1);
dataInfoDao.insert(dataInfo);
}
}

参考:https://wizardforcel.gitbooks.io/gen-wo-xue-spring/content/36.html

https://stackoverflow.com/questions/23700540/cross-cutting-concern-example

https://en.wikipedia.org/wiki/Concern_(computer_science)

https://en.wikipedia.org/wiki/Separation_of_concerns

https://en.wikipedia.org/wiki/Cross-cutting_concern

5. Aspect Oriented Programming with Spring

5.1. AOP Concepts

让我们从定义一些核心 AOP 概念和术语开始。 这些术语不是 Spring 特定的。 不幸的是,AOP 术语并不是特别直观。 但是,如果 Spring 使用它自己的术语,那就更令人困惑了

Let us begin by defining some central AOP concepts and terminology. These terms are not Spring-specific. Unfortunately, AOP terminology is not particularly intuitive. However, it would be even more confusing if Spring used its own terminology.

  • 面向方面编程 (AOP) 通过提供另一种思考程序结构的方式来补充面向对象编程 (OOP)。 OOP 中模块化的关键单元是类,而 AOP 中模块化的单元是方面。 方面支持跨多种类型和对象的关注点(例如事务管理)的模块化。 (这种关注点在 AOP 文献中通常被称为“横切”关注点。)

​ Aspect-oriented Programming (AOP) complements Object-oriented Programming (OOP) by providing another way of thinking about program structure. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects enable the modularization of concerns (such as transaction management) that cut across multiple types and objects. (Such concerns are often termed “crosscutting” concerns in AOP literature.)

  • 方面/切面:跨多个类的关注点的模块化。事务管理是企业 Java 应用程序中横切关注点的一个很好的例子。在 Spring AOP 中,方面是通过使用常规类(基于模式的方法)或使用 @Aspect 注释(@AspectJ 样式)注释的常规类来实现的。

​ Aspect: A modularization of a concern that cuts across multiple classes. Transaction management is a good example of a crosscutting concern in enterprise Java applications. In Spring AOP, aspects are implemented by using regular classes (the schema-based approach) or regular classes annotated with the @Aspect annotation (the @AspectJ style).

  • 连接点:程序执行过程中的一个点,例如方法的执行或异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法执行。

​ Join point: A point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.

  • 建议:方面在特定连接点采取的行动。不同类型的建议包括“周围”、“之前”和“之后”建议。 (通知类型将在后面讨论。)许多 AOP 框架,包括 Spring,将通知建模为拦截器,并在连接点周围维护一个拦截器链。

​ Advice: Action taken by an aspect at a particular join point. Different types of advice include “around”, “before” and “after” advice. (Advice types are discussed later.) Many AOP frameworks, including Spring, model an advice as an interceptor and maintain a chain of interceptors around the join point.

  • 切入点:匹配连接点的谓词。 Advice 与切入点表达式相关联,并在与切入点匹配的任何连接点处运行(例如,执行具有特定名称的方法)。切入点表达式匹配的连接点的概念是 AOP 的核心,Spring 默认使用 AspectJ 切入点表达式语言。

​ Pointcut: A predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut expression language by default.

  • Introduction:代表一个类型声明额外的方法或字段。 Spring AOP 允许您向任何建议的对象引入新接口(和相应的实现)。例如,您可以使用介绍使 bean 实现 IsModified 接口,以简化缓存。 (介绍在 AspectJ 社区中称为类型间声明。)

​ Introduction: Declaring additional methods or fields on behalf of a type. Spring AOP lets you introduce new interfaces (and a corresponding implementation) to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching. (An introduction is known as an inter-type declaration in the AspectJ community.)

  • 目标对象:一个或多个方面建议的对象。也称为“建议对象”。由于 Spring AOP 是使用运行时代理实现的,因此该对象始终是代理对象。

​ Target object: An object being advised by one or more aspects. Also referred to as the “advised object”. Since Spring AOP is implemented by using runtime proxies, this object is always a proxied object.

  • AOP 代理:由 AOP 框架创建的对象,用于实现方面协定(建议方法执行等)。 在 Spring Framework 中,AOP 代理是 JDK 动态代理或 CGLIB 代理。

​ AOP proxy: An object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy is a JDK dynamic proxy or a CGLIB proxy.

  • 编织:将方面与其他应用程序类型或对象链接以创建建议对象。 这可以在编译时(例如,使用 AspectJ 编译器)、加载时或运行时完成。 Spring AOP 与其他纯 Java AOP 框架一样,在运行时执行编织。

​ Weaving: linking aspects with other application types or objects to create an advised object. This can be done at compile time (using the AspectJ compiler, for example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, performs weaving at runtime.

5.4.1. Enabling @AspectJ Support

通过自动代理,我们的意思是,如果 Spring 确定一个 bean 由一个或多个方面通知,它会自动为该 bean 生成一个代理来拦截方法调用并确保根据需要运行通知。

By auto-proxying, we mean that, if Spring determines that a bean is advised by one or more aspects, it automatically generates a proxy for that bean to intercept method invocations and ensures that advice is run as needed.