Java优雅地执行js

ScriptEngine

java从jdk1.6开始引入js引擎 ScriptEngine,从而支持执行js脚本,但是如果js脚本中包含一些浏览器内置对象,比如window对象,那么java在执行该脚本时会抛异常

Selenium?

selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,可以使用包括括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等浏览器,和用户自己操作浏览器一样。 可以作为web自动化测试工具,也可以作为第三方中介来执行一些java中执行不了的js代码

本文主要介绍 通过使用Selenium来让java 执行js方法

引入依赖

1
2
3
4
5
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.0.0-alpha-5</version>
</dependency>

selenium 对应浏览器驱动下载

各浏览器下载地址:

Chrome浏览器驱动:chromedriver

Firefox浏览器驱动:geckodriver

还有其他的浏览器:IE浏览器驱动、Edge浏览器驱动、Opera浏览器驱动、hantomJS浏览器驱动,这边就具体举例了

注:下载的浏览器驱动 一定得和电脑中的浏览器 版本 符合

Selenium 简单例子

把相关驱动和依赖都配好后,我们先弄一个小例子来测试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RestController
public class ThirdPartyController {

@GetMapping("/thirdParty/test")
public void test() throws FileNotFoundException {
// chromedriver服务地址
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "/src/main/resources/static/driver/"+ "chromedriver93.exe");
// 1.创建webdriver驱动
WebDriver driver = new ChromeDriver();
// 2.打开百度首页
driver.get("https://www.baidu.com");
// 3.退出浏览器
driver.quit();
}

}

效果:浏览器会自动打开,并跳到百度

工具类

话不多说,直接上干货,将我们常用的方法抽出工具类,方便大家使用

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
85
86
87
88
package com.xiaoniu.blog.utils;

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/**
* @Author: xiaoniuhululu.com
* @Date: 2021-12-28-23:37
* @Description: 执行js
* @Version 1.0 zhangjun
*/
public class JsExecutorUtils {
static Logger logger = LoggerFactory.getLogger(JsExecutorUtils.class);

/**
* 不带 线程等待时间的 默认300毫秒
* @param webDriver
* @param js
* @return
*/

public static Object sendJS(WebDriver webDriver, String js){
// 默认300 毫秒
return sendJS(webDriver,js, 300);
}

/**
* 带线程等待时间的,默认是第二个参数的 单位毫秒
*/

public static Object sendJS(WebDriver webDriver,String js, int m){
logger.info("执行JS==>> "+js);
Object object = ((JavascriptExecutor) webDriver).executeScript(js);
try { Thread.sleep(m); }catch (Exception e){ }
return object;
}

/**
* 执行js文件(网上目前没有相关的可参考,自己就撸了一个,挺巧妙的--)
* @param webDriver
* @param fileName
* @param funName
* @param m
* @param var2
* @return
* @throws IOException
*/
public static String executeJsByFile(WebDriver webDriver, String fileName,String funName, int m, Object... var2) throws IOException {
String result= "";
StringBuilder script = new StringBuilder();
File file = new File(System.getProperty("user.dir") + "/src/main/resources/static/js/"+ fileName+ ".js");
FileReader filereader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(filereader);
String tempString = null;
while ((tempString = bufferedReader.readLine()) != null) {
script.append(tempString).append("\n");
}
bufferedReader.close();
filereader.close();

String params="";
if(var2.length > 0) {
for(int i=0;i< var2.length;i++) {
params = params + "arguments["+ i+ "]";
if(i!= var2.length-1) {
params = params + ",";
}
}
}
String addStr = "return "+ funName+ "("+params+");";
script.append(addStr);

Object object_file = ((JavascriptExecutor) webDriver).executeScript(script.toString(), var2);
try { Thread.sleep(m); }catch (Exception e){ }

result = String.valueOf(object_file);
return result;
}

}

测试 :执行js

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
@SpringBootTest
public class DemoJsTests {

@Test
void contextLoads() {
/**
* 配置系统变量
*/
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "/src/main/resources/static/driver/"+ "chromedriver96.exe");
/**
* 声明一个ChromeOptions变量,来控制 浏览器启动参数
*/
ChromeOptions chromeOptions = new ChromeOptions();
// 配置headless属性为true,无界面模式,表示不在前台打开chrome
chromeOptions.setHeadless(true);

/**
* 创建webdriver驱动
*/
WebDriver driver = new ChromeDriver(chromeOptions);
String result = String.valueOf(JsExecutorUtils.sendJS(driver,"return 3+2"));
System.out.println(result);

//一定记得要及时 退出
driver.quit();
return;
}

}

结果:

5

测试:执行JS文件

test.js

1
2
3
4
5
6
7
8
9
10
11
function sum(a, b) {
return a+b;
}

function average(a, b, c) {
return (a+b+c)/3;
}

function console() {
return "test";
}

我们接着来测试一下,看看实战效果,将整个逻辑串一串

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
package com.xiaoniu.blog;

import com.xiaoniu.blog.utils.JsExecutorUtils;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
class BlogApplicationTests {

@Test
void contextLoads() {
// chromedriver服务地址
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "/src/main/resources/static/driver/"+ "chromedriver93.exe");

/**
* 声明一个ChromeOptions变量,来控制 浏览器启动参数
*/
ChromeOptions chromeOptions = new ChromeOptions();
// 配置headless属性为true,无界面模式,表示不在前台打开chrome
chromeOptions.setHeadless(true);

WebDriver driver = new ChromeDriver(chromeOptions);

try {
String result = JsExecutorUtils.executeJsByFile(driver,"test","sum",300, 8, 9);
System.out.println("test:"+ result);

String result2 = JsExecutorUtils.executeJsByFile(driver,"test","average",300, 1, 2,3);
System.out.println("average:"+ result2);

String result3 = JsExecutorUtils.executeJsByFile(driver,"test","console",300);
System.out.println("console:"+ result3);


} catch (IOException e) {
e.printStackTrace();
}
//一定记得要及时 退出
driver.quit();

}

}

结果:

test:17

average:2

console:test

Selenium 操作页面

Selenium可以执行基本上所有 document,window,jquery等js相关操作,不像java的js引擎那样 限制重重

尾语

本文 主要是 将Selenium作为中介 ,让java执行js方法,其他的没有过多,但Selenium作为自动化测试框架,功能异常强大,本职功能可以写自动测试程序,但作用远不止如此,比如由于它可以模拟人去操作页面,能够操作iframe等平常技术难以操作的页面元素,可以当作超级爬虫,跨越网站的层层安全防护墙等等。


本篇文章到这里就结束啦,如果喜欢的话,多多支持,欢迎关注!