动态 返回 CSS 实现
本文介绍如何通过识别浏览器的 User-Agent,判断设备是移动端还是桌面端,并返回对应的 CSS 样式。
解析 User-Agent
常见的 User-Agent 示例
Google Chrome:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36
Microsoft Edge:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.43
Mozilla Firefox:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0
iPhone Safari:
Mozilla/5.0 (iPhone; CPU iPhone OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.3 Mobile/15E148 Safari/604.1
Android Chrome:
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36
微信浏览器:
Mozilla/5.0 (Linux; Android 13; IN2017 Build/RKQ1.211119.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.120 Mobile Safari/537.36 XWEB/1220133 MMWEBSDK/20240501 MMWEBID/9296 MicroMessenger/8.0.49.2685(0x28003145) WeChat/arm64 Weixin GPVersion/1 NetType/WIFI Language/en ABI/arm64
QQ 浏览器:
Mozilla/5.0 (Linux; Android 13; IN2017 Build/RKQ1.211119.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/109.0.5414.86 MQQBrowser/6.2 TBS/047101 Mobile Safari/537.36 V1_AND_SQ_9.0.50_6258_YYB_D QQ/9.0.50.16545 NetType/WIFI WebP/0.3.0 AppId/537217916 Pixel/1080 StatusBarHeight/107 SimpleUISwitch/0 QQTheme/1103 StudyMode/1 CurrentMode/2 CurrentFontScale/1.0 GlobalDensityScale/0.90000004 AllowLandscape/false InMagicWin/0
解析 User-Agent
Tio-Utils
提供了 UserAgentUtil
工具类,可以方便地解析 User-Agent
并获取相关信息。
示例代码如下:
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.annotation.RequestPath;
import com.litongjava.tio.utils.http.useragent.UserAgent;
import com.litongjava.tio.utils.http.useragent.UserAgentUtil;
@RequestPath("/")
public class IndexController {
@RequestPath()
public UserAgent index(HttpRequest request) {
return UserAgentUtil.parse(request.getUserAgent());
}
}
解析后的 JSON 内容示例如下:
{
"version": "127.0.0.0",
"mobile": false,
"engineVersion": "537.36",
"engine": {
"name": "Webkit",
"pattern": "webkit",
"unknown": false
},
"platform": {
"mobile": false,
"name": "Windows",
"pattern": "windows",
"unknown": false
},
"browser": {
"mobile": false,
"name": "Chrome",
"pattern": "chrome",
"unknown": false
},
"os": {
"name": "Windows 10 or Windows Server 2016",
"pattern": "windows nt 10\\.0",
"unknown": false
}
}
动态 CSS 实现
实现思路
解析浏览器的 User-Agent
使用UserAgentUtil
解析浏览器的User-Agent
,判断请求来自移动端还是桌面端。返回对应的 CSS 样式
- 如果是移动端,则返回移动端的 CSS 样式,样式文件位于运行时目录的
mobile/{uri}.css
。 - 如果是桌面端,则返回桌面端的 CSS 样式,样式文件位于运行时目录的
pc/{uri}.css
。
- 如果是移动端,则返回移动端的 CSS 样式,样式文件位于运行时目录的
自动创建 CSS 文件
如果请求的 CSS 文件不存在,系统会自动创建该文件,并写入默认内容。
实现代码
以下是实现动态 CSS 返回的代码示例:
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.annotation.RequestPath;
import com.litongjava.tio.http.server.util.Resps;
import com.litongjava.tio.utils.environment.EnvUtils;
import com.litongjava.tio.utils.http.useragent.UserAgent;
import com.litongjava.tio.utils.http.useragent.UserAgentUtil;
@RequestPath("/css")
public class CSSController {
private Map<String, String> cssMap = new ConcurrentHashMap<>();
@RequestPath("/{filename}")
public HttpResponse index(HttpRequest request, String filename) {
// 解析 User-Agent,判断请求来自移动端还是桌面端
UserAgent userAgent = UserAgentUtil.parse(request.getUserAgent());
// 根据设备类型定义对应的目录
String directory = userAgent.isMobile() ? "css/mobile/" : "css/pc/";
String pathname = directory + filename;
if (EnvUtils.isDev()) {
// 创建 CSS 文件对象
File file = new File(pathname);
// 检查文件是否存在
if (!file.exists()) {
// 如果文件不存在,则创建必要的父目录
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs(); // 创建目录
}
try {
// 创建新 CSS 文件并写入默认内容(可选)
Files.write(file.toPath(), "/* Default CSS content */".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace(); // 处理异常
}
}
}
String cssContent = cssMap.get(pathname);
if (cssContent == null) {
// 创建 CSS 文件对象
File file = new File(pathname);
try {
// 读取并返回 CSS 文件的内容
cssContent = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
cssMap.put(pathname, cssContent);
} catch (IOException e) {
e.printStackTrace(); // 处理异常
return Resps.css(request, "/* Error loading CSS */");
}
}
return Resps.css(request, cssContent);
}
}
请求地址示例:http://localhost:8000/css/index.css
返回的数据示例:
/* Default CSS content */