├── .gitignore ├── README.md ├── basicskill ├── basicskill-java │ ├── dependency-reduced-pom.xml │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── cn │ │ │ └── yourbatman │ │ │ └── basicskill │ │ │ └── java │ │ │ └── rain │ │ │ ├── CodeRainJPanel.java │ │ │ └── CodeRainMain.java │ │ └── resources │ │ └── duanwujie.txt └── pom.xml ├── cors ├── cors-java │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── cn │ │ │ └── yourbatman │ │ │ └── cors │ │ │ └── java │ │ │ ├── filter │ │ │ └── CORSFilter.java │ │ │ ├── servlet │ │ │ ├── CookieServlet.java │ │ │ ├── CorsCookieServlet.java │ │ │ ├── CorsServlet.java │ │ │ ├── JSONPServlet.java │ │ │ └── MultipleOriginsCorsServlet.java │ │ │ └── spring │ │ │ └── CorsConfigurationDemo.java │ │ └── resources │ │ ├── logback.xml │ │ └── static │ │ ├── cookie.html │ │ ├── cors.html │ │ ├── corscookie.html │ │ ├── jsonp.html │ │ └── multiple_origins_cors.html ├── cors-spring-framework │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── cn │ │ │ └── yourbatman │ │ │ └── cors │ │ │ ├── configuration │ │ │ ├── MyWebAppInitializer.java │ │ │ ├── RootConfiguration.java │ │ │ └── WebMvcConfiguration.java │ │ │ └── springframework │ │ │ ├── Application.java │ │ │ ├── controller │ │ │ ├── IndexController.java │ │ │ └── UrlPathHelperController.java │ │ │ └── filter │ │ │ └── CORSFilterV2.java │ │ └── resources │ │ ├── logback.xml │ │ └── static │ │ └── index.html ├── cors-springboot │ └── pom.xml └── pom.xml ├── foundation ├── foundation-java │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── cn │ │ └── yourbatman │ │ └── foundation │ │ └── java │ │ ├── WebUtils.java │ │ ├── filter │ │ └── FakeFilter.java │ │ └── servlet │ │ ├── Demo1Servlet.java │ │ ├── Fake1Servlet.java │ │ ├── FakeServlet.java │ │ └── UrlPatternDemoServlet.java ├── foundation-spring-framework │ └── pom.xml ├── foundation-springboot │ └── pom.xml └── pom.xml ├── javaee ├── javaee-el │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── cn │ │ └── yourbatman │ │ └── javaee │ │ └── el │ │ └── Demo.java ├── javaee-jaxrs │ └── pom.xml ├── javaee-jsonb │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── cn │ │ └── yourbatman │ │ └── javaee │ │ └── jsonb │ │ ├── Demo.java │ │ └── Person.java ├── javaee-servlet │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── cn │ │ │ └── yourbatman │ │ │ └── javaee │ │ │ └── servlet │ │ │ └── HelloServlet.java │ │ └── webapp │ │ ├── WEB-INF │ │ └── web.xml │ │ └── hello.jsp ├── javaee-websocket │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── cn │ │ │ └── yourbatman │ │ │ └── javaee │ │ │ └── websocket │ │ │ ├── App.java │ │ │ ├── WsClient.java │ │ │ └── WsServer.java │ │ └── resources │ │ └── logback.xml └── pom.xml ├── pom.xml └── spring5 ├── pom.xml └── spring5-java ├── pom.xml └── src └── main └── java └── cn └── yourbatman └── spring5 └── java ├── antpathmatcher └── Demo1.java └── pathpattern ├── CompareDemo.java ├── Demo1.java ├── Demo2.java └── WebMvcConfiguration.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Contact me if any problem occurred. mailto:yourbatman@aliyun.com | https://yourbatman.cn 2 | HELP.md 3 | target/ 4 | !.mvn/wrapper/maven-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### eclipse/STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | 23 | ### NetBeans ### 24 | /nbproject/private/ 25 | /nbbuild/ 26 | /dist/ 27 | /nbdist/ 28 | /.nb-gradle/ 29 | build/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | 34 | ### temp ignore ### 35 | *.orig 36 | *.log 37 | *.cache 38 | *.diff 39 | *.patch 40 | *.tmp 41 | 42 | ### for project ### 43 | directoryList.md -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### :man_technologist: [方向盘(YourBatman、方哥)](https://yourbatman.cn) | 做爱做之事❣交配交之人 2 | 我是[**方向盘(YourBatman、方哥)**](https://mp.weixin.qq.com/s/PGIFtpI7aZaxY7es0F6C6Q):一个前25年还不会写Hallo World、早已毕业的[**大龄程序员**](https://yourbatman.cn/about)。网瘾失足、清考、延期毕业、房产中介、保险销售、送外卖...是我不可抹灭的黑标签 3 | 4 | --- 5 | 6 |
7 |
8 | 9 |
10 |
11 | 12 |
13 | 14 | 15 | 16 | 17 |
18 |
19 | 20 | 本仓库是你需要的专栏【**大本营**】,汇聚了方向盘(YourBatman、方哥)原创的几十个小而美的技术专栏,万丈高楼平地起,打实基础方可走得更快、更远。 21 | 22 | ## 专栏目录 23 | | 序号 | 专栏名称 | 专栏地址 | 24 | | :--: | --------------------------------------------- | --------------------------------------------- | 25 | | 01 | 【方向盘】-程序人生 | 待归档... | 26 | | 02 | 【方向盘】-日期时间 | 待归档... | 27 | | 03 | 【方向盘】-资讯/新特性 | 待归档... | 28 | | 04 | 【方向盘】-Spring static | 待归档... | 29 | | 05 | 【方向盘】-Bean Validation | 待归档... | 30 | | 06 | 【方向盘】-Servlet | 待归档... | 31 | | 07 | 【方向盘】-Spring技术栈 | 待归档... | 32 | | 08 | 【方向盘】-JDK | 待归档... | 33 | | 09 | 【方向盘】-Cors跨域 | 待归档... | 34 | | 10 | 【方向盘】-Spring配置类 | 待归档... | 35 | | 11 | 【方向盘】-Spring类型转换 | 待归档... | 36 | | 12 | 【方向盘】-Jackson | 待归档... | 37 | | 13 | 【方向盘】-IntelliJ IDEA | 待归档... | 38 | | 14 | 【方向盘】-Java EE | [专栏地址](https://github.com/yourbatman/FXP-java-ee) | 39 | | 15 | 待归档... | 待归档... | 待归档... | 40 | 41 | > Tips:关注公众号【Java方向盘】,后台回复"专栏列表",可【提前阅读】上面专栏内容 42 | 43 | ## 阅读说明书 44 | 本着追本溯源,拒绝浅尝辄止的学习目的。自上而下的应用,自底向上的学习,做到学有所成,**既知所用又懂原理方可通透**。 45 | 46 | (几乎)所有专栏会按照三步曲进行展开: 47 | 1. 基础:万丈高楼平地起。深入了解其设计理念、架构思想、组件功能、API设计 48 | 2. 进阶:协同进阶以拔高。高级功能、和其它组件/框架协同使用 49 | 3. 应用:智能整合供应用。如何智能化、简单化供给开发者使用,是一个产品的外观 50 | 51 | 三步曲体现在工程目录上如下结构所示: 52 | ``` 53 | |-- project 54 | |-- cors // 专栏名 55 | | |-- cors-java 56 | | |-- cors-spring-framework 57 | | |-- cors-spring-boot 58 | |-- xxx // 专栏名 59 | | |-- xxx-java 60 | | |-- xxx-spring-framework 61 | | |-- xxx-spring-boot 62 | ``` 63 | 1. xxx-java工程:最纯粹工程。去除一切非相关依赖,直接接触**底层API**。深入理解其设计思想。 64 | - 一般来讲该工程仅依赖JDK以及该专题设计的【底层基础Jar包】 65 | - 启动/运行方式:main方法(servlet web工程除外,需要war包方式部署到外置Tomcat启动) 66 | 2. xxx-spring-framework工程:通过扩展点和Spring框架整合。只有进阶了解了Spring Framework的协同使用,才会有对原理更深一层的理解 67 | - 一般来讲该工程会依赖【Spring容器】,在上工程基础上引入Spring Framework相关依赖 68 | - 启动/运行方式:main方法(spring web工程除外,需要war包方式部署到外置Tomcat启动) 69 | 3. xxx-spirng-boot工程;一切的最终目的都是使用。而开发者必定面向更加智能化的Spring Boot开发应用 70 | - 一般来讲这是最后一步。Spring Boot是高度封装、智能化的基础框架,一切专题/组件最后都需和它整合方可使用 71 | - 启动/运行方式:main方法 72 | 73 | --- 74 | 75 | ### 联系我 76 | > - 🎓2013.07 清考、毕业答辩3次未通过、延期毕业 77 | > - 🏷2013.08-2014.07 宁夏中介公司卖二手房1年,毕业后第1份工作 78 | > - ️️🏷2014.07-2015.05 荆州/武汉,泰康人寿卖保险3月、饿了么送外卖2月,还有炸鸡排、直销等第2345份工作 79 | > - 🏷2015.08 开始从事Java开发,闯过外包,呆过大厂!多年架构经验,任基础架构/中间件团队负责人 80 | > - 🏷2021.08 [因“双减政策”失业!历经9面,终获美团外卖L8的offer](https://mp.weixin.qq.com/s/tMiDQXPt2Gw3hRikAGibAg) 81 | > - 82 | > - 🙅🏻‍♀️Java架构师、Spring开源贡献者、CSDN博客之星年度Top 10、领域建模专家、写作大赛1/2届评委 83 | > - 📚将出版书籍《Spring奇淫巧技》,致力于国内zui好、zui具深度、zui实用的专栏,为市场贡献微薄之力 84 | > - 85 | > - 现在写纯粹技术专栏(公号后台回复**专栏列表**),不哗众取宠。如果你也有共鸣,可加我好友(fsx1056342982)一起进步 86 | 87 | - Contact me:[方向盘(YourBatman、方哥)](https://yourbatman.cn) 88 | - 公众号:[Java方向盘](https://cdn.jsdelivr.net/gh/yourbatman/cdn/blog/image/yourbatman/wechat-public-8cm.jpg) 89 | - 我的站点:[https://yourbatman.cn](https://yourbatman.cn) 90 | - 我的网盘:[https://wangpan.yourbatman.cn](https://wangpan.yourbatman.cn) 91 | - 注册送1G超小容量,助你做减法(为什么要做减法?读这里:[做加法容易做减法难,程序员的我深有同感](https://yourbatman.cn/x2y/89616c6e.html)) 92 | 93 | ![Java方向盘-搜一搜](https://cdn.jsdelivr.net/gh/yourbatman/cdn/blog/image/yourbatman/wechat-public-soso-qrcode.png) 94 | 95 | ### 实用工具 96 | - 【女娲Knife-Initializr工程】访问地址:[http://152.136.106.14:8761](http://152.136.106.14:8761) 97 | - 【程序员专用网盘】公益上线啦,注册送1G超小容量,帮你实践做**减法**:[https://wangpan.yourbatman.cn](https://mp.weixin.qq.com/s/e_ffqJd7edyCM8celr-Uww) 98 | - 【Java开发软件包(Mac)】:[https://wangpan.yourbatman.cn/s/rEH0](https://wangpan.yourbatman.cn/s/rEH0) 提取码:javakit 99 | 100 | ### 期待与你相遇 101 | 喜欢交朋友,喜欢讨论技术,更喜欢向你学习。期待在程序的世界里我们能相遇! 102 | 103 | --- 104 | *由于作者水平有限,可能存在描述不准确或错别字内容,👏🏻欢迎随时反馈给我。我是方向盘(YourBatman、方哥),一个纯粹技术工!* -------------------------------------------------------------------------------- /basicskill/basicskill-java/dependency-reduced-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | basicskill 5 | cn.yourbatman 6 | 1.0-SNAPSHOT 7 | 8 | 4.0.0 9 | basicskill-java 10 | 11 | codeRainApp 12 | 13 | 14 | maven-shade-plugin 15 | 2.4.1 16 | 17 | 18 | package 19 | 20 | shade 21 | 22 | 23 | 24 | 25 | 26 | 27 | cn.yourbatman.basicskill.java.rain.CodeRainMain 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.springframework 37 | spring-test 38 | 5.3.20 39 | test 40 | 41 | 42 | 43 | 8 44 | 8 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /basicskill/basicskill-java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | basicskill 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | basicskill-java 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | commons-io 22 | commons-io 23 | 24 | 25 | org.apache.commons 26 | commons-lang3 27 | 28 | 29 | 30 | 31 | codeRainApp 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-shade-plugin 36 | 2.4.1 37 | 38 | 39 | 40 | cn.yourbatman.basicskill.java.rain.CodeRainMain 41 | 42 | 43 | 44 | 45 | 46 | package 47 | 48 | shade 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /basicskill/basicskill-java/src/main/java/cn/yourbatman/basicskill/java/rain/CodeRainJPanel.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.basicskill.java.rain; 2 | 3 | import java.awt.Color; 4 | import java.awt.Font; 5 | import java.awt.Graphics; 6 | import java.awt.Graphics2D; 7 | import java.awt.event.KeyAdapter; 8 | import java.awt.event.KeyEvent; 9 | import java.util.List; 10 | import java.util.concurrent.ThreadLocalRandom; 11 | import javax.swing.JPanel; 12 | 13 | /** 14 | * 代码雨面板 15 | *

Panel是Java图形用户界面(GUI)工具包swing中的【面板】容器类

16 | * 17 | * @author YourBatman. Send email to me 18 | * @site https://yourbatman.cn 19 | * @date 2022/6/3 11:12 20 | * @since 0.0.1 21 | */ 22 | public class CodeRainJPanel extends JPanel { 23 | 24 | 25 | private static final int FONT_SIZE = 33; // 字体大小 26 | private static final int SPACE = 40; // 字间距 27 | private static final int SLEEP_TIME = 130; // 休眠时间(ms),可以尽量慢点 28 | 29 | private String[][] charsetArray; // 字符集合(可从文件、外部配置读取),二位数组 30 | private int[] pos; // 列的起始位置 31 | private Color[] colors = new Color[10]; //列的渐变颜色 32 | 33 | private List surceLines; // 数据源:按行读取 34 | 35 | public CodeRainJPanel(List surceLines) { 36 | this.surceLines = surceLines; 37 | } 38 | 39 | /** 40 | * 按行随机输出 41 | */ 42 | private void randomFromSourceLines(String[] charset) { 43 | int lineCount = this.surceLines.size(); 44 | 45 | int length = 0; 46 | int destPos = 0; 47 | while (true) { 48 | int index = ThreadLocalRandom.current().nextInt(lineCount); 49 | String line = surceLines.get(index); // 从所有行中随机取一行 50 | String[] lineArray = line.split(""); // 将这一行打散成一个个的字 51 | 52 | boolean breakFlag; 53 | if (lineArray.length + destPos >= charset.length) { 54 | length = charset.length - destPos; 55 | breakFlag = true; 56 | } else { 57 | length = lineArray.length; 58 | breakFlag = false; 59 | } 60 | 61 | System.arraycopy(lineArray, 0, charset, destPos, length); // 放进charset里 62 | destPos += length; 63 | if (breakFlag) { 64 | break; 65 | } 66 | } 67 | } 68 | 69 | public void init() { 70 | int width = getWidth(); // 屏幕宽度 71 | int height = getHeight(); // 屏幕高度 72 | 73 | charsetArray = new String[width / SPACE][height / SPACE]; 74 | for (int i = 0; i < charsetArray.length; i++) { 75 | randomFromSourceLines(charsetArray[i]); 76 | } 77 | 78 | //随机化列起始位置 79 | pos = new int[charsetArray.length]; 80 | for (int i = 0; i < pos.length; i++) { 81 | pos[i] = ThreadLocalRandom.current().nextInt(1000); 82 | } 83 | 84 | // 生成渐变色:生成从黑色到绿色的渐变颜色 85 | for (int i = 0; i < colors.length - 1; i++) { 86 | colors[i] = new Color(0, 180 / colors.length * (i + 1), 0); 87 | // colors[i] = new Color(0, 255 / colors.length * (i + 1), 0); 88 | } 89 | 90 | // 背景颜色 91 | setBackground(Color.BLACK); 92 | } 93 | 94 | public void start() { 95 | init(); 96 | new Thread(() -> { 97 | while (true) { 98 | try { 99 | repaint(); // 重绘,调用paint()方法 100 | Thread.sleep(SLEEP_TIME); // 停一会,继续重回,达到一闪一闪的效果 101 | } catch (InterruptedException e) { 102 | Thread.currentThread().interrupt(); 103 | } 104 | } 105 | }).start(); 106 | 107 | // 按键盘的任意箭退出 108 | addKeyListener(new KeyAdapter() { 109 | @Override 110 | public void keyPressed(KeyEvent e) { 111 | System.exit(0); 112 | } 113 | }); 114 | // addMouseListener(new MouseAdapter() { 115 | // @Override 116 | // public void mousePressed(MouseEvent e) { 117 | // System.exit(0); 118 | // } 119 | // }); 120 | } 121 | 122 | 123 | @Override 124 | public void paint(Graphics g) { 125 | //必须设置,否则setBackground(Color.BLACK); 设置背景色无效 126 | super.paint(g); 127 | 128 | Graphics2D g2 = (Graphics2D) g;// 转换为Graphics2D类型 129 | g2.setFont(new Font("华文行楷", Font.BOLD, FONT_SIZE)); 130 | 131 | for (int i = 0; i < charsetArray.length; i++) { 132 | for (int j = 0; j < colors.length; j++) { 133 | int index = (pos[i] + j) % charsetArray[i].length; 134 | 135 | // int R = ThreadLocalRandom.current().nextInt(100);// 随机产生颜色的R值 136 | // int G = ThreadLocalRandom.current().nextInt(180);// 随机产生颜色的G值 137 | // int B = ThreadLocalRandom.current().nextInt(100);// 随机产生颜色的B值 138 | // g2.setColor(new Color(R, G, B)); 139 | 140 | g2.setColor(colors[j]); // 纯黑色,黑客帝国的感觉,不够喜庆 141 | g2.drawString(charsetArray[i][index], i * SPACE, (index + 1) * SPACE); 142 | 143 | } 144 | pos[i] = (pos[i] + 1) % charsetArray[i].length; 145 | // if(pos[i]==0){ 146 | // random(charset[i]); 147 | // } 148 | } 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /basicskill/basicskill-java/src/main/java/cn/yourbatman/basicskill/java/rain/CodeRainMain.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.basicskill.java.rain; 2 | 3 | import static java.lang.String.format; 4 | import static java.nio.charset.StandardCharsets.UTF_8; 5 | 6 | import java.awt.Dimension; 7 | import java.awt.Toolkit; 8 | import java.io.IOException; 9 | import java.util.List; 10 | import javax.swing.JFrame; 11 | import org.apache.commons.io.IOUtils; 12 | import org.springframework.core.io.ClassPathResource; 13 | 14 | /** 15 | * 程序入口 16 | * 17 | * @author YourBatman. Send email to me 18 | * @site https://yourbatman.cn 19 | * @date 2022/6/3 16:50 20 | * @since 0.0.1 21 | */ 22 | public class CodeRainMain { 23 | 24 | public static void main(String[] args) throws IOException { 25 | // 读取端午节祝福语文案 26 | List lines = IOUtils.readLines(new ClassPathResource("duanwujie.txt").getInputStream(), UTF_8); 27 | 28 | // ========== 读取到文案后,开始展示 ========= 29 | Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize(); 30 | int width = (int) (screensize.getWidth() * 0.85); // 笔记本一般是1440 31 | int height = (int) (screensize.getHeight() * 0.85); // 笔记本一般是900 32 | System.out.println(format("屏幕大小为:width:%s height:%s", width, height)); 33 | 34 | JFrame frame = new JFrame("YourBatman祝:端午安康"); 35 | CodeRainJPanel panel = new CodeRainJPanel(lines); // 自定义的代码雨面板对象 36 | 37 | frame.add(panel); // 将面板添加到JFrame中 38 | frame.setSize(width, height); // 设置窗口大小 39 | frame.setResizable(false); 40 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 41 | frame.setLocationRelativeTo(null); // 窗体居中显示 42 | frame.setVisible(true); // 尽快调用paint 43 | 44 | panel.start(); 45 | panel.requestFocus(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /basicskill/basicskill-java/src/main/resources/duanwujie.txt: -------------------------------------------------------------------------------- 1 | 你开发了祝福的程序, 2 | 你安装了虚拟的系统, 3 | 你设置了幸福的密码, 4 | 你下载了流畅的软件, 5 | 端午节到了, 6 | 愿你有个快乐的心情。 7 | 你从智慧中开发财富, 8 | 你从勤奋中耕耘成就, 9 | 你从耐心中创造艺术, 10 | 你从工作中寻找生活, 11 | 端午节到了, 12 | 愿你编出精彩的人生。 13 | 你用命令开启了精彩, 14 | 你用效率创造了价值, 15 | 你用冷静判断了是非, 16 | 你用可观展示了结果, 17 | 端午节到了, 18 | 愿你码出高效的代码。 -------------------------------------------------------------------------------- /basicskill/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tech-column-learning 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | pom 12 | 13 | basicskill-java 14 | 15 | basicskill 16 | 17 | 18 | 8 19 | 8 20 | 21 | 22 | -------------------------------------------------------------------------------- /cors/cors-java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | cors 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | cors-java 12 | war 13 | 14 | 15 | 16 | jakarta.servlet 17 | jakarta.servlet-api 18 | provided 19 | 20 | 21 | org.springframework 22 | spring-webmvc 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/java/cn/yourbatman/cors/java/filter/CORSFilter.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.java.filter; 2 | 3 | import javax.servlet.Filter; 4 | import javax.servlet.FilterChain; 5 | import javax.servlet.ServletException; 6 | import javax.servlet.ServletRequest; 7 | import javax.servlet.ServletResponse; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.io.IOException; 11 | 12 | /** 13 | * 在此处添加备注信息 14 | * 15 | * @author YourBatman. Send email to me 16 | * @site https://yourbatman.cn 17 | * @date 2021/6/14 09:50 18 | * @since 0.0.1 19 | */ 20 | public class CORSFilter implements Filter { 21 | 22 | 23 | @Override 24 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 25 | HttpServletResponse resp = (HttpServletResponse) response; 26 | resp.addHeader("Access-Control-Allow-Credentials", "true"); 27 | resp.addHeader("Access-Control-Allow-Origin", "*"); 28 | resp.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); 29 | resp.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); 30 | if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { 31 | resp.getWriter().println("ok"); 32 | return; 33 | } 34 | chain.doFilter(request, resp); 35 | } 36 | } -------------------------------------------------------------------------------- /cors/cors-java/src/main/java/cn/yourbatman/cors/java/servlet/CookieServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.java.servlet; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.annotation.WebServlet; 7 | import javax.servlet.http.Cookie; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | import static java.util.stream.Collectors.toList; 17 | 18 | /** 19 | * 在此处添加备注信息 20 | * 21 | * @author YourBatman. Send email to me 22 | * @site https://yourbatman.cn 23 | * @date 2021/6/9 10:36 24 | * @since 0.0.1 25 | */ 26 | @Slf4j 27 | @WebServlet(urlPatterns = "/cookie") 28 | public class CookieServlet extends HttpServlet { 29 | 30 | @Override 31 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 32 | String requestURI = req.getRequestURI(); 33 | String method = req.getMethod(); 34 | String originHeader = req.getHeader("Origin"); 35 | log.info("收到请求:{},方法:{}, Origin头:{}", requestURI, method, originHeader); 36 | 37 | // 读取Cookie 38 | List myCookies = new ArrayList<>(); 39 | if (req.getCookies() != null) { 40 | myCookies = Arrays.stream(req.getCookies()).filter(c -> c.getName().equals("name") || c.getName().equals("age")).collect(toList()); 41 | } 42 | 43 | if (myCookies.isEmpty()) { // 种植Cookie 44 | Cookie cookie = new Cookie("name", "YourBatman"); 45 | // cookie.setDomain("baidu.com"); 46 | cookie.setMaxAge(3600); 47 | resp.addCookie(cookie); 48 | cookie = new Cookie("age", "18"); 49 | cookie.setMaxAge(3600); 50 | resp.addCookie(cookie); 51 | } else { 52 | myCookies.stream().forEach(c -> { 53 | log.info("name:{} value:{} domain:{} path:{} maxAge:{} secure:{}", c.getName(), c.getValue(), c.getDomain(), c.getPath(), c.getMaxAge(), c.getVersion(), c.getSecure()); 54 | }); 55 | } 56 | 57 | resp.getWriter().write("hello cookie..."); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/java/cn/yourbatman/cors/java/servlet/CorsCookieServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.java.servlet; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.annotation.WebServlet; 7 | import javax.servlet.http.Cookie; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | import java.util.ArrayList; 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | import static java.util.stream.Collectors.toList; 17 | 18 | /** 19 | * 在此处添加备注信息 20 | * 21 | * @author YourBatman. Send email to me 22 | * @site https://yourbatman.cn 23 | * @date 2021/6/9 10:36 24 | * @since 0.0.1 25 | */ 26 | @Slf4j 27 | @WebServlet(urlPatterns = "/corscookie") 28 | public class CorsCookieServlet extends HttpServlet { 29 | 30 | @Override 31 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 32 | String requestURI = req.getRequestURI(); 33 | String method = req.getMethod(); 34 | String originHeader = req.getHeader("Origin"); 35 | log.info("收到请求:{},方法:{}, Origin头:{}", requestURI, method, originHeader); 36 | 37 | // 读取Cookie 38 | List myCookies = new ArrayList<>(); 39 | if (req.getCookies() != null) { 40 | myCookies = Arrays.stream(req.getCookies()).filter(c -> c.getName().equals("name") || c.getName().equals("age")).collect(toList()); 41 | } 42 | 43 | if (myCookies.isEmpty()) { // 种植Cookie 44 | Cookie cookie = new Cookie("name", "YourBatman"); 45 | // cookie.setDomain("baidu.com"); 46 | cookie.setMaxAge(3600); 47 | resp.addCookie(cookie); 48 | cookie = new Cookie("age", "18"); 49 | cookie.setMaxAge(3600); 50 | resp.addCookie(cookie); 51 | } else { 52 | myCookies.stream().forEach(c -> { 53 | log.info("name:{} value:{} domain:{} path:{} maxAge:{} secure:{}", c.getName(), c.getValue(), c.getDomain(), c.getPath(), c.getMaxAge(), c.getVersion(), c.getSecure()); 54 | }); 55 | } 56 | 57 | setCrosHeader(resp); 58 | resp.getWriter().write("hello cookie..."); 59 | } 60 | 61 | private void setCrosHeader(HttpServletResponse resp) { 62 | resp.setHeader("Access-Control-Allow-Origin", "http://localhost:63342"); 63 | resp.setHeader("Access-Control-Allow-Credentials", "true"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/java/cn/yourbatman/cors/java/servlet/CorsServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.java.servlet; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.annotation.WebServlet; 7 | import javax.servlet.http.HttpServlet; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.io.IOException; 11 | 12 | /** 13 | * 在此处添加备注信息 14 | * 15 | * @author YourBatman. Send email to me 16 | * @site https://yourbatman.cn 17 | * @date 2021/6/9 10:36 18 | * @since 0.0.1 19 | */ 20 | @Slf4j 21 | @WebServlet(urlPatterns = "/cors") 22 | public class CorsServlet extends HttpServlet { 23 | 24 | @Override 25 | protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 26 | super.doOptions(req, resp); 27 | // setCrosHeader(resp); 28 | } 29 | 30 | @Override 31 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 32 | String requestURI = req.getRequestURI(); 33 | String method = req.getMethod(); 34 | String originHeader = req.getHeader("Origin"); 35 | log.info("收到请求:{},方法:{}, Origin头:{}", requestURI, method, originHeader); 36 | 37 | resp.getWriter().write("hello cors..."); 38 | setCrosHeader(resp); 39 | } 40 | 41 | private void setCrosHeader(HttpServletResponse resp) { 42 | resp.setHeader("Access-Control-Allow-Origin", "http://localhost:63342"); 43 | resp.setHeader("Access-Control-Expose-Headers", "token,secret"); 44 | resp.setHeader("Access-Control-Allow-Headers", "token,secret"); // 一般来讲,让此头的值是上面那个的【子集】(或相同) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/java/cn/yourbatman/cors/java/servlet/JSONPServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.java.servlet; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.annotation.WebServlet; 7 | import javax.servlet.http.HttpServlet; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.io.IOException; 11 | 12 | /** 13 | * 在此处添加备注信息 14 | * 15 | * @author YourBatman. Send email to me 16 | * @site https://yourbatman.cn 17 | * @date 2021/6/9 10:36 18 | * @since 0.0.1 19 | */ 20 | @Slf4j 21 | @WebServlet(urlPatterns = "/jsonp") 22 | public class JSONPServlet extends HttpServlet { 23 | 24 | @Override 25 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 26 | String callback = req.getParameter("callback"); 27 | resp.getWriter().write(callback + "('hello jsonp...')"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/java/cn/yourbatman/cors/java/servlet/MultipleOriginsCorsServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.java.servlet; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.annotation.WebServlet; 7 | import javax.servlet.http.HttpServlet; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * 多Origin响应 16 | * 17 | * @author YourBatman. Send email to me 18 | * @site https://yourbatman.cn 19 | * @date 2021/6/9 10:36 20 | * @since 0.0.1 21 | */ 22 | @Slf4j 23 | @WebServlet(urlPatterns = "/multiple_origins_cors") 24 | public class MultipleOriginsCorsServlet extends HttpServlet { 25 | 26 | private List ALLOW_ORIGINS = new ArrayList<>(); 27 | 28 | @Override 29 | public void init() throws ServletException { 30 | ALLOW_ORIGINS.add("http://localhost:9090"); 31 | ALLOW_ORIGINS.add("http://foo.baidu.com:9090"); 32 | ALLOW_ORIGINS.add("http://bar.baidu.com:9090"); 33 | ALLOW_ORIGINS.add("http://static.yourbatman.cn:9090"); 34 | } 35 | 36 | @Override 37 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 38 | String requestURI = req.getRequestURI(); 39 | String method = req.getMethod(); 40 | String originHeader = req.getHeader("Origin"); 41 | log.info("收到请求:{},方法:{}, Origin头:{}", requestURI, method, originHeader); 42 | 43 | resp.getWriter().write("hello multiple origins cors..."); 44 | setCrosHeader(originHeader, resp); 45 | } 46 | 47 | /** 48 | * 写跨域响应头 49 | */ 50 | // private void setCrosHeader(HttpServletResponse resp) { 51 | // resp.setHeader("Access-Control-Allow-Origin", "http://localhost:9090"); 52 | // } 53 | // private void setCrosHeader(HttpServletResponse resp) { 54 | // resp.setHeader("Access-Control-Allow-Origin", "http://foo.baidu.com:9090,http://bar.baidu.com:9090"); 55 | // } 56 | // private void setCrosHeader(HttpServletResponse resp) { 57 | // resp.addHeader("Access-Control-Allow-Origin", "http://foo.baidu.com:9090"); 58 | // resp.addHeader("Access-Control-Allow-Origin", "http://bar.baidu.com:9090"); 59 | // } 60 | // private void setCrosHeader(HttpServletResponse resp) { 61 | // resp.addHeader("Access-Control-Allow-Origin", "http://*.baidu.com:9090"); 62 | // } 63 | private void setCrosHeader(String reqOrigin, HttpServletResponse resp) { 64 | if (reqOrigin == null) { 65 | return; 66 | } 67 | // 匹配算法:equals 68 | if (ALLOW_ORIGINS.contains(reqOrigin)) { 69 | resp.addHeader("Access-Control-Allow-Origin", reqOrigin); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/java/cn/yourbatman/cors/java/spring/CorsConfigurationDemo.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.java.spring; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.http.HttpMethod; 5 | import org.springframework.web.cors.CorsConfiguration; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | 10 | /** 11 | * 在此处添加备注信息 12 | * 13 | * @author YourBatman. Send email to me 14 | * @site https://yourbatman.cn 15 | * @date 2021/6/26 08:00 16 | * @since 0.0.1 17 | * @see CorsConfiguration 18 | */ 19 | public class CorsConfigurationDemo { 20 | 21 | @Test 22 | public void test() { 23 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 24 | 25 | corsConfiguration.addAllowedOrigin("*"); 26 | corsConfiguration.setAllowCredentials(true); 27 | 28 | // 验证:请求Request的此Origin是否合法 29 | String checkedOrigin = corsConfiguration.checkOrigin("https://yourbatman.cn"); 30 | System.out.println("Access-Control-Allow-Origin的值为:" + checkedOrigin); 31 | } 32 | 33 | 34 | /** 35 | * allowedOriginPatterns使用示例 36 | */ 37 | @Test 38 | public void test1() { 39 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 40 | 41 | // 正常的模式匹配(字面量匹配就不演示了) 42 | corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("https://*.yourbatman.cn:[8080,8081]")); 43 | System.out.println("Access-Control-Allow-Origin的值为:" + corsConfiguration.checkOrigin("https://blog.yourbatman.cn:8081")); 44 | 45 | // 使用*进行通配,同时allowCredentials设置为true 46 | corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*")); 47 | corsConfiguration.setAllowCredentials(true); 48 | System.out.println("Access-Control-Allow-Origin的值为:" + corsConfiguration.checkOrigin("https://blog.yourbatman.cn:8081")); 49 | } 50 | 51 | @Test 52 | public void test2() { 53 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 54 | 55 | corsConfiguration.setAllowedOrigins(Collections.singletonList("*")); 56 | System.out.println("Access-Control-Allow-Origin的值为:" + corsConfiguration.checkOrigin("https://blog.yourbatman.cn:8081")); 57 | } 58 | 59 | @Test 60 | public void test3() { 61 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 62 | 63 | // 默认case:放行GET和HEAD 64 | System.out.println("allowedMethods的值为:" + corsConfiguration.getAllowedMethods()); 65 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.GET)); 66 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.POST)); 67 | } 68 | 69 | @Test 70 | public void test4() { 71 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 72 | 73 | // 手动明确指定只支持get(即使调用的是add方法),那就只支持GET喽 74 | corsConfiguration.setAllowedMethods(Collections.singletonList("GET")); 75 | System.out.println("allowedMethods的值为:" + corsConfiguration.getAllowedMethods()); 76 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.GET)); 77 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.HEAD)); 78 | 79 | 80 | corsConfiguration.addAllowedMethod("HEAD"); 81 | System.out.println("allowedMethods的值为:" + corsConfiguration.getAllowedMethods()); 82 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.GET)); 83 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.HEAD)); 84 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.POST)); 85 | 86 | // 当添加一个*号时 87 | corsConfiguration.addAllowedMethod(CorsConfiguration.ALL); 88 | System.out.println("allowedMethods的值为:" + corsConfiguration.getAllowedMethods()); 89 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.GET)); 90 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.HEAD)); 91 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.POST)); 92 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.PUT)); 93 | System.out.println(corsConfiguration.checkHttpMethod(HttpMethod.DELETE)); 94 | } 95 | 96 | @Test 97 | public void test5() { 98 | CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues(); 99 | 100 | corsConfiguration.setAllowedHeaders(Arrays.asList("Authorization", "YourBatman")); 101 | System.out.println(corsConfiguration.checkHeaders(Arrays.asList("Authorization", "YourBatman"))); 102 | System.out.println(corsConfiguration.checkHeaders(Arrays.asList("yourbatman", "Name"))); 103 | 104 | // 添加一个通配符* 105 | corsConfiguration.addAllowedHeader(CorsConfiguration.ALL); 106 | System.out.println(corsConfiguration.checkHeaders(Arrays.asList("Name", "Age"))); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/resources/static/cookie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cookie交互机制(同域) 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/resources/static/cors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CORS跨域请求 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 27 | 28 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/resources/static/corscookie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cookie交互机制(跨域) 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/resources/static/jsonp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JSONP跨域请求 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 28 | 29 | -------------------------------------------------------------------------------- /cors/cors-java/src/main/resources/static/multiple_origins_cors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 多Origin响应CORS跨域请求 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 21 | 22 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | cors 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | cors-spring-framework 12 | war 13 | 14 | 15 | 16 | org.springframework 17 | spring-webmvc 18 | 19 | 20 | jakarta.servlet 21 | jakarta.servlet-api 22 | provided 23 | 24 | 25 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/java/cn/yourbatman/cors/configuration/MyWebAppInitializer.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.configuration; 2 | 3 | import cn.yourbatman.cors.springframework.filter.CORSFilterV2; 4 | import org.springframework.web.cors.CorsConfiguration; 5 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 6 | 7 | import javax.servlet.DispatcherType; 8 | import javax.servlet.FilterRegistration; 9 | import javax.servlet.ServletContext; 10 | import javax.servlet.ServletException; 11 | import java.util.EnumSet; 12 | 13 | /** 14 | * 自己实现 基于注解驱动的ServletInitializer来初始化DispatcherServlet 15 | * 16 | * @author YourBatman. Send email to me 17 | * @site https://yourbatman.cn 18 | * @date 2021/5/19 15:52 19 | * @since 0.0.1 20 | */ 21 | public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 22 | 23 | /** 24 | * 根容器的配置类;(Spring的配置文件) 父容器; 25 | */ 26 | @Override 27 | protected Class[] getRootConfigClasses() { 28 | return new Class[]{RootConfiguration.class}; 29 | } 30 | 31 | /** 32 | * web容器的配置类(SpringMVC配置文件) 子容器; 33 | */ 34 | @Override 35 | protected Class[] getServletConfigClasses() { 36 | return new Class[]{WebMvcConfiguration.class}; 37 | } 38 | 39 | //获取DispatcherServlet的映射信息 40 | // 注意: /:拦截所有请求(包括静态资源(xx.js,xx.png)),但是不包括*.jsp; 41 | // /*:拦截所有请求;连*.jsp页面都拦截;jsp页面是tomcat的jsp引擎解析的; 42 | @Override 43 | protected String[] getServletMappings() { 44 | // return new String[]{"/"}; 45 | return new String[]{"/api/*"}; 46 | } 47 | 48 | @Override 49 | public void onStartup(ServletContext servletContext) throws ServletException { 50 | super.onStartup(servletContext); 51 | 52 | // 注册过滤器 53 | CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues(); 54 | FilterRegistration.Dynamic dynamic = servletContext.addFilter("corsFilter", new CORSFilterV2(corsConfiguration)); 55 | dynamic.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*"); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/java/cn/yourbatman/cors/configuration/RootConfiguration.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.configuration; 2 | 3 | import cn.yourbatman.cors.springframework.Application; 4 | import org.springframework.context.annotation.ComponentScan; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.FilterType; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.ControllerAdvice; 9 | 10 | /** 11 | * 在此处添加备注信息 12 | * 13 | * @author YourBatman. Send email to me 14 | * @site https://yourbatman.cn 15 | * @date 2021/5/19 15:41 16 | * @since 0.0.1 17 | */ 18 | // 备注:此处@ControllerAdvice、RestControllerAdvice 这个注解不要忘了,属于Controller层处理全局异常的,应该交给web去扫描 19 | @ComponentScan(basePackageClasses = {Application.class}, excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, ControllerAdvice.class}) 20 | }) 21 | @Configuration(proxyBeanMethods = false) 22 | public class RootConfiguration { 23 | 24 | } -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/java/cn/yourbatman/cors/configuration/WebMvcConfiguration.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.configuration; 2 | 3 | import cn.yourbatman.cors.springframework.Application; 4 | import org.springframework.context.annotation.ComponentScan; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.FilterType; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.ControllerAdvice; 9 | import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; 10 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 11 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 12 | import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; 13 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 14 | 15 | /** 16 | * 在此处添加备注信息 17 | * 18 | * @author YourBatman. Send email to me 19 | * @site https://yourbatman.cn 20 | * @date 2021/5/19 15:43 21 | * @since 0.0.1 22 | */ 23 | @EnableWebMvc 24 | @ComponentScan(basePackageClasses = {Application.class}, useDefaultFilters = false, includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, ControllerAdvice.class})}) 25 | @Configuration(proxyBeanMethods = false) 26 | public class WebMvcConfiguration implements WebMvcConfigurer { 27 | 28 | //视图解析器 29 | @Override 30 | public void configureViewResolvers(ViewResolverRegistry registry) { 31 | //默认所有的页面都从 /WEB-INF/ xxx .jsp 32 | //registry.jsp(); 33 | registry.jsp("/WEB-INF/views/", ".jsp"); 34 | } 35 | 36 | // 开启静态资源的请求转发到默认servlet上,不配置页面报错404,(默认servlet不是DispatcherServlet!理解的) 37 | @Override 38 | public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 39 | configurer.enable(); 40 | } 41 | 42 | //自定义添加拦截器=========这个比较常用 43 | @Override 44 | public void addInterceptors(InterceptorRegistry registry) { 45 | //registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**"); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/java/cn/yourbatman/cors/springframework/Application.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.springframework; 2 | 3 | public class Application { 4 | } 5 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/java/cn/yourbatman/cors/springframework/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.springframework.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * 在此处添加备注信息 8 | * 9 | * @author YourBatman. Send email to me 10 | * @site https://yourbatman.cn 11 | * @date 2021/6/18 15:21 12 | * @since 0.0.1 13 | */ 14 | @RestController 15 | class IndexController { 16 | 17 | @GetMapping("/index") 18 | Object index() { 19 | return "Hello Spring"; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/java/cn/yourbatman/cors/springframework/controller/UrlPathHelperController.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.springframework.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import org.springframework.web.util.UrlPathHelper; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | /** 12 | * 在此处添加备注信息 13 | * 14 | * @author YourBatman. Send email to me 15 | * @site https://yourbatman.cn 16 | * @date 2021/6/27 10:20 17 | * @since 0.0.1 18 | */ 19 | @RestController 20 | public class UrlPathHelperController { 21 | 22 | @Autowired 23 | private HttpServletRequest request; 24 | private UrlPathHelper urlPathHelper = new UrlPathHelper(); 25 | 26 | @GetMapping("/demo1") 27 | Object demo1(@RequestParam String name) { 28 | requestPrint(); 29 | urlPathHelperPrint(); 30 | 31 | return "hello " + name; 32 | } 33 | 34 | 35 | 36 | private void requestPrint(){ 37 | String contextPath = request.getContextPath(); 38 | String servletPath = request.getServletPath(); 39 | StringBuffer requestURL = request.getRequestURL(); 40 | String requestURI = request.getRequestURI(); 41 | 42 | System.out.println("request contextPath:" + contextPath); 43 | System.out.println("request servletPath:" + servletPath); 44 | System.out.println("request requestURL:" + requestURL); 45 | System.out.println("request requestURI:" + requestURI); 46 | } 47 | 48 | private void urlPathHelperPrint(){ 49 | String contextPath = urlPathHelper.getContextPath(request); 50 | String servletPath = urlPathHelper.getServletPath(request); 51 | String requestUri = urlPathHelper.getRequestUri(request); 52 | 53 | 54 | System.out.println("urlPathHelper contextPath:" + contextPath); 55 | System.out.println("urlPathHelper servletPath:" + servletPath); 56 | System.out.println("urlPathHelper requestURL:" + requestUri); 57 | } 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/java/cn/yourbatman/cors/springframework/filter/CORSFilterV2.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.cors.springframework.filter; 2 | 3 | import org.springframework.http.HttpHeaders; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.cors.CorsConfiguration; 6 | import org.springframework.web.cors.CorsUtils; 7 | 8 | import javax.servlet.Filter; 9 | import javax.servlet.FilterChain; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | 17 | /** 18 | * 基于{@link CorsConfiguration} 实现 19 | * 20 | * @author YourBatman. Send email to me 21 | * @site https://yourbatman.cn 22 | * @date 2021/6/14 09:50 23 | * @since 0.0.1 24 | * @see CorsConfiguration 25 | */ 26 | public class CORSFilterV2 implements Filter { 27 | 28 | private CorsConfiguration corsConfiguration; 29 | 30 | public CORSFilterV2(CorsConfiguration corsConfiguration) { 31 | this.corsConfiguration = corsConfiguration; 32 | } 33 | 34 | @Override 35 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 36 | HttpServletRequest req = (HttpServletRequest) request; 37 | HttpServletResponse resp = (HttpServletResponse) response; 38 | 39 | boolean isValid = process(corsConfiguration, req, resp); 40 | // Cors跨域不通过,拦截掉 41 | if (!isValid) { 42 | return; 43 | } 44 | // 如果是预检请求,即使通过了也不让继续往下走了(注:此方法必须放在process()后面,因为响应头得设置好) 45 | if (CorsUtils.isPreFlightRequest(req)) { 46 | return; 47 | } 48 | 49 | chain.doFilter(request, response); 50 | } 51 | 52 | /** 53 | * 判断该请求是否匹配Cors跨域规则,并且设置好响应头 54 | */ 55 | private boolean process(CorsConfiguration corsConfiguration, HttpServletRequest request, HttpServletResponse response) throws IOException { 56 | // 若此请求不是跨域请求,那请回 57 | if (!CorsUtils.isCorsRequest(request)) { 58 | return true; 59 | } 60 | boolean isRreFlightRequest = CorsUtils.isPreFlightRequest(request); 61 | 62 | // 若此请求你自己已经设置过Access-Control-Allow-Origin,那我也不再处理了 63 | if (response.getHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN) != null) { 64 | return true; 65 | } 66 | 67 | // 若没配置Cors策略,那也什么都不能做 68 | if (corsConfiguration == null) { 69 | if (isRreFlightRequest) { //预检请求进来了,但是你又没有配置跨域方案,那肯定拒绝啦 70 | rejectRequest(response); 71 | return false; 72 | } 73 | return true; // 正常请求进来,没配置跨域方案,那就当此过滤器是空气就好 74 | } 75 | 76 | 77 | // =======配置了跨域方案的校验====== 78 | String requestOrigin = request.getHeader(HttpHeaders.ORIGIN); 79 | String checkOrigin = corsConfiguration.checkOrigin(requestOrigin); 80 | if (checkOrigin == null) { 81 | rejectRequest(response); 82 | return false; 83 | } 84 | 85 | // ...检查Methods、检查Headers等等 86 | 87 | // ============开始设置响应头============= 88 | response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, checkOrigin); 89 | // if (isRreFlightRequest) { 90 | // response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, allowMethods); 91 | // } 92 | // if (corsConfiguration.getAllowCredentials() == true) { 93 | // response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); 94 | // } 95 | // if (isRreFlightRequest && corsConfiguration.getMaxAge() != null) { 96 | // response.addHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, corsConfiguration.getMaxAge()); 97 | // } 98 | return true; 99 | } 100 | 101 | 102 | protected void rejectRequest(HttpServletResponse response) throws IOException { 103 | response.setStatus(HttpStatus.FORBIDDEN.value()); 104 | response.getWriter().write("Invalid CORS request"); 105 | response.flushBuffer(); 106 | } 107 | 108 | 109 | } -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /cors/cors-spring-framework/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CORS跨域请求 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /cors/cors-springboot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | cors 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | cors-springboot 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | -------------------------------------------------------------------------------- /cors/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tech-column-learning 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | pom 12 | cn.yourbatman 13 | cors 14 | 15 | 16 | cors-java 17 | cors-spring-framework 18 | cors-springboot 19 | 20 | 21 | -------------------------------------------------------------------------------- /foundation/foundation-java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | foundation 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | war 12 | foundation-java 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | jakarta.servlet 22 | jakarta.servlet-api 23 | provided 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /foundation/foundation-java/src/main/java/cn/yourbatman/foundation/java/WebUtils.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.foundation.java; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | /** 6 | * Web工具方法 7 | * 8 | * @author YourBatman. Send email to me 9 | * @site https://yourbatman.cn 10 | * @date 2021/6/27 11:03 11 | * @since 0.0.1 12 | */ 13 | public abstract class WebUtils { 14 | 15 | /** 16 | * 打印{@link HttpServletRequest}的路径信息 17 | */ 18 | public static void printRequestPath(HttpServletRequest request) { 19 | String contextPath = request.getContextPath(); 20 | String servletPath = request.getServletPath(); 21 | String pathInfo = request.getPathInfo(); 22 | String requestURI = request.getRequestURI(); 23 | 24 | System.out.println("request contextPath:" + contextPath); 25 | System.out.println("request servletPath:" + servletPath); 26 | System.out.println("request pathInfo:" + pathInfo); 27 | System.out.println("request requestURI:" + requestURI); 28 | 29 | System.out.println("request requestURL(用得很少):" + request.getRequestURL()); 30 | System.out.println("---------------------------"); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /foundation/foundation-java/src/main/java/cn/yourbatman/foundation/java/filter/FakeFilter.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.foundation.java.filter; 2 | 3 | import javax.servlet.FilterChain; 4 | import javax.servlet.ServletException; 5 | import javax.servlet.annotation.WebFilter; 6 | import javax.servlet.http.HttpFilter; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | 11 | /** 12 | * 在此处添加备注信息 13 | * 14 | * @author YourBatman. Send email to me 15 | * @site https://yourbatman.cn 16 | * @date 2021/6/27 17:38 17 | * @since 0.0.1 18 | */ 19 | // @WebFilter(urlPatterns = {"/"}) // Filter使用/无效果,拦截所有只能使用/* 20 | // @WebFilter(urlPatterns = {"/*"}) 21 | public class FakeFilter extends HttpFilter { 22 | 23 | @Override 24 | protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { 25 | System.out.println("FakeFilter收到请求:" + req.getRequestURI()); 26 | super.doFilter(req, res, chain); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /foundation/foundation-java/src/main/java/cn/yourbatman/foundation/java/servlet/Demo1Servlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.foundation.java.servlet; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | import static cn.yourbatman.foundation.java.WebUtils.printRequestPath; 10 | 11 | /** 12 | * 在此处添加备注信息 13 | * 14 | * @author YourBatman. Send email to me 15 | * @site https://yourbatman.cn 16 | * @date 2021/6/27 12:25 17 | * @since 0.0.1 18 | */ 19 | // @WebServlet(urlPatterns = {"/api/demo1", "/api/demo2"}) // 精确匹配 20 | // @WebServlet(urlPatterns = {"/api/*", "/*"}) // 路径匹配 21 | // @WebServlet(urlPatterns = {"*.jsp", "*.*"}) // 后缀匹配 22 | // @WebServlet(urlPatterns = "/") // 缺省匹配 23 | public class Demo1Servlet extends HttpServlet { 24 | 25 | @Override 26 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 27 | printRequestPath(req); 28 | resp.getWriter().write("hello " + req.getParameter("name")); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /foundation/foundation-java/src/main/java/cn/yourbatman/foundation/java/servlet/Fake1Servlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.foundation.java.servlet; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.annotation.WebServlet; 5 | import javax.servlet.http.HttpServlet; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | /** 11 | * 举例证明错误言论 12 | * 13 | * @author YourBatman. Send email to me 14 | * @site https://yourbatman.cn 15 | * @date 2021/6/27 17:30 16 | * @since 0.0.1 17 | */ 18 | // @WebServlet(urlPatterns = {"/*"}) 19 | public class Fake1Servlet extends HttpServlet { 20 | 21 | @Override 22 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 23 | System.out.println("Fake1Servlet收到请求:" + req.getRequestURI()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /foundation/foundation-java/src/main/java/cn/yourbatman/foundation/java/servlet/FakeServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.foundation.java.servlet; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | /** 10 | * 举例证明错误言论 11 | * 12 | * @author YourBatman. Send email to me 13 | * @site https://yourbatman.cn 14 | * @date 2021/6/27 17:30 15 | * @since 0.0.1 16 | */ 17 | // @WebServlet(urlPatterns = {"/*"}) 18 | // @WebServlet(urlPatterns = {"/"}) 19 | public class FakeServlet extends HttpServlet { 20 | 21 | @Override 22 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 23 | System.out.println("FakeServlet收到请求:" + req.getRequestURI()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /foundation/foundation-java/src/main/java/cn/yourbatman/foundation/java/servlet/UrlPatternDemoServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.foundation.java.servlet; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.annotation.WebServlet; 5 | import javax.servlet.http.HttpServlet; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | /** 11 | * 在此处添加备注信息 12 | * 13 | * @author YourBatman. Send email to me 14 | * @site https://yourbatman.cn 15 | * @date 2021/6/27 12:25 16 | * @since 0.0.1 17 | */ 18 | // @WebServlet(urlPatterns = {"/api/demo1", "/api/demo2"}) // 精确匹配 19 | // @WebServlet(urlPatterns = {"*.jsp", "*.*"}) // 后缀匹配 20 | // @WebServlet(urlPatterns = {"/api/*", "/*"}) // 路径匹配 21 | @WebServlet(urlPatterns = "/") // 缺省匹配 22 | // @WebServlet(urlPatterns = "/api/*.jsp") // 启动报错 23 | public class UrlPatternDemoServlet extends HttpServlet { 24 | @Override 25 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 26 | System.out.printf("收到请求:%s ServletPath:%s PathInfo:%s\n", req.getRequestURI(), req.getServletPath(), req.getPathInfo()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /foundation/foundation-spring-framework/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | foundation 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | foundation-spring-framework 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | -------------------------------------------------------------------------------- /foundation/foundation-springboot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | foundation 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | foundation-springboot 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | -------------------------------------------------------------------------------- /foundation/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tech-column-learning 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | foundation 12 | pom 13 | 14 | foundation-java 15 | foundation-spring-framework 16 | foundation-springboot 17 | 18 | 19 | 20 | 8 21 | 8 22 | 23 | 24 | -------------------------------------------------------------------------------- /javaee/javaee-el/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | javaee 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | javaee-el 13 | 14 | 15 | 8 16 | 8 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 | org.apache.tomcat.embed 42 | tomcat-embed-el 43 | 44 | 45 | 46 | javax.servlet.jsp.jstl 47 | jstl-api 48 | 1.2 49 | 50 | 51 | -------------------------------------------------------------------------------- /javaee/javaee-el/src/main/java/cn/yourbatman/javaee/el/Demo.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.javaee.el; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import javax.el.ELManager; 6 | import javax.el.ExpressionFactory; 7 | import javax.el.MethodExpression; 8 | import javax.el.StandardELContext; 9 | import javax.el.ValueExpression; 10 | 11 | /** 12 | * 在此处添加备注信息 13 | * 14 | * @author YourBatman. Send email to me 15 | * @site https://yourbatman.cn 16 | * @date 2021/7/4 10:52 17 | * @since 0.0.1 18 | */ 19 | public class Demo { 20 | 21 | @Test 22 | public void test1() { 23 | ExpressionFactory factory = ELManager.getExpressionFactory(); 24 | StandardELContext elContext = new StandardELContext(factory); 25 | 26 | // 将instance转为对应类型 27 | ValueExpression valueExpression = factory.createValueExpression("18", Integer.class); 28 | System.out.println(valueExpression.getValue(elContext)); 29 | 30 | // 计算表达式的值 31 | valueExpression = factory.createValueExpression(elContext, "${1+1}", Integer.class); 32 | System.out.println(valueExpression.getValue(elContext)); 33 | 34 | // 方法调用 35 | // MethodExpression methodExpression = factory.createMethodExpression(elContext, "${Math.addExact()}", Integer.class, new Class[]{Integer.class, Integer.class}); 36 | // System.out.println(methodExpression.invoke(elContext, new Object[]{1, 2})); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /javaee/javaee-jaxrs/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | javaee 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | war 12 | 13 | javaee-jaxrs 14 | 15 | 16 | 8 17 | 8 18 | 19 | 20 | -------------------------------------------------------------------------------- /javaee/javaee-jsonb/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | javaee 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | javaee-jsonb 12 | 13 | 14 | 8 15 | 8 16 | 17 | 18 | 19 | 20 | javax.json.bind 21 | javax.json.bind-api 22 | 1.0 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /javaee/javaee-jsonb/src/main/java/cn/yourbatman/javaee/jsonb/Demo.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.javaee.jsonb; 2 | 3 | import javax.json.bind.Jsonb; 4 | import javax.json.bind.JsonbBuilder; 5 | 6 | /** 7 | * 在此处添加备注信息 8 | * 9 | * @author YourBatman. Send email to me 10 | * @site https://yourbatman.cn 11 | * @date 2021/7/4 18:51 12 | * @since 0.0.1 13 | */ 14 | public class Demo { 15 | 16 | public static void main(String[] args) { 17 | Person p = new Person(); 18 | p.setName("YourBatman"); 19 | p.setAge(18); 20 | 21 | Jsonb jsonb = JsonbBuilder.create(); 22 | String json = jsonb.toJson(p); 23 | System.out.println("序列化结果:" + json); 24 | 25 | // 反序列化 26 | System.out.println(jsonb.fromJson(json, Person.class)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /javaee/javaee-jsonb/src/main/java/cn/yourbatman/javaee/jsonb/Person.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.javaee.jsonb; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 在此处添加备注信息 7 | * 8 | * @author YourBatman. Send email to me 9 | * @site https://yourbatman.cn 10 | * @date 2021/7/4 19:05 11 | * @since 0.0.1 12 | */ 13 | @Data 14 | public class Person { 15 | 16 | private String name; 17 | private Integer age; 18 | 19 | } -------------------------------------------------------------------------------- /javaee/javaee-servlet/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | javaee 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | war 12 | javaee-servlet 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | jakarta.servlet 22 | jakarta.servlet-api 23 | provided 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /javaee/javaee-servlet/src/main/java/cn/yourbatman/javaee/servlet/HelloServlet.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.javaee.servlet; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.annotation.WebServlet; 5 | import javax.servlet.http.HttpServlet; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | /** 11 | * 在此处添加备注信息 12 | * 13 | * @author YourBatman. Send email to me 14 | * @site https://yourbatman.cn 15 | * @date 2021/7/3 15:24 16 | * @since 0.0.1 17 | */ 18 | @WebServlet(urlPatterns = {"/hello"}) 19 | public class HelloServlet extends HttpServlet { 20 | 21 | @Override 22 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 23 | resp.getWriter().write("hello servlet..."); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /javaee/javaee-servlet/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /javaee/javaee-servlet/src/main/webapp/hello.jsp: -------------------------------------------------------------------------------- 1 | <%@ page import="java.util.Date" pageEncoding="utf-8" %> 2 | 3 | JSP示例页面 4 | 5 | <%--可用书写Java代码--%> 6 |

今天的日期是:<%= new Date() %> 7 |

8 | 9 | -------------------------------------------------------------------------------- /javaee/javaee-websocket/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | javaee 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | war 12 | javaee-websocket 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | javax.websocket 22 | javax.websocket-api 23 | provided 24 | 25 | 26 | org.eclipse.jetty.websocket 27 | javax-websocket-client-impl 28 | 9.4.42.v20210604 29 | 30 | 31 | -------------------------------------------------------------------------------- /javaee/javaee-websocket/src/main/java/cn/yourbatman/javaee/websocket/App.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.javaee.websocket; 2 | 3 | import javax.websocket.ContainerProvider; 4 | import javax.websocket.DeploymentException; 5 | import javax.websocket.Session; 6 | import javax.websocket.WebSocketContainer; 7 | import java.io.IOException; 8 | import java.net.URI; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | /** 12 | * 用Main方法启动WebSocket的客户端,去连接服务端 13 | * 14 | * @author YourBatman. Send email to me 15 | * @site https://yourbatman.cn 16 | * @date 2021/7/4 16:35 17 | * @since 0.0.1 18 | */ 19 | public class App { 20 | 21 | private static URI uri = URI.create("ws://localhost:8080/websocket/chat"); 22 | private static Session session; 23 | 24 | public static void main(String[] args) throws DeploymentException, IOException, InterruptedException { 25 | WebSocketContainer container = ContainerProvider.getWebSocketContainer(); 26 | 27 | // 顺序执行5次会话,端口后再建立新会话 28 | for (int i = 0; i < 3; i++) { 29 | session = container.connectToServer(WsClient.class, uri); 30 | session.close(); 31 | TimeUnit.SECONDS.sleep(2); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /javaee/javaee-websocket/src/main/java/cn/yourbatman/javaee/websocket/WsClient.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.javaee.websocket; 2 | 3 | import javax.websocket.ClientEndpoint; 4 | import javax.websocket.OnClose; 5 | import javax.websocket.OnMessage; 6 | import javax.websocket.OnOpen; 7 | import javax.websocket.Session; 8 | import java.io.IOException; 9 | 10 | /** 11 | * 在此处添加备注信息 12 | * 13 | * @author YourBatman. Send email to me 14 | * @site https://yourbatman.cn 15 | * @date 2021/7/4 16:29 16 | * @since 0.0.1 17 | */ 18 | @ClientEndpoint 19 | public class WsClient { 20 | 21 | // 会话(与服务端建立的会话) 22 | private Session session; 23 | 24 | /** 25 | * 建连成功的回调 26 | */ 27 | @OnOpen 28 | public void onOpen(Session session) throws IOException { 29 | this.session = session; 30 | System.out.println("Client连接到服务端成功,会话ID:" + session.getId()); 31 | sendMessage("这是一条来自Client端,会话["+session.getId()+"]的消息"); 32 | } 33 | 34 | @OnMessage 35 | public void onMessage(String message) { 36 | System.out.println("Client端收到消息: " + message); 37 | } 38 | 39 | @OnClose 40 | public void onClose() { 41 | System.out.println("Client会话" + session.getId() + "已断开"); 42 | } 43 | 44 | /** 45 | * 发送消息 46 | */ 47 | public void sendMessage(String message) throws IOException { 48 | this.session.getBasicRemote().sendText(message); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /javaee/javaee-websocket/src/main/java/cn/yourbatman/javaee/websocket/WsServer.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.javaee.websocket; 2 | 3 | import javax.websocket.OnClose; 4 | import javax.websocket.OnError; 5 | import javax.websocket.OnMessage; 6 | import javax.websocket.OnOpen; 7 | import javax.websocket.Session; 8 | import javax.websocket.server.ServerEndpoint; 9 | import java.io.IOException; 10 | import java.util.Set; 11 | import java.util.concurrent.CopyOnWriteArraySet; 12 | 13 | /** 14 | * 在此处添加备注信息 15 | * 16 | * @author YourBatman. Send email to me 17 | * @site https://yourbatman.cn 18 | * @date 2021/7/4 16:17 19 | * @since 0.0.1 20 | */ 21 | @ServerEndpoint("/websocket/chat") 22 | public class WsServer { 23 | 24 | 25 | // 当前连接上来的连接们(每一个连接都是一个WsServerDemo实例,包含一个Session会话) 26 | private static Set webSocketSet = new CopyOnWriteArraySet<>(); 27 | // 会话 28 | private Session session; 29 | 30 | /** 31 | * 建连成功的回调 32 | */ 33 | @OnOpen 34 | public void onOpen(Session session) { 35 | this.session = session; 36 | webSocketSet.add(this); // 保存当前连接 37 | System.out.println("Server有新连接加入!当前在线人数为" + webSocketSet.size()); 38 | } 39 | 40 | /** 41 | * 连接关闭调用的方法 42 | */ 43 | @OnClose 44 | public void onClose() { 45 | webSocketSet.remove(this); 46 | System.out.println("Server有一连接关闭!当前在线人数为" + webSocketSet.size()); 47 | } 48 | 49 | /** 50 | * 收到客户端消息后调用的方法 51 | */ 52 | @OnMessage 53 | public void onMessage(String message) throws IOException { 54 | System.out.println("Server来自客户端的消息:" + message); 55 | sendMessage("会话[" + session.getId() + "]的消息已经收到,内容为:" + message); 56 | // // =======群发消息========= 57 | // for (WsServerDemo item : webSocketSet) { 58 | // try { 59 | // item.sendMessage(message); 60 | // } catch (IOException e) { 61 | // continue; 62 | // } 63 | // } 64 | } 65 | 66 | /** 67 | * 发生错误时调用 68 | */ 69 | @OnError 70 | public void onError(Throwable error) { 71 | System.out.println("Server发生错误:" + error.getMessage()); 72 | } 73 | 74 | /** 75 | * 发送消息 76 | */ 77 | public void sendMessage(String message) throws IOException { 78 | this.session.getBasicRemote().sendText(message); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /javaee/javaee-websocket/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /javaee/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tech-column-learning 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | pom 12 | 13 | javaee-jaxrs 14 | javaee-servlet 15 | javaee-el 16 | javaee-websocket 17 | javaee-jsonb 18 | 19 | javaee 20 | 21 | 22 | 8 23 | 8 24 | 25 | 26 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.yourbatman 8 | tech-column-learning 9 | 1.0-SNAPSHOT 10 | 11 | cors 12 | spring5 13 | foundation 14 | javaee 15 | basicskill 16 | 17 | pom 18 | 19 | 20 | 8 21 | 8 22 | 2.7.0 23 | 24 | 25 | 26 | BAT的乌托邦 27 | https://yourbatman.cn 28 | 29 | 30 | 31 | YourBatman 32 | yourbatman@aliyun.com 33 | https://yourbatman.cn 34 | +8 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-dependencies 44 | ${spring-boot-dependencies} 45 | pom 46 | import 47 | 48 | 49 | commons-io 50 | commons-io 51 | 2.11.0 52 | 53 | 54 | org.apache.commons 55 | commons-lang3 56 | 3.12.0 57 | 58 | 59 | 60 | 61 | 62 | 63 | ch.qos.logback 64 | logback-classic 65 | 66 | 67 | org.springframework 68 | spring-core 69 | 70 | 71 | org.springframework 72 | spring-test 73 | test 74 | 75 | 76 | org.junit.jupiter 77 | junit-jupiter-api 78 | 79 | 80 | org.projectlombok 81 | lombok 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-war-plugin 91 | 3.3.1 92 | 93 | false 94 | 95 | 96 | 97 | org.apache.maven.plugins 98 | maven-compiler-plugin 99 | 3.8.1 100 | 101 | 102 | 108 | 109 | 110 | src/main/java 111 | 112 | **/*.properties 113 | **/*.xml 114 | **/*.tld 115 | 116 | false 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /spring5/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | tech-column-learning 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | spring5 12 | pom 13 | 这是针对Spring 5提供的一些特殊新功能的工程 14 | 15 | spring5-java 16 | 17 | 18 | 19 | 8 20 | 8 21 | 22 | 23 | 24 | 25 | org.springframework 26 | spring-core 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /spring5/spring5-java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | spring5 7 | cn.yourbatman 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | spring5-java 13 | 14 | 15 | 8 16 | 8 17 | 18 | 19 | 20 | 21 | org.springframework 22 | spring-webmvc 23 | 24 | 25 | -------------------------------------------------------------------------------- /spring5/spring5-java/src/main/java/cn/yourbatman/spring5/java/antpathmatcher/Demo1.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.spring5.java.antpathmatcher; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.util.AntPathMatcher; 5 | import org.springframework.util.PathMatcher; 6 | 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.Comparator; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | /** 14 | * 在此处添加备注信息 15 | * 16 | * @author YourBatman. Send email to me 17 | * @site https://yourbatman.cn 18 | * @date 2021/6/18 18:01 19 | * @since 0.0.1 20 | * @see AntPathMatcher 21 | */ 22 | // @ComponentScan(basePackages = "cn.yourbatman.**.controller") 23 | public class Demo1 { 24 | 25 | private static final PathMatcher MATCHER = new AntPathMatcher(); 26 | 27 | @Test 28 | public void test1() { 29 | System.out.println("=======?:匹配任意单字符======="); 30 | String pattern = "/api/your?atman"; 31 | 32 | match(1, MATCHER, pattern, "/api/youratman"); 33 | match(2, MATCHER, pattern, "/api/yourBatman"); 34 | match(3, MATCHER, pattern, "/api/yourBatman/address"); 35 | match(4, MATCHER, pattern, "/api/yourBBBatman"); 36 | } 37 | 38 | @Test 39 | public void test2() { 40 | System.out.println("=======*:匹配任意数量的字符======="); 41 | String pattern = "/api/*/yourbatman"; 42 | 43 | match(1, MATCHER, pattern, "/api//yourbatman"); 44 | match(2, MATCHER, pattern, "/api/ /yourbatman"); 45 | match(3, MATCHER, pattern, "/api/yourbatman"); 46 | match(4, MATCHER, pattern, "/api/v1v2v3/yourbatman"); 47 | } 48 | 49 | @Test 50 | public void test3() { 51 | System.out.println("=======**:匹配任意层级的路径/目录======="); 52 | String pattern = "/api/yourbatman/**"; 53 | 54 | 55 | match(1, MATCHER, pattern, "/api/yourbatman"); 56 | match(2, MATCHER, pattern, "/api/yourbatman/"); 57 | match(3, MATCHER, pattern, "/api/yourbatman/address"); 58 | match(4, MATCHER, pattern, "/api/yourbatman/a/b/c"); 59 | } 60 | 61 | @Test 62 | public void test4() { 63 | System.out.println("=======**:匹配任意层级的路径/目录======="); 64 | String pattern = "/api/**/yourbatman"; 65 | 66 | match(1, MATCHER, pattern, "/api/yourbatman"); 67 | match(2, MATCHER, pattern, "/api//yourbatman"); 68 | match(3, MATCHER, pattern, "/api/a/b/c/yourbatman"); 69 | } 70 | 71 | @Test 72 | public void test5() { 73 | System.out.println("======={pathVariable:可选的正则表达式}======="); 74 | String pattern = "/api/yourbatman/{age}"; 75 | 76 | match(1, MATCHER, pattern, "/api/yourbatman/10"); 77 | match(2, MATCHER, pattern, "/api/yourbatman/Ten"); 78 | 79 | // 打印提取到的内容 80 | extractUriTemplateVariables(MATCHER, pattern, "/api/yourbatman/10"); 81 | extractUriTemplateVariables(MATCHER, pattern, "/api/yourbatman/Ten"); 82 | } 83 | 84 | @Test 85 | public void test6() { 86 | System.out.println("======={pathVariable:可选的正则表达式}======="); 87 | String pattern = "/api/yourbatman/{age:[0-9]*}"; 88 | 89 | match(1, MATCHER, pattern, "/api/yourbatman/10"); 90 | match(2, MATCHER, pattern, "/api/yourbatman/Ten"); 91 | 92 | // 打印提取到的内容 93 | extractUriTemplateVariables(MATCHER, pattern, "/api/yourbatman/10"); 94 | extractUriTemplateVariables(MATCHER, pattern, "/api/yourbatman/Ten"); 95 | } 96 | 97 | @Test 98 | public void test7() { 99 | System.out.println("=======isPattern方法======="); 100 | 101 | System.out.println(MATCHER.isPattern("/api/yourbatman")); 102 | System.out.println(MATCHER.isPattern("/api/your?atman")); 103 | System.out.println(MATCHER.isPattern("/api/*/yourBatman")); 104 | System.out.println(MATCHER.isPattern("/api/yourBatman/**")); 105 | } 106 | 107 | @Test 108 | public void test8() { 109 | System.out.println("=======matchStart方法======="); 110 | String pattern = "/api/?"; 111 | 112 | System.out.println("match方法结果:" + MATCHER.match(pattern, "/api/y")); 113 | System.out.println("match方法结果:" + MATCHER.match(pattern, "/api//")); 114 | System.out.println("match方法结果:" + MATCHER.match(pattern, "/api////")); 115 | System.out.println("matchStart方法结果:" + MATCHER.matchStart(pattern, "/api//")); 116 | System.out.println("matchStart方法结果:" + MATCHER.matchStart(pattern, "/api////")); 117 | System.out.println("matchStart方法结果:" + MATCHER.matchStart(pattern, "/api///a/")); 118 | } 119 | 120 | @Test 121 | public void test9() { 122 | System.out.println("=======extractPathWithinPattern方法======="); 123 | String pattern = "/api/*.html"; 124 | 125 | System.out.println("是否匹配成功:" + MATCHER.match(pattern, "/api/yourbatman/address") 126 | + ",提取结果:" + MATCHER.extractPathWithinPattern(pattern, "/api/yourbatman/address")); 127 | System.out.println("是否匹配成功:" + MATCHER.match(pattern, "/api/index.html") 128 | + ",提取结果:" + MATCHER.extractPathWithinPattern(pattern, "/api/index.html")); 129 | } 130 | 131 | @Test 132 | public void test10() { 133 | System.out.println("=======extractPathWithinPattern方法======="); 134 | String pattern = "/api/**/yourbatman/*.html/temp"; 135 | 136 | System.out.println("是否匹配成功:" + MATCHER.match(pattern, "/api/yourbatman/address") 137 | + ",提取结果:" + MATCHER.extractPathWithinPattern(pattern, "/api/yourbatman/address")); 138 | System.out.println("是否匹配成功:" + MATCHER.match(pattern, "/api/yourbatman/index.html/temp") 139 | + ",提取结果:" + MATCHER.extractPathWithinPattern(pattern, "/api/yourbatman/index.html/temp")); 140 | } 141 | 142 | @Test 143 | public void test11() { 144 | System.out.println("=======getPatternComparator方法======="); 145 | 146 | List patterns = Arrays.asList( 147 | "/api/**/index.html", 148 | "/api/yourbatman/*.html", 149 | "/api/**/*.html", 150 | "/api/yourbatman/index.html" 151 | ); 152 | System.out.println("排序前:" + patterns); 153 | 154 | Comparator patternComparator = MATCHER.getPatternComparator("/api/yourbatman/index.html"); 155 | Collections.sort(patterns, patternComparator); 156 | System.out.println("排序后:" + patterns); 157 | } 158 | 159 | private static void match(int index, PathMatcher matcher, String pattern, String reqPath) { 160 | boolean match = matcher.match(pattern, reqPath); 161 | System.out.println(index + "\tmatch结果:" + pattern + "\t" + (match ? "【成功】" : "【失败】") + "\t" + reqPath); 162 | } 163 | 164 | private static void extractUriTemplateVariables(PathMatcher matcher, String pattern, String reqPath) { 165 | Map variablesMap = matcher.extractUriTemplateVariables(pattern, reqPath); 166 | System.out.println("extractUriTemplateVariables结果:" + variablesMap + "\t" + pattern + "\t" + reqPath); 167 | } 168 | 169 | 170 | } 171 | -------------------------------------------------------------------------------- /spring5/spring5-java/src/main/java/cn/yourbatman/spring5/java/pathpattern/CompareDemo.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.spring5.java.pathpattern; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.http.server.PathContainer; 5 | import org.springframework.util.AntPathMatcher; 6 | import org.springframework.util.PathMatcher; 7 | import org.springframework.web.util.pattern.PathPattern; 8 | import org.springframework.web.util.pattern.PathPatternParser; 9 | 10 | import java.time.Duration; 11 | import java.time.Instant; 12 | 13 | /** 14 | * 在此处添加备注信息 15 | * 16 | * @author YourBatman. Send email to me 17 | * @site https://yourbatman.cn 18 | * @date 2021/6/20 17:25 19 | * @since 0.0.1 20 | */ 21 | public class CompareDemo { 22 | 23 | 24 | private static final String pattern = "/api/your?atman/{age}/**"; 25 | 26 | @Test 27 | public void test1() { 28 | Instant start = Instant.now(); 29 | for (int i = 0; i < 10000000; i++) { 30 | String reqPath = "/api/yourBatman/" + i + "/" + i; 31 | // antPathMatcher(reqPath); 32 | pathPattern(reqPath); 33 | } 34 | System.out.println("耗时(ms):" + Duration.between(start, Instant.now()).toMillis()); 35 | } 36 | 37 | 38 | private static final PathMatcher MATCHER = new AntPathMatcher(); 39 | 40 | public static void antPathMatcher(String reqPath) { 41 | MATCHER.match(pattern, reqPath); 42 | } 43 | 44 | private static final PathPattern PATTERN = PathPatternParser.defaultInstance.parse(pattern); 45 | 46 | public static void pathPattern(String reqPath) { 47 | PATTERN.matches(PathContainer.parsePath(reqPath)); 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /spring5/spring5-java/src/main/java/cn/yourbatman/spring5/java/pathpattern/Demo1.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.spring5.java.pathpattern; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.http.server.PathContainer; 5 | import org.springframework.web.util.pattern.PathPattern; 6 | import org.springframework.web.util.pattern.PathPatternParser; 7 | 8 | /** 9 | * 在此处添加备注信息 10 | * 11 | * @author YourBatman. Send email to me 12 | * @site https://yourbatman.cn 13 | * @date 2021/6/20 09:47 14 | * @since 0.0.1 15 | */ 16 | public class Demo1 { 17 | 18 | /** 19 | * 将pattern字符串的每一段都解析为element,用链状形式连接起来 20 | */ 21 | @Test 22 | public void test1() { 23 | PathPatternParser parser = new PathPatternParser(); 24 | PathPattern pathPattern = parser.parse("/api/v1/**"); 25 | System.out.println(pathPattern); 26 | } 27 | 28 | @Test 29 | public void test2() { 30 | PathContainer pathContainer = PathContainer.parsePath("/api/v1/address", PathContainer.Options.HTTP_PATH); 31 | System.out.println(pathContainer); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /spring5/spring5-java/src/main/java/cn/yourbatman/spring5/java/pathpattern/Demo2.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.spring5.java.pathpattern; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.http.server.PathContainer; 5 | import org.springframework.util.AntPathMatcher; 6 | import org.springframework.web.util.pattern.PathPattern; 7 | import org.springframework.web.util.pattern.PathPatternParser; 8 | 9 | import java.util.SortedSet; 10 | import java.util.TreeSet; 11 | 12 | /** 13 | * {@link PathPattern} 是Spring 5推出的用于取代{@link AntPathMatcher}的路径匹配神器。前者性能更强 14 | * 15 | * @author YourBatman. Send email to me 16 | * @site https://yourbatman.cn 17 | * @date 2021/6/18 17:01 18 | * @since 0.0.1 19 | * @see PathPattern 20 | * @see PathPatternParser 21 | */ 22 | public class Demo2 { 23 | 24 | @Test 25 | public void test1() { 26 | System.out.println("======={*pathVariable}语法======"); 27 | PathPattern pattern = PathPatternParser.defaultInstance.parse("/api/yourbatman/{*pathVariable}"); 28 | 29 | 30 | // 提取匹配到的的变量值 31 | System.out.println("是否匹配:" + pattern.matches(PathContainer.parsePath("/api/yourbatman/a/b/c"))); 32 | PathPattern.PathMatchInfo pathMatchInfo = pattern.matchAndExtract(PathContainer.parsePath("/api/yourbatman/a/b/c")); 33 | System.out.println("匹配到的值情况:" + pathMatchInfo.getUriVariables()); 34 | } 35 | 36 | @Test 37 | public void test2() { 38 | System.out.println("======={*pathVariable}和/**优先级======"); 39 | PathPattern pattern1 = PathPatternParser.defaultInstance.parse("/api/yourbatman/{*pathVariable}"); 40 | PathPattern pattern2 = PathPatternParser.defaultInstance.parse("/api/yourbatman/**"); 41 | 42 | SortedSet sortedSet = new TreeSet<>(); 43 | sortedSet.add(pattern1); 44 | sortedSet.add(pattern2); 45 | 46 | System.out.println(sortedSet); 47 | } 48 | 49 | 50 | @Test 51 | public void test3() { 52 | System.out.println("=======/**放在中间语法======"); 53 | PathPattern pattern = PathPatternParser.defaultInstance.parse("/api/**/yourbatman"); 54 | 55 | pattern.matches(PathContainer.parsePath("/api/a/b/c/yourbatman")); 56 | } 57 | 58 | @Test 59 | public void test4() { 60 | System.out.println("======={*pathVariable}放中间代替/**放中间======"); 61 | PathPattern pattern = PathPatternParser.defaultInstance.parse("/api/{*pathVariable}/yourbatman"); 62 | 63 | System.out.println(pattern.matches(PathContainer.parsePath("/api/a/b/c/yourbatman"))); 64 | } 65 | 66 | 67 | 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /spring5/spring5-java/src/main/java/cn/yourbatman/spring5/java/pathpattern/WebMvcConfiguration.java: -------------------------------------------------------------------------------- 1 | package cn.yourbatman.spring5.java.pathpattern; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | import org.springframework.web.util.pattern.PathPatternParser; 7 | 8 | /** 9 | * 在此处添加备注信息 10 | * 11 | * @author YourBatman. Send email to me 12 | * @site https://yourbatman.cn 13 | * @date 2021/6/20 18:33 14 | * @since 0.0.1 15 | */ 16 | @Configuration(proxyBeanMethods = false) 17 | public class WebMvcConfiguration implements WebMvcConfigurer { 18 | 19 | @Override 20 | public void configurePathMatch(PathMatchConfigurer configurer) { 21 | configurer.setPatternParser(PathPatternParser.defaultInstance); 22 | } 23 | } 24 | --------------------------------------------------------------------------------