Java自学第11课:电商项目(4)重新建立项目

news2024/11/18 23:47:37

经过前几节的学习,我们已经找到之前碰到的问题的原因了。那么下面接着做项目学习。

1 新建dynamic web project

建立时把web.xml也生成下,省的右面再添加。

会询问是否改为java ee环境?no就行,其实改过来也是可以的。这个不重要。

新建完毕后,看下当前的web.xml

欢迎界面不需要,删除即可。

2 流程图

我们开始写代码之前,还是重点关注下这个逻辑流程图,之前编程序都没注意这个,所以才发生错误不知道怎么回事。

web.xml很重要,这里配置了这个工程的入口。我们这个程序实际上是一个servlet程序,前端配合jsp网页展示。所以,入口就是规定servlet的名称及url。当部署在服务器后,我们的页面首先要访问servlet,之后拦截请求后,处理请求并获取参数,之后再传给前端的jsp网页去呈现。

在编写代码时,可以先写servlet,也可以先配置web.xml,也可以先写jsp文件,从逻辑上将,我们先去配置servlet的web.xml更好。

3 配置servlet

这里主要是配置servlet信息,如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>eb1</display-name>
<servlet>
	<servlet-name>index</servlet-name>
	<servlet-class>com.xxx.xx</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>index</servlet-name>
	<url-pattern>/index</url-pattern>
</servlet-mapping>
</web-app>

主要是servlet及其mapping,然后各有两个项。

其中名称需要一致,类就指向之后要新建的类。然后url也可以随便指定,部署后就从这里进入。

4 引入类库

这些类库都是配置好的,直接放入lib即可。放入后,所有类库需要buildpath,项目会自动加入reference libraries.

5 创建实体类

实体类根据数据库的表来创建。对于导航栏,有两个表需要用到:大类表和标签表。

实体类可放入vo包里。由于大类型包含小类型,所以小类型也得建类。

下面是具体实现:

tagl类:

package com.xx.vo;
/**
  *  标签类
 *
 */
public class Tag {
	private int id;
	private String name;
	private String url;
	
	public Tag() {
		// TODO Auto-generated constructor stub
	}

	public Tag(int id, String name, String url) {
		super();
		this.id = id;
		this.name = name;
		this.url = url;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	@Override
	public String toString() {
		return "Tag [id=" + id + ", name=" + name + ", url=" + url + "]";
	}

	
	
	
}

bigtype类

package com.xx.vo;

import java.util.ArrayList;
import java.util.List;

public class ProductBigType {
	private int id;
	private String name;
	private String remarks;
	private List<ProductSmallType> smallTypeList = new ArrayList<ProductSmallType>();
	
	public ProductBigType() {
		// TODO Auto-generated constructor stub
	}

	public ProductBigType(int id, String name, String remarks, List<ProductSmallType> smallTypeList) {
		super();
		this.id = id;
		this.name = name;
		this.remarks = remarks;
		this.smallTypeList = smallTypeList;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRemarks() {
		return remarks;
	}

	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}

	public List<ProductSmallType> getSmallTypeList() {
		return smallTypeList;
	}

	public void setSmallTypeList(List<ProductSmallType> smallTypeList) {
		this.smallTypeList = smallTypeList;
	}

	@Override
	public String toString() {
		return "ProductBigType [id=" + id + ", name=" + name + ", remarks=" + remarks + ", smallTypeList="
				+ smallTypeList + "]";
	}
	
	
	
}

smalltype类

package com.xx.vo;

public class ProductSmallType {
	private int id;
	private String name;
	private String remarks;
	private int bigTypeId;
	
	public ProductSmallType() {
		// TODO Auto-generated constructor stub
	}

	public ProductSmallType(int id, String name, String remarks, int bigTypeId) {
		super();
		this.id = id;
		this.name = name;
		this.remarks = remarks;
		this.bigTypeId = bigTypeId;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRemarks() {
		return remarks;
	}

	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}

	public int getBigTypeId() {
		return bigTypeId;
	}

	public void setBigTypeId(int bigTypeId) {
		this.bigTypeId = bigTypeId;
	}

	@Override
	public String toString() {
		return "ProductSmallType [id=" + id + ", name=" + name + ", remarks=" + remarks + ", bigTypeId=" + bigTypeId
				+ "]";
	}
	
	
}

其中,大类里用到了List和ArrayList,需要引导util包。

6 创建数据库交互类

数据库交互主要是连接,关闭数据库,需要做成静态的,这样就一直存在。

DBUtil类

package com.xx.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
  * 数据库交互类
 *
 */
public class DBUtil {
	
	// 主方法 用于测试
	public static void main(String[] args) {
		try {
			DBUtil.getConn();
			System.out.println("conn ok...");
		} catch (Exception e) {
			System.out.println("conn error...");
			e.printStackTrace();
		}
		
	}
	
	// 加载驱动
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver"); // 反射机制加载驱动
		} catch (ClassNotFoundException e) {
			System.out.println("error in forName...");
			e.printStackTrace();
		}
	}
	
	// 获取连接
	public static Connection getConn() {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ebuys?useUnicode=true&characterEncoding=utf8","root","1234");
		} catch (SQLException e) {
			System.out.println("error in DriverManager");
			e.printStackTrace();
		}
		return conn;
	}
	
	// 完整关闭
	public static void closeAll(Connection conn, PreparedStatement pstmt, ResultSet rs) {
		closeResult(rs);
		closeState(pstmt);
		closeConn(conn);
	}
	
	// 关闭连接
	private static void closeConn(Connection conn) {
		if(null != conn) {
			try {
				conn.close();
			} catch (SQLException e) {
				System.out.println("error in close...");
				e.printStackTrace();
			}
		}
	}
	
	// 关闭管道
	private static void closeState(PreparedStatement pstmt) {
		if(null != pstmt) {
			try {
				pstmt.close();
			} catch (SQLException e) {
				System.out.println("error in pstmt...");
				e.printStackTrace();
			}
		}
	}
	
	// 关闭结果
	private static void closeResult(ResultSet rs) {
		if(null != rs) {
			try {
				rs.close();
			} catch (SQLException e) {
				System.out.println("error in rs...");
				e.printStackTrace();
			}
		}
	}
	
}

这里可以用main主方法来测试下是否能够连接,注意这些都是需要类库支持的,要是忘记引入,会发生错误。

7 创建servlet

现在来编写刚才web.xml规定的servlet,作用是将数据库内的信息传入页面。这里需要进行间接的数据库操作。

package com.xx.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.xx.service.ProductBigTypeService;
import com.xx.service.TagService;
import com.xx.service.impl.ProductBigTypeServiceImpl;
import com.xx.service.impl.TagServiceImpl;
import com.xx.vo.ProductBigType;
import com.xx.vo.Tag;

public class InitController extends HttpServlet {

	private static final long serialVersionUID = 1L;

	// 通过接口及其实例化来降低耦合度 让程序容易拓展
	private ProductBigTypeService bigTypeService = new ProductBigTypeServiceImpl();
	private TagService tagService = new TagServiceImpl();
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		// 查询类别
		List<ProductBigType> bigTypeList = bigTypeService.findAllBigType();
		// 查询标签
		List<Tag> tagList = tagService.findAll();
		
		// 查询结果放入作用域
		req.setAttribute("bigTypeList", bigTypeList);
		req.setAttribute("tagLiat", tagList);
		
		//
		req.getRequestDispatcher("/index.jsp").forward(req, resp);
		
		
	}
	
}

这个类的思路是重写service来处理请求,并转发到index.jsp。处理过程用到了大类列表和标签列表,这就涉及到查询,这个查询是封装在服务的方法里的。

这里涉及的概念较多,服务被写为了接口,也就是可以理解为纯虚函数。具体在impl里实现方法。

大类列表是通过大类服务的获取大类方法实现的,标签列表是通过标签服务的获取标签方法实现的。两者思路是相同的,需要具体实现。

实现的过程中,大类还包括了小类,因此也需要相应的实现小类的服务和方法。

标签的较为简单,是单层的,先看标签的接口

package com.xx.service;

import java.util.List;

import com.xx.vo.Tag;

public interface TagService {
	// 查询标签
	List<Tag> findAll();
}

其实现是

package com.xx.service.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.xx.service.TagService;
import com.xx.util.DBUtil;
import com.xx.vo.Tag;

public class TagServiceImpl implements TagService {

	@Override
	public List<Tag> findAll() {
		List<Tag> list = new ArrayList<Tag>();
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		

		try {
			conn = DBUtil.getConn();
			String sql = "SELECT * FROM T_TAG";
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();
			while(rs.next()) {
				Tag tag = new Tag();
				tag.setId(rs.getInt("id"));
				tag.setName(rs.getString("name"));
				tag.setUrl(rs.getString("url"));
				list.add(tag);
			}
			return list;
		} catch (SQLException e) {
			System.out.println("error in tagServiceImpl...");
			e.printStackTrace();
		} finally {
			DBUtil.closeAll(conn, pstmt, rs);
		}
		
		
		return null;
	}

}

再来看大类接口

package com.xx.service;

import java.util.List;

import com.xx.vo.ProductBigType;

public interface ProductBigTypeService {
	// 查询大类信息
	List<ProductBigType> findAllBigType();
}

其实现为

package com.xx.service.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.xx.service.ProductBigTypeService;
import com.xx.service.ProductSmallTypeService;
import com.xx.util.DBUtil;
import com.xx.vo.ProductBigType;
import com.xx.vo.ProductSmallType;

public class ProductBigTypeServiceImpl implements ProductBigTypeService {

	private ProductSmallTypeService smallTypeService = new ProductSmallTypeServiceImpl();
	
	@Override
	public List<ProductBigType> findAllBigType() {
		List<ProductBigType> list = new ArrayList<ProductBigType>();
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {
			conn = DBUtil.getConn();
			String sql = "SELECT * FROM T_BIGTYPE";
			pstmt = conn.prepareStatement(sql);
			rs = pstmt.executeQuery();
			while(rs.next()) {
				ProductBigType pbt = new ProductBigType();
				pbt.setId(rs.getInt("id"));
				pbt.setName(rs.getString("name"));
				pbt.setRemarks(rs.getString("remarks"));
				
				List<ProductSmallType> pst = smallTypeService.findByBigTypeId(rs.getInt("id"));
				pbt.setSmallTypeList(pst);
				list.add(pbt);
			}
			return list;
		} catch (SQLException e) {
			System.out.println("error in bigTypeServiceImpl...");
			e.printStackTrace();
		} finally {
			DBUtil.closeAll(conn, pstmt, rs);
		}
		
		
		
		return null;
	}

}

在组合列表时,用到了小类接口,这里需要传入大类的id

package com.xx.service;

import java.util.List;

import com.xx.vo.ProductSmallType;

public interface ProductSmallTypeService {
	// 查询当前大类id对应的所有小类
	List<ProductSmallType> findByBigTypeId(int bigTypeId);
}

对应的实现是

package com.xx.service.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.xx.service.ProductSmallTypeService;
import com.xx.util.DBUtil;
import com.xx.vo.ProductSmallType;

public class ProductSmallTypeServiceImpl implements ProductSmallTypeService {

	@Override
	public List<ProductSmallType> findByBigTypeId(int bigTypeId) {
		
		List<ProductSmallType> list = new ArrayList<ProductSmallType>();
		
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		try {		
			conn = DBUtil.getConn();
			String sql = "SELECT * FROM T_SMALLTYPE WHERE BIGTYPEID = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, bigTypeId);
			rs = pstmt.executeQuery();
			while(rs.next()) {
				ProductSmallType pst = new ProductSmallType();
				pst.setId(rs.getInt("id"));
				pst.setName(rs.getString("name"));
				pst.setRemarks(rs.getString("remarks"));
				pst.setBigTypeId(bigTypeId);
				list.add(pst);
			}
			return list;
		} catch (SQLException e) {
			System.out.println("error in ProductSmallTypeServiceImpl...");
			e.printStackTrace();
		} finally {
			DBUtil.closeAll(conn, pstmt, rs);
		}
		return null;
	}

}

这里用到个知识点,就是怎么用通配符写sql语句。

8 写index.jsp

接下来,就可以写jsp了。首先引入css和图片资源,之后新建index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>eb1</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
	<div id="header" class="wrap">
		<jsp:include page="common/top.jsp"/>
	</div>

	<div id="footer">
		<jsp:include page="common/footer.jsp"/>
	</div>
</body>
</html>

这里用到了jsp里的include指令。分别指向top和footer,先来看footer

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	Copyright &copy; 2019 xx inc. All rights reserved.
</body>
</html>

再来看top,使用div来构建出导航栏。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
	<div id="logo">
		<img src="images/logo.gif" />
		
	</div>
	
	<div class="help">
	</div>
	
	<div class="navbar">
		<ul class="clearfix">
			<li class="current"><a href="index">首页</a></li>
			<c:forEach items="${bigTypeList}" var="bType">
				<li>
					<a href="productServlet?oper=productType&id=${bType.id}">${bType.name}</a>
				</li>
			
			</c:forEach>
		</ul>
	</div>
</body>
</html>

这里先实现了主导航栏,用了c:foreach的写法。

8 效果展示

下面看下实现效果,使用tomcat部署,打开网页:

也就是说前面写的都是正确的。今天的课程就到这里,接下来接着完善jsp页面和servlet类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1204690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redhat7查看时区、修改时区

问题&#xff1a; 安装好redhat7之后&#xff0c;发现时间和物理机上面的网络时间不一致&#xff0c;于是查看本着修改时间的目的&#xff0c;却发现原来是时区的问题。 解决步骤&#xff1a; 查看时区状态信息 timedatectl修改时区到亚洲/上海 timedatectl set-timezone A…

数列计算

题目描述 有一列数是 : 请找出这个数列的规律&#xff0c;编写程序计算并输出这个数列的第项&#xff0c;要求是分数形式&#xff0c;并计算这个数列的前项和 ( 结果四舍五入保留两位小数 ) 输入格式 第一行仅有一个正整数 &#xff08;) 。 输出格式 共有 行&#xff0c;第一…

ctfshow sql171-179

mysql 先打开我们本地的mysql&#xff0c;可以看到这些数据库 information_schema information_schema 库: 是信息数据库&#xff0c;其中保存着关于MySQL服务器所维护的所有其他数据库的信息比如数据库名&#xff0c;数据库表&#xff0c; SCHEMATA表: 提供了当前MySQL实例…

Springboot+Dubbo+Nacos 集成 Sentinel(入门)

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。Sentinel 官网 1.版本选择 参考 SpringClou…

高级数据分析方法与模型

前言 数据思维练习不仅要熟练地掌握了分析工具&#xff0c;还要掌握大量的数据分析方法和模型。 这样得出的结论不仅具备条理性和逻辑性&#xff0c;而且还更具备结构化和体系化&#xff0c;并保证分析结果的有效性和准确性。今天从以下6个维度36种分析模型和方法逐个简略介绍…

双11终极战报:全程强势领跑 德施曼连续8年蝉联全渠道第一

截止11月11日24时&#xff0c;2023年双11电商大促落下帷幕&#xff0c;回顾今年的双11&#xff0c;在各种营销玩法、直播带货等形式的刺激下&#xff0c;激发了广大消费者的购物热潮。 也正因此&#xff0c;在双11结束后&#xff0c;各大电商平台、商家都纷纷交出了亮眼的成绩…

如何搞垮一个测试团队?

要想彻底搞垮一个测试团队并非易事&#xff0c;需要多角色通力配合、多方联动、综合施策&#xff0c;才能达到目的。 本文从实践经验出发&#xff0c;为大家总结了搞垮测试团队的18项措施&#xff0c;或许可以给大家带来一些启发。 — 1 — QA QA作为质量管理者&#xff0c;…

Adobe家里那点事儿~~~

今天&#xff0c;我们来谈谈关于Adobe全家桶中Photoshop的故事。 Adobe Photoshop&#xff0c;简称PS。其定位是一款图像处理软件。他主要处理以像素所构成的数字图像。也就是说我们常见的非矢量图片。 Photoshop的专长在于图像处理&#xff0c;而不是图形的创作。他是对已有的…

ZYNQ实验--Petalinux--Linux C 编程入门

Linux C 编程入门 在 Windows 下我们可以使用各种各样的 IDE 进行编程&#xff0c;比如强大的 Visual Studio。Ubuntu 下也有一些可以进行编程的工具&#xff0c;但是大多都只是编辑器&#xff0c;也就是只能进行代码编辑&#xff0c;如果要编译的话就需要用到 GCC 编译器&…

应急响应练习2

目录 1. 请提交攻击者的ip与系统版本 2. 攻击者通过某个组件漏洞获得服务器权限&#xff0c;请提交该组件的名称 3. 请提交攻击者首次攻击成功的时间 4. 请提交攻击者上传的webshell文件绝对路径 5. 请提交攻击者使用的webshell管理工具 6. 攻击者进一步留下的免杀的webs…

数据结构—数组栈的实现

前言&#xff1a;各位小伙伴们我们前面已经学习了带头双向循环链表&#xff0c;数据结构中还有一些特殊的线性表&#xff0c;如栈和队列&#xff0c;那么我们今天就来实现数组栈。 目录&#xff1a; 一、 栈的概念 二、 栈的实现 三、 代码测试 栈的概念&#xff1a; 栈的概念…

互联网医院牌照|互联网医院牌照办理小知识

随着互联网技术的快速发展&#xff0c;互联网医院牌照已经成为医疗行业的一个重要资质&#xff0c;我们致力于为您提供最优质的服务&#xff0c;帮助您的公司或产品顺利获得此牌照。 一、产品特性描述 1、专业性&#xff1a;我们的团队由经验丰富的顾问组成&#xff0c;对互联…

Redis 连接不上 WRONGPASS invalid username-password pair

1.我的RedisDesktopManager 可以连接 但是 Springboot远程使用Redis就是连不上 2.我的密码是 abc123.. 多了英文的 ..符号 在Springboot过不了&#xff0c;所以Redis密码尽量字母数字&#xff0c;不要其他符号

洛谷P1923 【深基9.例4】求第 k 小的数(java)

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.StreamTokenizer; import java.util.Arrays; import java.util.Scanner; //输入n个数字ai&#xff0c;输出这些数字的第k小的数。最小的数是第0小。 public cla…

IP-guard WebServer 命令执行漏洞复现

简介 IP-guard是一款终端安全管理软件&#xff0c;旨在帮助企业保护终端设备安全、数据安全、管理网络使用和简化IT系统管理。在旧版本申请审批的文件预览功能用到了一个开源的插件 flexpaper&#xff0c;使用的这个插件版本存在远程命令执行漏洞&#xff0c;攻击者可利用该漏…

SAP 60策略测试简介

前面我们已经测试了10.11.20.40.50.52策略的测试&#xff0c;下面我们会测试一下60的策略&#xff0c;我们把60策略和50的策略进行一个比较&#xff0c;先看下后台的配置上面有什么不一样的地方。 首先是50策略 我们看到60策略里面很多地方都显示有计划物料&#xff0c;所以我…

链表相关部分OJ题

&#x1f493;作者简介&#x1f44f;&#xff1a;在校大二迷茫大学生 &#x1f496;个人主页&#x1f389;&#xff1a;小李很执着 &#x1f497;系列专栏&#xff1a;Leetcode经典题 每日分享&#xff1a;人总是在离开一个地方后开始原谅它❣️❣️❣️———————————…

基于php+thinphp+vue的教材管理系统

运行环境 开发语言&#xff1a;PHP 数据库:MYSQL数据库 应用服务:apache服务器 使用框架:ThinkPHPvue 开发工具:VScode/Dreamweaver/PhpStorm等均可 项目简介 教材管理系统&#xff0c;主要的模块包括首页、个人中心、学生管理、老师管理、教材征订管理、教师教材退订管理、…

基于RK3568新零售智能售货柜解决方案

I 方案简介 新零售智能售货柜解决方案&#xff1a; 无人零售除了无人货架外&#xff0c;自动售货机仍是亮点。但仍有很多人认为自动售货机已经过时&#xff0c;不会成为新零售领域的新星。 随着手机支付、人脸支付不断普及&#xff0c;智能售卖不断的推陈出新&#xff0c;无人…

【赠书第5期】AI时代项目经理成长之道:ChatGPT让项目经理插上翅膀

文章目录 前言 1 ChatGPT为项目经理带来便利 2 提供自动化的通知和提醒 3 提供数据分析和可视化 4 结论 5 推荐图书 6 粉丝福利 前言 在现代商业环境中&#xff0c;项目经理需要具备高度的灵活性和响应能力。而现在&#xff0c;随着技术的不断提升和新工具的涌现&#…