# webproject **Repository Path**: hrbu2023/webproject ## Basic Information - **Project Name**: webproject - **Description**: 学习Javaweb - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-11-13 - **Last Updated**: 2025-11-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # JavaWeb HTTP协议 ![image-20251113084839989](./assets/image-20251113084839989.png) ![image-20251113085809222](./assets/image-20251113085809222.png) 上下文 ![image-20251113085821317](./assets/image-20251113085821317.png) 地址映射 ![image-20251113085832117](./assets/image-20251113085832117.png) ## 中间件 在Java开发中,有多种Web服务器和容器可供选择,每种都有其特定的用途和优势。下面是一些常见Web服务器和容器的简要介绍,以及它们各自的特点: ### 1. Tomcat(SpringBoot 默认 嵌入式的 Tomcat--可切换) - ‌**概述**‌:Apache Tomcat是一个开源的Web服务器和Servlet容器,实现了Java Servlet和JavaServer Pages技术。 ‌ 特点‌: - 支持Servlet规范。 - 易于配置和使用。 - 广泛用于开发和生产环境中的Java Web应用。 - ‌**使用场景**‌:适合需要快速部署Java Web应用,尤其是基于Servlet和JSP的项目。 ### 2. JBoss - ‌**概述**‌:JBoss是一个开源的应用服务器,最初由JBoss公司开发,现在属于Red Hat的一部分。它支持多种Java EE技术。 - ‌特点‌: - 支持完整的Java EE平台。 - 提供了丰富的企业级功能,如事务管理、集群支持等。 - 高度可配置和可扩展。 - ‌**使用场景**‌:适合需要高度可扩展性和企业级功能的大型企业应用。 ### 3. Jetty - ‌**概述**‌:Jetty是一个开源的Servlet容器,提供Web服务器和Java Servlet技术。 - ‌特点‌:轻量级、非阻塞式I/O。 - 易于嵌入到其他应用中。 - 适合快速开发和原型制作。 - ‌**使用场景**‌:适合需要高性能和快速开发的场景,如嵌入式系统或微服务架构。 ### 4. WebLogic - ‌**概述**‌:WebLogic是Oracle公司开发的一个企业级应用服务器,支持Java EE技术。 - ‌特点‌: - 提供全面的企业级功能,如集群、负载均衡、安全性和事务管理。 - 强大的性能和可伸缩性。 - 集成Oracle数据库和其他Oracle产品。 - ‌**使用场景**‌:适合需要高度集成和强大管理工具的大型企业级应用。 ### 5. WebSphere - ‌**概述**‌:IBM的WebSphere是另一个企业级应用服务器,支持Java EE技术。 - ‌特点‌: - 提供全面的企业级功能,如安全性、事务管理、集群等。 - 强大的性能和可伸缩性。 - 集成IBM产品和技术。 - ‌**使用场景**‌:适合需要IBM技术支持和集成的大型企业应用。 ### 选择建议: - ‌**如果项目较小且主要基于Servlet/JSP**‌,可以选择‌**Tomcat**‌。 - ‌**对于需要全面Java EE支持的企业级应用**‌,可以选择‌**JBoss**‌或‌**WebLogic/WebSphere**‌。 - ‌**如果需要轻量级、易于嵌入的应用服务器**‌,可以选择‌**Jetty**‌。 - ‌**根据具体需求选择是否需要特定的企业级功能、集成或性能要求**‌,这将影响你的选择是Tomcat、JBoss、WebLogic还是WebSphere。 每种服务器和容器都有其特定的优势和适用场景,选择最适合你的项目需求的那个是最重要的 ## 安装中间件 Tomcat : https://tomcat.apache.org/ Java EE : (Tomcat 9-) javax.servlet.HttpServletRequest javax.servlet.HttpServletResponse ![image-20251113090319562](./assets/image-20251113090319562.png) Jakarta EE :(Tomcat 10+) jakarta.servlet.HttpServletRequest jakarta.servlet.HttpServletResponse ### 下载 https://tomcat.apache.org/download-10.cgi ![image-20251113090526593](./assets/image-20251113090526593.png) ![image-20251113090651576](./assets/image-20251113090651576.png) ### 解压 ![image-20251113090721233](./assets/image-20251113090721233.png) ### 启动 需要环境变量中有 %JAVA_HOME% ![image-20251113090833182](./assets/image-20251113090833182.png) ### 测试访问 http://localhost:8080 http://localhost:8080/ --> ROOT项目 ![image-20251113091045171](./assets/image-20251113091045171.png) ### 编写项目发布到Tomcat、 ![image-20251113091340259](./assets/image-20251113091340259.png) ```html Document

自己编写的项目 发布到Tomcat

``` 将编写的文件夹 copy到 webapps目录中 ![image-20251113091435815](./assets/image-20251113091435815.png) Tomcat热部署 image-20251113091502297 请求地址: http://localhost:8080/java1/index.html ![image-20251113092333569](./assets/image-20251113092333569.png) ## 将Tomcat集成到 IDEA ![image-20251113092404319](./assets/image-20251113092404319.png) ![image-20251113092539781](./assets/image-20251113092539781.png) ![image-20251113092603513](./assets/image-20251113092603513.png) ![image-20251113092632346](./assets/image-20251113092632346.png) ![image-20251113092722650](./assets/image-20251113092722650.png) # 创建项目 - 聚合项目 - 项目A - B - C - 各种项目 ## 聚合项目 聚合项目不需要编写代码,可以删掉 src 目录 ![image-20251113092925805](./assets/image-20251113092925805.png) ![image-20251113093005140](./assets/image-20251113093005140.png) 创建子项目 ![image-20251113093135818](./assets/image-20251113093135818.png) ![image-20251113093233206](./assets/image-20251113093233206.png) ## 创建Web子项目 - 创建普通的java项目 - 编写的是java代码 - 添加web支持 - WEB-INF ### 创建普通项目 ![image-20251113094350089](./assets/image-20251113094350089.png) ![image-20251113094518880](./assets/image-20251113094518880.png) ### 添加Web支持 ![image-20251113094536880](./assets/image-20251113094536880.png) ![image-20251113094611023](./assets/image-20251113094611023.png) ![image-20251113094621880](./assets/image-20251113094621880.png) ![image-20251113094710553](./assets/image-20251113094710553.png) ![image-20251113094718655](./assets/image-20251113094718655.png) ## 编写HTML发布到Tomcat部署 ### 编写Index.html ```html Title 使用IDEA集成的 TOmcat 部署 ``` ### 部署到Tomcat中 ![image-20251113094915348](./assets/image-20251113094915348.png) ![image-20251113094944767](./assets/image-20251113094944767.png) ![image-20251113095000189](./assets/image-20251113095000189.png) ![image-20251113095015429](./assets/image-20251113095015429.png) ![image-20251113095051145](./assets/image-20251113095051145.png) ![image-20251113095106099](./assets/image-20251113095106099.png) ![image-20251113095128952](./assets/image-20251113095128952.png) ![image-20251113095216061](./assets/image-20251113095216061.png) ![image-20251113095233141](./assets/image-20251113095233141.png) ![image-20251113095258963](./assets/image-20251113095258963.png) ### 启动Tomcat ![image-20251113095350866](./assets/image-20251113095350866.png) ![image-20251113095419941](./assets/image-20251113095419941.png) http://localhost:8080/web/index.html ![image-20251113095438784](./assets/image-20251113095438784.png) ## Tomcat热部署 ![image-20251113102732600](./assets/image-20251113102732600.png) # URL http://192.168.84.47:8080/web/index.html ## 协议 - http - https = HTTP+SSL(安全加密套件) ![image-20251113103440016](./assets/image-20251113103440016.png) ## 主机地址 - localhost - 127.0.0.1 - 192.168.84.47 - 域名 - www.baidu.com ---> DNS ---> IP (110.242.69.21) - 正在 Ping www.a.shifen.com [110.242.69.21] 具有 32 字节的数据: 来自 110.242.69.21 的回复: 字节=32 时间=36ms TTL=51 来自 110.242.69.21 的回复: 字节=32 时间=36ms TTL=51 来自 110.242.69.21 的回复: 字节=32 时间=36ms TTL=51 来自 110.242.69.21 的回复: 字节=32 时间=36ms TTL=51 110.242.69.21 的 Ping 统计信息: 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失), 往返行程的估计时间(以毫秒为单位): 最短 = 36ms,最长 = 36ms,平均 = 36 根服务器 .com - www.163.com --> DNS --->IP - 模拟域名 - www.jshand.com --> 127.0.0.1 - 修改 C:\windows\dirver\etsc - ![image-20251113104000196](./assets/image-20251113104000196.png) ![image-20251113104151330](./assets/image-20251113104151330.png) ![image-20251113104201794](./assets/image-20251113104201794.png) ![image-20251113104213579](./assets/image-20251113104213579.png) ## 端口 - 8080 Tomcat - 3306 MySQL - 7001 Weblogic - 3389 远程桌面 - 1433 : SQL Server ![image-20251113104335857](./assets/image-20251113104335857.png) ## 资源地址 - 完整路径 : http://www.jshand.com:8080/web/index.html - 当前的Tomcat http://www.jshand.com:8080 - 资源地址 web/index.html - web 上下文 - index.html具体的资源路径 # 编写动态内容 用到了Servlet API ![image-20251113105045504](./assets/image-20251113105045504.png) - 添加Tomcat 类库到项目中 - 编写Servlet类 需要集成 HttpServlet - 重写Service方法(暂时) ## 添加Tomcat库 ![image-20251113105324897](./assets/image-20251113105324897.png) ![image-20251113105336676](./assets/image-20251113105336676.png) ![image-20251113105345636](./assets/image-20251113105345636.png) ## 编写Servlet ``` package com.neuedu.servlet; import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; /*** * 项目名称: webproject * 包: com.neuedu.servlet * date: 2025/11/13 10:51 * 描述: * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ public class FirstServlet extends HttpServlet { @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // super.service(req, resp); response.setContentType("text/html;charset=utf-8"); ServletOutputStream os = response.getOutputStream(); String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); os.println("

now: "+now+"

"); os.flush(); os.close(); } } ``` ## 映射地址 ![image-20251113105959969](./assets/image-20251113105959969.png) ## 构造地址 http://localhost:8080/web/first 启动应用 每次请求刷新都会得到最新的时间 ![image-20251113110222693](./assets/image-20251113110222693.png) - 重写的方法 - 不应该是service -- 缓存判断 - 需要重写的 doGet、doPost Servlet声明周期、Servlet是线程不安全 ````java package com.neuedu.servlet; import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; /*** * 项目名称: webproject * 包: com.neuedu.servlet * date: 2025/11/13 10:51 * 描述: 我们的 Servlet 不是线程安全的, 多线程共享 同一个实例 * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ @WebServlet(urlPatterns = "/first") public class FirstServlet extends HttpServlet { public FirstServlet() { System.out.println("声明周期: 1 FirstServlet。构造器 -- 只执行一次 "); } @Override public void init() throws ServletException { System.out.println("声明周期: 2 FirstServlet。init --只执行一次 "); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("声明周期: 3 FirstServlet。doGet、 doPost (每次请求执行 )"); Thread thread = Thread.currentThread(); System.out.println(""" id : %s; name: %s,FirstServlet实例(Hash):%s """.formatted(thread.getId(), thread.getName(),this.hashCode())); response.setContentType("text/html;charset=utf-8"); ServletOutputStream os = response.getOutputStream(); String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); os.println("

now: "+now+"

"); os.flush(); os.close(); } @Override public void destroy() { super.destroy(); System.out.println("声明周期: 4 FirstServlet。destroy (只执行一次 )"); } } ```` [localhost:8080/web/first](http://localhost:8080/web/first) ![image-20251113134342675](./assets/image-20251113134342675.png) # 设置Servlet模板 ![image-20251113135001690](./assets/image-20251113135001690.png) ```java #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; #parse("File Header.java") @WebServlet(urlPatterns = "${path}") public class ${NAME} extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); // 处理GET请求 doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理POST请求 } } ``` ![image-20251113135130033](./assets/image-20251113135130033.png) ## 使用模板创建Servlet ![image-20251113135201996](./assets/image-20251113135201996.png) ![image-20251113135742812](./assets/image-20251113135742812.png) ![image-20251113135802256](./assets/image-20251113135802256.png) # 状态码 200 OK 304 缓存 404 http://localhost:8080/web/second ![image-20251113140344539](./assets/image-20251113140344539.png) 405 请求的方法不支持 地址栏直接访问 Get,但是 Servlet中没有doGet方法 ![image-20251113140740390](./assets/image-20251113140740390.png) ![image-20251113140810487](./assets/image-20251113140810487.png) 500: 服务器内部错误: # 使用Request API - HTTPServletRequest ![image-20251113142416384](./assets/image-20251113142416384.png) ## 获取请求参数 ```java package com.neuedu.servlet; import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /*** * 项目名称: webproject * 包: com.neuedu.servlet * date: 2025/11/13 14:23 * 描述: 使用RequestAPI * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ @WebServlet(urlPatterns = "/req") public class UserRequestServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); // 处理GET请求 doPost(request, response); } /** * * * http://localhost:8080/web/req * http://localhost:8080/web/req?参数列表 * http://localhost:8080/web/req?name=zhangsan&age=18&num=100 * http://localhost:8080/web/req?name=zhangsan&age=18&num=100&fav=bastball&fav=football * * @param request * @param response * @throws ServletException * @throws IOException */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 处理POST请求 //接受参数 String name = request.getParameter("name"); String age = request.getParameter("age"); String num = request.getParameter("num"); String[] fav = request.getParameterValues("fav"); System.out.println("name = " + name); System.out.println("age = " + age); System.out.println("num = " + num); StringBuffer favs = new StringBuffer(); if(fav !=null){ for (String item : fav) { favs.append(item+","); } } // 响应结果 PrintWriter 带缓冲区的 字符 PrintWriter out = response.getWriter(); out.write("name : "+name+" age: "+age+ " num: "+num +" fav:"+favs.toString()); // writer.flush(); out.close(); } } ``` ![image-20251113143019929](./assets/image-20251113143019929.png) ![image-20251113143905504](./assets/image-20251113143905504.png) ![image-20251113144149986](./assets/image-20251113144149986.png) # 使用工具模拟浏览器发送请求 [Apifox - API 文档、调试、Mock、测试一体化协作平台。拥有接口文档管理、接口调试、Mock、自动化测试等功能,接口开发、测试、联调效率,提升 10 倍。最好用的接口文档管理工具,接口自动化测试工具。](https://apifox.com/) ![image-20251113144733938](./assets/image-20251113144733938.png) ![image-20251113144751115](./assets/image-20251113144751115.png) 邀请; 金山 在 Apifox 邀请你加入团队 Java1班 https://app.apifox.com/invite?token=kMEO5XpbfLOBkSAIKqt_a ![image-20251113145217333](./assets/image-20251113145217333.png) # 添加数据库的支持 - MySQL 驱动 - utils -- 项目 -jar ## 新建lib目录 ### 添加MYSQL驱动 [mysql-connector-j-8.0.31.jar](..\MyDBUtils\lib\mysql-connector-j-8.0.31.jar) ![image-20251114102851392](./assets/image-20251114102851392.png) ![image-20251114102912923](./assets/image-20251114102912923.png) ![image-20251114102945299](./assets/image-20251114102945299.png) ### utils -- 项目 -jar - 将 p01-dbutil项目打包成 jar - 添加到 系统libs - 在项目中添加依赖 #### 添加打包构建(工件)-jar ![image-20251114103133776](./assets/image-20251114103133776.png) ![image-20251114103153258](./assets/image-20251114103153258.png) ![image-20251114103204770](./assets/image-20251114103204770.png) ![image-20251114103305771](./assets/image-20251114103305771.png) #### 执行打包 ![image-20251114103331927](./assets/image-20251114103331927.png) ![image-20251114103344635](./assets/image-20251114103344635.png) ![image-20251114103416232](./assets/image-20251114103416232.png) #### 添加依赖 ![image-20251114103513076](./assets/image-20251114103513076.png) ![image-20251114103553290](./assets/image-20251114103553290.png) ## 测试连接数据库 jdbc.properties ```properties jdbc.url=jdbc:mysql://localhost:3306/his jdbc.driverClass=com.mysql.cj.jdbc.Driver jdbc.username=root jdbc.password=root ``` 编写一些po、Dao ![image-20251114104327681](./assets/image-20251114104327681.png) ![image-20251114104336501](./assets/image-20251114104336501.png) # 使用数据库内容展示列表 ![image-20251114113924547](./assets/image-20251114113924547.png) - UserController (UserServlet改名) - list 真正从数据库中加载数据 - UserService # 响应JSON ``` protected void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //从数据库查询xinxi List list = userService.list(); //设置编码 response.setCharacterEncoding("UTF-8"); //设置MIME类型 (媒体) // response.setContentType("text/plain;charset=UTF-8"); // response.setContentType("text/html;charset=UTF-8"); // 响应json response.setContentType("application/json;charset=UTF-8"); //使用response 相应内容 PrintWriter out = response.getWriter(); /** * [ * { "username":"admin' , "password":"123456" ,"nickname":"管理" ,"lastLogin":170000000000 } * { "username":"root' , "password":"123456" ,"nickname":"管理" ,"lastLogin":170000000000 } * { "username":"super' , "password":"123456" ,"nickname":"管理" ,"lastLogin":170000000000 } * { "username":"admin' , "password":"123456" ,"nickname":"管理" ,"lastLogin":170000000000 } * { "username":"admin' , "password":"123456" ,"nickname":"管理" ,"lastLogin":170000000000 } * { "username":"admin' , "password":"123456" ,"nickname":"管理" ,"lastLogin":170000000000 } * { "username":"admin' , "password":"123456" ,"nickname":"管理" ,"lastLogin":170000000000 } * * ] */ String template = "{ \"username\":\"%s\" , \"password\":\"%s\" ,\"nickname\":\"%s\" ,\"lastLogin\":%d }" ; StringBuffer json = new StringBuffer("["); for (User user : list) { Date lastLogin = user.getLastLogin(); long time = 0; if(lastLogin != null){ time = lastLogin.getTime(); } json.append(template.formatted(user.getUsername(), user.getPassword(), user.getNickname(),time )); } json.append("]"); System.out.println("json = " + json); // 响应内容到 浏览器 out.print(json.toString()); out.flush(); out.close(); } ``` - fastjson - **fastjson2** - GSON - **jackson(Spring )** ### 下载jackson - https://repo1.maven.org/maven2/tools/jackson/core/jackson-core/3.0.2/jackson-core-3.0.2.jar - https://repo1.maven.org/maven2/tools/jackson/core/jackson-databind/3.0.2/jackson-databind-3.0.2.jar - https://repo1.maven.org/maven2/tools/jackson/dataformat/jackson-dataformat-xml/3.0.2/jackson-dataformat-xml-3.0.2.jar - https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/3.0-rc5/jackson-annotations-3.0-rc5.jar 添加库 ![image-20251114135701289](./assets/image-20251114135701289.png) ### 使用main方法进行测试 ```java package test; import com.neuedu.po.User; import tools.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.Date; import java.util.List; /*** * 项目名称: webproject * 包: test * date: 2025/11/14 13:58 * 描述: * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ public class Object2JSONString { public static void main(String[] args) { ObjectMapper objectMapper = new ObjectMapper(); User user = new User(); user.setUsername("张三"); user.setPassword("123456"); user.setNickname("管理员"); user.setId(100L); user.setLastLogin(new Date()); //将内存对象转换成 JSON格式的 字符串 String json = objectMapper.writeValueAsString(user); System.out.println(json); List list = new ArrayList(); for (int i = 0; i < 5; i++) { User itemUser = new User(); itemUser.setUsername("张三"); itemUser.setPassword("123456"); itemUser.setNickname("管理员"); itemUser.setId(100L); itemUser.setLastLogin(new Date()); list.add(itemUser); } //集合转换成JSON数组 //将内存对象转换成 JSON格式的 字符串 json = objectMapper.writeValueAsString(list); System.out.println(json); } } ``` # 控制台乱码解决 - loadOnStartup 容器启动的时候初始化 Servlet ![image-20251119084304997](./assets/image-20251119084304997.png) ![image-20251119084335926](./assets/image-20251119084335926.png) ``` -Dfile.encoding=utf-8 ``` # 修改地址映射 > 原来地址: > > ``` > //http://127.0.0.1:8080/web/user > //http://127.0.0.1:8080/web/user?_type= > //http://127.0.0.1:8080/web/user?_type=list > ``` > > 希望修改成下面的: > > http://127.0.0.1:8080/web/user/list > > http://127.0.0.1:8080/web/user/add > > http://127.0.0.1:8080/web/user/update > > http://127.0.0.1:8080/web/user/getById > > http://127.0.0.1:8080/web/user/delete ## 修改WebServlet注解 ![image-20251119084659177](./assets/image-20251119084659177.png) ## 获取上下文 和URL Controller中使用 ``` // requestURI = /web/user String requestURI = request.getRequestURI(); // contextPath = /web String contextPath = request.getContextPath(); String requestMethods = ""; if(requestURI.equals(contextPath)){ return; } requestURI = requestURI.substring(contextPath.length()); requestMethods = URLUtils.getRequestMethods(requestURI); System.out.println("requestMethods = " + requestMethods); ``` ```java package com.neuedu.util; /*** * 项目名称: webproject * 包: com.neuedu.util * date: 2025/11/19 8:51 * 描述: * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ public class URLUtils { /** * * @param uri /web/user * @return */ public static String getRequestMethods(String uri) throws RuntimeException { if(uri == null || "".equals(uri) || !uri.contains("/")){ throw new RuntimeException("URI不能为空 URL地址不正确 ,url:{"+uri+"}"); } return uri.substring(uri.lastIndexOf("/")+1); } public static void main(String[] args) { String requestMethods = ""; // String uri = "/web/role/update"; // String uri = "/web/role/add"; String uri = "/web"; String contextPath = "/web"; System.out.println("uri = " + uri); if(uri.equals(contextPath)){ return; } uri = uri.substring(contextPath.length()); System.out.println("uri = " + uri); requestMethods = URLUtils.getRequestMethods(uri); System.out.println("requestMethods = " + requestMethods); } } ``` # CRUD练习 仿照 User相关的代码完成的Role角色表的增删改查(CRUD) - UserController - UserService - UserDao - RoleDao - RoleService - RoleController # 封装参数绑定 在CRUD中会大量的 回去参数,绑定到 User、Role (PO)对象中 - 传递那些参数 - - 动态创建实例new User new Role - 将参数设置到实例中 工具类 ```java package com.neuedu.util; import com.neuedu.po.Role; import jakarta.servlet.http.HttpServletRequest; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Enumeration; /*** * 项目名称: webproject * 包: com.neuedu.util * date: 2025/11/19 10:40 * 描述: * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ public class ParameterUtils { public static T convertRequest2PO(HttpServletRequest request , Class clazz){ // Class clazz = Role.class; String paraName = ""; String setMethodName = ""; Object po = null; try { po = clazz.newInstance(); //获取所有参数名称 Enumeration parameterNames = request.getParameterNames(); while( parameterNames.hasMoreElements() ){ paraName = parameterNames.nextElement(); Field declaredField = clazz.getDeclaredField(paraName); Class type = declaredField.getType(); setMethodName = "set" + paraName.substring(0, 1).toUpperCase() + paraName.substring(1); Method declaredMethod = clazz.getDeclaredMethod(setMethodName, type); //将String 类型的参数 转换成 Long Date Integer .... Object value = converObjectType(request.getParameter(paraName),type); declaredMethod.invoke(po,value); } } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (NoSuchFieldException e) { System.out.println("未知的属性 class ["+clazz.toString()+"] ,prop:["+paraName+"]"); throw new RuntimeException(e); } catch (NoSuchMethodException e) { System.out.println("未知的方法 class ["+clazz.toString()+"] ,method:["+setMethodName+"]"); throw new RuntimeException(e); } catch (ParseException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } return (T) po; } public static Object converObjectType(String value, Class type ) throws ParseException { String name = type.getName(); System.out.println("name = " + name); Object retValue = null; switch (name){ case "java.util.Date": SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); retValue = simpleDateFormat.parse(value); break; case "java.lang.String": retValue = value; break; case "java.lang.Long": retValue = Long.valueOf(value); break; case "java.lang.Integer": retValue = Integer.valueOf(value); break; case "java.lang.Double": retValue = Double.valueOf(value); break; case "java.lang.Byte": retValue = Byte.valueOf(value); break; case "java.lang.Short": retValue = Short.valueOf(value); break; } return retValue; } } ``` ## 使用正则表达式 匹配 日期格式 - 2025-11-14 - 2025-11-14 15:38:16 - 2025/11/14 - 2025/11/14 15:38:16 ```java package com.neuedu.util; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; /*** * 项目名称: webproject * 包: com.neuedu.util * date: 2025/11/14 14:43 * 描述: * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ public class DateUtils { private static Map DATE_FORMAT_MAPPING = new HashMap(); static { DATE_FORMAT_MAPPING.put("^\\d{4}-\\d{2}-\\d{1,2}$","yyyy-MM-dd" ); DATE_FORMAT_MAPPING.put("^\\d{4}-\\d{2}-\\d{1,2} \\d{2}:\\d{2}:\\d{2}$","yyyy-MM-dd HH:mm:ss" ); } public static Date str2Date(String strTime,String pattern){ Date parse = null; try { parse = new SimpleDateFormat(pattern).parse(strTime); } catch (ParseException e) { throw new RuntimeException(e); } return parse; } public static Date str2Date(String strTime ){ return str2Date(strTime,"yyyy-MM-dd HH:mm:ss"); } /** * 根据日期 字符串的 模式 , 自动转换成 Date 类型 * @param dataValue * @return */ public static Date getDate(String dataValue){ Date date = null; // Pattern compile = Pattern.compile("^\\d{4}-\\d{2}-\\d{1,2}$"); Set patterns = DATE_FORMAT_MAPPING.keySet(); for (String pattern : patterns) { Pattern compile = Pattern.compile(pattern); Matcher matcher = compile.matcher(dataValue); boolean matches = matcher.matches(); if (matches) { String format = DATE_FORMAT_MAPPING.get(pattern); date = DateUtils.str2Date(dataValue, format); break; } } return date; } /** * - 2025-11-14 * - 2025-11-14 15:38:16 * * - 2025/11/14 * - 2025/11/14 15:38:16 * @param args */ public static void main(String[] args) { String dataValue = "2025-11-14"; // String dataValue = "2025-11-14 15:38:16"; Date info = getDate(dataValue); System.out.println("info = " + info); } } ``` # 通用的返回结果: ``` [ { "createTime": "2025-11-07T01:25:03.000Z", "createUser": 1, "id": 1, "lastLogin": null, "nickname": "管理员1", "password": "123456", "status": "1", "updateTime": null, "updateUser": 0, "username": "admin" }, { "createTime": "2025-11-07T01:26:00.000Z", "createUser": 1, "id": 2, "lastLogin": null, "nickname": "系统管理员2", "password": "123456", "status": "1", "updateTime": null, "updateUser": 0, "username": "root" }, { "createTime": "2025-11-07T01:26:00.000Z", "createUser": 1, "id": 3, "lastLogin": "2025-11-12T01:15:03.000Z", "nickname": "测试昵称3333", "password": "123456", "status": "1", "updateTime": "2025-11-12T01:15:03.000Z", "updateUser": 1, "username": "super" }, { "createTime": "2025-11-07T06:56:17.000Z", "createUser": 0, "id": 8, "lastLogin": null, "nickname": "JDBC4", "password": "123456", "status": "1", "updateTime": null, "updateUser": 0, "username": "abd" }, { "createTime": "2025-11-12T01:02:03.000Z", "createUser": 0, "id": 9, "lastLogin": null, "nickname": "JDBC5", "password": "123456", "status": "1", "updateTime": null, "updateUser": 0, "username": "PrepareUser" }, { "createTime": "2025-11-12T03:24:53.000Z", "createUser": 0, "id": 10, "lastLogin": null, "nickname": "JDBC6", "password": "123456", "status": "1", "updateTime": null, "updateUser": 0, "username": "PrepareUser" }, { "createTime": "2025-11-14T06:49:36.000Z", "createUser": 0, "id": 11, "lastLogin": null, "nickname": "api管理员", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "apifox" }, { "createTime": null, "createUser": 1, "id": 13, "lastLogin": "2025-11-14T06:50:05.000Z", "nickname": "api管理员", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "apifox" }, { "createTime": null, "createUser": 1, "id": 14, "lastLogin": "2025-11-14T06:50:05.000Z", "nickname": "api管理员URL", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "apifox_URL" }, { "createTime": null, "createUser": 1, "id": 15, "lastLogin": "2025-11-14T06:50:05.000Z", "nickname": "api管理员URL", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "apifox_URL" }, { "createTime": null, "createUser": 0, "id": 16, "lastLogin": "2025-11-14T06:50:05.000Z", "nickname": "api管理员URL", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "apifox_URL" }, { "createTime": null, "createUser": 0, "id": 17, "lastLogin": "2025-11-14T06:50:05.000Z", "nickname": "api管理员URL", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "封装参数" }, { "createTime": null, "createUser": 0, "id": 18, "lastLogin": "2025-11-13T16:00:00.000Z", "nickname": "api管理员URL", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "封装参数111" }, { "createTime": null, "createUser": 0, "id": 19, "lastLogin": "2025-11-14T10:35:25.000Z", "nickname": "api管理员URL", "password": null, "status": "1", "updateTime": null, "updateUser": 0, "username": "封装参数2222" } ] ``` ``` true ``` ``` HTTP状态 405 - 方法不允许

HTTP状态 405 - 方法不允许


类型 状态报告

消息 方法不支持

描述 请求行中接收的方法由源服务器知道,但目标资源不支持


Apache Tomcat/10.1.49

``` 因为不同的请求,返回的结果不一致, 在Vue(前端) ## 成功: ``` { code: 200 msg:"操作成功"|| null data: 查询的结果 } { code: 200 msg:"操作成功"|| null data: ture } ``` ## 失败 ``` { code: 404 msg: e.message || "错误消息....." data: null } { code: 403 msg: e.message || "错误消息....." data: null } { code: 405 msg:"操作成功"|| null data: null } { code: 500 msg:"操作成功"|| null data: null } ``` ```java package com.neuedu.common; import com.neuedu.util.ParameterUtils; import java.text.ParseException; import java.util.Date; /*** * 项目名称: webproject * 包: com.neuedu.common * date: 2025/11/19 10:04 * 描述: * @author : 张金山 * 作者博客: https://blog.fulfill.com.cn */ public class Ret { private int code; private String msg; private Object data; public Ret(int code, String msg, Object data) { this.code = code; this.msg = msg; this.data = data; } public static Ret ok(Object data){ return new Ret(200,null,data); } public static Ret ok(){ return new Ret(200,null,null); } public static Ret fail(String msg){ return new Ret(500,msg,null); } public static Ret noPres(String msg){ return new Ret(403,msg,null); } public static Ret notFound(String msg){ return new Ret(404,msg,null); } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } @Override public String toString() { return "Ret{" + "code=" + code + ", msg='" + msg + '\'' + ", data=" + data + '}'; } } ``` ![image-20251119133312593](./assets/image-20251119133312593.png) ![image-20251119133333953](./assets/image-20251119133333953.png) ## 当浏览器访问的地址 和 ajax 访问的地址 不同源: 浏览器触发同源策略: https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy ![image-20251119141549988](./assets/image-20251119141549988.png) ![image-20251119142210629](./assets/image-20251119142210629.png) 解决跨域的问题: ![image-20251119145518953](./assets/image-20251119145518953.png) # 整合Vue 将vue-vite项目复制一份,去掉没有用 ## 将 p03-front.zip ---解压 理论解压到哪里都型,为了管理方便,放到 webproject ![image-20251119145858766](./assets/image-20251119145858766.png) ## 安装依赖 ![image-20251119145933418](./assets/image-20251119145933418.png) ``` npm install ``` ## 启动 ![image-20251119150841205](./assets/image-20251119150841205.png) ## 在Vue中使用ajax - 在 src\views\system\user\index.vue中使用 ajax ```vue ```