日志框架、阶段项目
1.日志框架
1.1日志技术的概述
日志技术具备的优势
可以将系统执行的信息选择性的记录到指定的位置(控制台、文件中、数据库中)。
可以随时以开关的形式控制是否记录日志,无需修改源代码。
日志技术的具体优势
|
输出语句 |
日志技术 |
输出位置 |
只能是控制台 |
可以将日志信息写入到文件或者数据库中 |
取消日志 |
需要修改代码,灵活性较差 |
不需要修改代码,灵活性较好 |
多线程 |
性能较差 |
性能较好 |
1.2日志技术体系结构
日志体系结构如下图所示。
日志规范:一些接口,提供给日志的实现框架设计的标准。
日志框架:者第三方公司已经做好的日志记录实现代码,后来者直接可以拿去使用。
1.3Logback概述
Logback是基于slf4j的日志规范实现的框架。
Logback主要分为三个技术模块:
logback-core:logback-core 模块为其他两个模块奠定了基础,必须有。
logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API。
logback-access:logback-access模块与 Tomcat 和 Jetty 等 Servlet 容器集成,以提供 HTTP 访问日志功能。
1.4Logback快速入门
需求:导入Logback日志技术到项目中,用于纪录系统的日志信息。
分析:
①:在项目下新建文件夹lib(lib代表依赖库,其中存放项目中可能会用到的jar包文件),导入Logback的相关jar包到该文件夹下,并添加到项目依赖库中去。
导入jar包具体步骤如下:
1):如下图所示,在要导入的工程中新建文件夹,起名为”lib”。
2):如下图所示,将提前下载好的jar包文件全部复制,粘贴到lib文件夹下。
如下图所示,在弹出的【复制】对话框中选择”重构”即可完成导入。
3):如下图所示,全部选中导入的jar包,右键选择”添加为库”。
在弹出的【Creat Library】对话框中选择”确定”即可完成将jar包添加到项目依赖库。
4):如下图所示,每个jar包前都有下拉菜单按钮,且能查看其中详细文件,代表jar包整合进工程成功。
②:将Logback的核心配置文件logback.xml(xml文件是项目的核心配置文件,其中进行相关功能的配置和控制)直接拷贝到src目录下(必须是src下)。
③:如下图所示,在代码中获取日志的对象。
④:使用日志对象LOGGER调用不同的方法在控制台/文件中输出不同的日志信息。
注:jar包是什么?
简单来说,jar包是对写好的类进行了打包。我们可以通过将jar包放到lib目录下来使用这些jar包中的类、属性和方法。
专业解释,JAR文件是Java Archive File-java档案文件的简称,是与平台无关的文件格式,基于zip文件格式将许多文件合成一个压缩文件.jar,区别是比zip多了一个 META-INF/MANIFEST.MF 文件,这个文件是在生成 JAR 文件的时候自动创建的。[1]
1.5Logback配置详解-输出位置、格式设置
Logback日志系统的特性都是通过核心配置文件logback.xml控制的。
Logback日志输出位置、格式设置:
通过logback.xml 中的<append>标签可以设置输出位置和日志信息的详细格式。
通常可以设置2个日志输出位置:一个是控制台、一个是系统文件中。
输出到控制台的配置标志如下图所示。
输出到系统文件的配置标志如下图所示。
logback.xml文件示例代码如下:
<configuration><!--CONSOLE :表示当前的日志信息是可以输出到控制台的。--><appendername="CONSOLE"class="ch.qos.logback.core.ConsoleAppender"><!--输出流对象 默认 System.out 改为 System.err(红色)--><target>System.out</target><encoder><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] : %msg%n</pattern></encoder></appender><!-- File是输出的方向通向文件的 --><appendername="FILE"class="ch.qos.logback.core.rolling.RollingFileAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern><charset>utf-8</charset></encoder><!--日志输出路径--><file>C:/code/itheima-data.log</file><!--指定日志文件拆分和压缩规则--><rollingPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><!--通过指定压缩文件名称,来确定分割文件方式--><fileNamePattern>C:/code/itheima-data2-%d{yyyy-MMdd}.log%i.gz</fileNamePattern><!--文件拆分大小--><maxFileSize>1MB</maxFileSize></rollingPolicy></appender><!--level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF, 默认debug<root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。--><rootlevel="ALL"><!--可按需求在此处配置关联打印位置(控制台或文件),否则不会打印--><appender-refref="CONSOLE"/><appender-refref="FILE"/></root></configuration>
1.6Logback配置详解-日志级别设置
日志级别
级别程度依次是:TRACE< DEBUG< INFO<WARN<ERROR ; 默认级别是debug(忽略大小写),对应其方法。
作用:用于控制系统中哪些日志级别是可以输出的,只输出级别不低于设定级别的日志信息。
ALL 和 OFF分别是打开全部日志信息及关闭全部日志信息。
日志级别具体在<root level=“INFO”>标签的level属性中设置。 <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制,可按需求在此处配置关联打印位置(控制台或文件),否则不会打印。
2.阶段项目实战
2.1电影购票系统简介
电影购票系统技术选型分析:
(1)面向对象编程
系统包含了电影对象,商家对象,客户对象,需要用到继承、多态等语法知识。
(2)使用集合容器
系统需要提供不同的容器分别存储系统注册的用户,以及当前商家发布的电影信息。
(3)程序流程控制
需要结合分支、循环、跳转关键字等相关操作控制程序的业务逻辑。
(4)使用常见API
登录信息的内容比较,业务数据的分析、处理,日期时间的处理等。
2.2日志框架搭建、系统角色分析
日志框架搭建、系统角色分析具体步骤如下:
① 集成日志框架、用于后期记录日志信息。
② 定义一个电影类Movie类,Movie类包含:片名、主演、评分、时长、票价、余票。
③ 系统包含2个用户角色:客户、商家。存在大量相同属性信息。
④ 定义User类作为父类,属性:登录名称、密码、真实名称、性别、电话、账户金额。
⑤ 定义Business类代表商家角色,属性:店铺名称、地址。
⑥ 定义Customer类代表客户角色,属性:。
⑦ 定义集合List<User>用户存放系统注册的用户对象信息。
⑧ 定义集合Map<Business, List<Movie>>存放商家和其排片信息。
⑨ 准备一些测试数据。
2.3首页设计、登录、商家界面、用户界面实现
首页、登录、商家界面、用户界面设计步骤如下:
① 首页需要包含登录,商家入驻,客户注册功能。
② 商家和客户可以共用一个登录功能。
③ 判断登录成功的用户的真实类型,根据用户类型完成对应的操作界面设计。
2.4商家-详情页设计、影片上架、退出
商家功能-展示详情、影片上架、退出步骤如下:
① 展示本商家的信息和其排片情况。
② 提供影片上架功能:就是创建一个影片对象,存入到商家的集合中去。
③ 退出,需要回到登录的首页。
易混淆点:
迭代器方法操作中间变量或原变量都不会改变原来变量的值;
非迭代器方法会改变原来变量的值。
详细理解为:
1、add(),remove(),set()方法操作中间变量会改变原变量的值。
2、iterator,stream()迭代器方法操作中间变量不会改变原变量的值,
3、需要注意,如果中间变量是基本数据类型,对这些基本数据类型的操作也不会改变原来变量的值。
如:原变量A为:Map<String, List> A,中间变量为 List B = A.get();对B的操作会改变A的值,如果再下一层中间变量Integer C=B.get(),则对C的操作不会改变B和A。
2.5商家-影片下架、影片修改
商家功能-影片下架、影片修改步骤如下:
① 提供影片下架功能:其实就是从商家的集合中删除影片对象。
② 影片修改功能:拿到需要修改的影片对象,修改里面的数据。
2.6用户-展示全部影片
用户功能-展示全部影片信息步骤如下:
①遍历全部商家和其排片信息并展示出来
2.7用户-购票功能
用户功能-购票操作步骤如下:
① 用户可以选择需要购买票的商家和其电影信息。
② 可以选择购买的数量。
③ 购买成功后需要支付金额,并更新商家金额和客户金额。
示例代码如下:
用户类
publicclassUser { privateStringloginName; // 登录名privateStringpassWord; // 登陆密码privateStringuserName; // 用户姓名privatecharsex; // 性别privateStringphoneNumber; // 联系方式privatedoublemoney; // 账户余额publicUser() { } publicUser(StringloginName, StringpassWord, StringuserName, charsex, StringphoneNumber, doublemoney) { this.loginName=loginName; this.passWord=passWord; this.userName=userName; this.sex=sex; this.phoneNumber=phoneNumber; this.money=money; } publicStringgetLoginName() { returnloginName; } publicvoidsetLoginName(StringloginName) { this.loginName=loginName; } publicStringgetPassWord() { returnpassWord; } publicvoidsetPassWord(StringpassWord) { this.passWord=passWord; } publicStringgetUserName() { returnuserName; } publicvoidsetUserName(StringuserName) { this.userName=userName; } publicchargetSex() { returnsex; } publicvoidsetSex(charsex) { this.sex=sex; } publicStringgetPhoneNumber() { returnphoneNumber; } publicvoidsetPhoneNumber(StringphoneNumber) { this.phoneNumber=phoneNumber; } publicdoublegetMoney() { returnmoney; } publicvoidsetMoney(doublemoney) { this.money=money; } }
商家类
publicclassBusinessextendsUser{ privateStringshopName; // 店铺名privateStringshopAddress; // 店铺地址publicStringgetShopName() { returnshopName; } publicvoidsetShopName(StringshopName) { this.shopName=shopName; } publicStringgetShopAddress() { returnshopAddress; } publicvoidsetShopAddress(StringshopAddress) { this.shopAddress=shopAddress; } }
顾客类
publicclassCustomerextendsUser{ }
电影类
publicclassMovie { privateStringname; // 电影名称privateStringactor; // 主演privatedoublescore; // 评分privatedoubletime; // 电影时长privatedoubleprice; // 票价privateintnumber; // 余票privateDatestartTime; // 放映时间publicMovie() { } publicMovie(Stringname, Stringactor, doubletime, doubleprice, intnumber, DatestartTime) { // 评分是用户评价的,不是创建对象时输入的,因此将score去掉this.name=name; this.actor=actor; this.time=time; this.price=price; this.number=number; this.startTime=startTime; } publicStringgetName() { returnname; } publicvoidsetName(Stringname) { this.name=name; } publicStringgetActor() { returnactor; } publicvoidsetActor(Stringactor) { this.actor=actor; } publicdoublegetScore() { returnscore; } publicvoidsetScore(doublescore) { this.score=score; } publicdoublegetTime() { returntime; } publicvoidsetTime(doubletime) { this.time=time; } publicdoublegetPrice() { returnprice; } publicvoidsetPrice(doubleprice) { this.price=price; } publicintgetNumber() { returnnumber; } publicvoidsetNumber(intnumber) { this.number=number; } publicDategetStartTime() { returnstartTime; } publicvoidsetStartTime(DatestartTime) { this.startTime=startTime; } }
测试类
publicclassMovieSystem { // 创建logback日志对象,打印日志,只需要初始化一次,即可被所有程序使用publicstaticfinalLoggerLOGGER=LoggerFactory.getLogger(MovieSystem.class); // 定义一个静态扫描器,只需要初始化一次,即可被所有程序使用publicstaticfinalScannerSYS_SC=newScanner(System.in); // 定义静态SimpleDateFormat对象,只需要初始化一次,即可被所有程序使用publicstaticSimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 因当前登陆用户最多仅有一个,因此定义静态用户对象,代表当前已经登陆的对象,后续在使用过程中随时调用即可,无需再传User对象参数publicstaticUserloginUser; // 定义系统的数据容器用于存储用户数据publicstaticfinalList<User>ALL_USERS=newArrayList<>(); // 定义容器用于存储商家的排片信息publicstaticfinalMap<Business, List<Movie>>ALL_MOVIES=newHashMap<>(); // 准备一些测试数据static { Customercustomer1=newCustomer(); customer1.setLoginName("abc123"); customer1.setPassWord("123456"); customer1.setUserName("张三"); customer1.setSex('男'); customer1.setMoney(10000); customer1.setPhoneNumber("110110"); ALL_USERS.add(customer1); Customercustomer2=newCustomer(); customer2.setLoginName("xyz123"); customer2.setPassWord("123456"); customer2.setUserName("李四"); customer2.setSex('女'); customer2.setMoney(500); customer2.setPhoneNumber("111111"); ALL_USERS.add(customer2); Businessbusiness1=newBusiness(); business1.setLoginName("wcCinema"); business1.setPassWord("123456"); business1.setUserName("王五"); business1.setMoney(0); business1.setSex('男'); business1.setPhoneNumber("110110"); business1.setShopAddress("火星6号2B二层"); business1.setShopName("甜甜圈国际影城"); ALL_USERS.add(business1); // 注意,商家一定需要加入到店铺排片信息中去List<Movie>movies=newArrayList<>(); ALL_MOVIES.put(business1, movies); Businessbusiness2=newBusiness(); business2.setLoginName("dbCinema"); business2.setPassWord("123456"); business2.setUserName("赵六"); business2.setMoney(0); business2.setSex('女'); business2.setPhoneNumber("110110"); business2.setShopAddress("火星8号8B八层"); business2.setShopName("巧克力国际影城"); ALL_USERS.add(business2); // 注意,商家一定需要加入到店铺排片信息中去List<Movie>movies3=newArrayList<>(); // public Movie(String name, String actor, double time, double price, int number, Date startTime)try { Moviemovie=newMovie("阿甘正传", "汤姆汉克斯", 120, 100, 10, sdf.parse("2022-05-16 16:30:00")); Moviemovie2=newMovie("肖申克的救赎", "安迪", 120, 100, 10, sdf.parse("2022-05-16 16:30:00")); movies3.add(movie); movies3.add(movie2); } catch (ParseExceptione) { e.printStackTrace(); } ALL_MOVIES.put(business2, movies3); } publicstaticvoidmain(String[] args) { showMain(); } /*** create by: 全聚德在逃烤鸭、* description: 首页展示* create time: 2022/5/14 0014 10:38** @param* @return void*/privatestaticvoidshowMain() { System.out.println("========wc电影首页========="); while (true) { System.out.println("请选择执行功能序号:1登陆\t2用户注册\t商家注册"); Stringcommand=SYS_SC.nextLine(); switch (command) { case"1": // 登陆login(); break; case"2": // 用户注册register(); break; case"3": // 商家注册break; default: System.out.println("输入命令有误!请重新输入!"); } } } /*** create by: 全聚德在逃烤鸭、* description: 用户注册* create time: 2022/5/15 0015 21:04** @param* @return void*/privatestaticvoidregister() { } /*** create by: 全聚德在逃烤鸭、* description: 用户登陆* create time: 2022/5/14 0014 10:46** @param* @return void*/privatestaticvoidlogin() { System.out.println("========用户登陆========="); OUT: while (true) { System.out.println("请输入登陆名"); StringloginName=SYS_SC.nextLine(); System.out.println("请输入登陆密码"); StringuserPassWord=SYS_SC.nextLine(); // 根据用户名查询用户对象Useruser=getUserByLoginName(loginName); if (user!=null) { // 查询密码是否正确if (user.getPassWord().equals(userPassWord)) { // 密码输入正确loginUser=user; // 将登陆成功的对象赋值代表当前登陆对象的给静态成员变量loginUserLOGGER.info(loginUser.getLoginName() +"登陆成功!"); // 使用instanceof判断用户类型是用户还是商家if (userinstanceofCustomer) { // 用户showCustomerMain(); } else { // 否则为商家showBusinessMain(); } break; } else { // 密码输入错误System.out.println("密码错误,请重新登陆!"); } } else { System.out.println("用户名不存在!"); while (true) { System.out.println("请选择执行功能序号:1重新登陆\t2退出到首页"); Stringcommand=SYS_SC.nextLine(); switch (command) { case"1": // 重新登陆continueOUT; case"2": // 退出到首页return; default: System.out.println("输入命令有误!请重新输入!"); } } } } } /*** create by: 全聚德在逃烤鸭、* description: 商家页面* create time: 2022/5/14 0014 11:14** @param* @return void*/privatestaticvoidshowBusinessMain() { while (true) { System.out.println("===========wc电影商家界面==================="); System.out.println(loginUser.getUserName() + (loginUser.getSex() =='男'?"先生" : "女士"+"欢迎您进入系统")); System.out.println("1、展示详情:"); System.out.println("2、上架电影:"); System.out.println("3、下架电影:"); System.out.println("4、修改电影:"); System.out.println("5、退出:"); System.out.println("请输入您要操作的命令:"); Stringcommand=SYS_SC.nextLine(); switch (command) { case"1": // 展示全部排片信息showBusinessInfos(); break; case"2": // 上架电影信息addMovie(); break; case"3": // 下架电影信息deleteMovie(); break; case"4": // 修改电影信息updateMovie(); break; case"5": System.out.println(loginUser.getUserName() +"退出成功!"); return; default: System.out.println("不存在该命令!!"); break; } } } /*** create by: 全聚德在逃烤鸭、* description: 修改上架影片* create time: 2022/5/16 0016 9:19** @param* @return void*/privatestaticvoidupdateMovie() { System.out.println("===========wc电影商家修改电影界面==================="); // 将User对象转换为真正的Business对象(当前对象实际上就是Business对象,不存在转换失败)Businessbusiness= (Business) loginUser; // 根据商家对象作为键提取其对应的值(当前上架的排片信息)List<Movie>movies=ALL_MOVIES.get(business); if (movies.size() ==0) { System.out.println("影院当前无放映信息"); return; } System.out.println("请输入要修改的电影名"); StringmovieName=SYS_SC.nextLine(); // 查询是否有movieName对应的影片MoviemovieByName=getMovieByNameStrictly(movieName); if (movieByName!=null) { // 查询到了符合条件的电影对象while (true) { try { System.out.println("请您输入修改后的电影片名:"); Stringname=SYS_SC.nextLine(); System.out.println("请您输入修改后的主演:"); Stringactor=SYS_SC.nextLine(); System.out.println("请您输入修改后的电影时长:"); StringtimeStr=SYS_SC.nextLine(); doubletime=Double.parseDouble(timeStr); System.out.println("请您输入修改后的票价:"); StringpriceStr=SYS_SC.nextLine(); doubleprice=Double.parseDouble(priceStr); System.out.println("请您输入修改后的票数:"); StringnumberStr=SYS_SC.nextLine(); intnumber=Integer.parseInt(numberStr); System.out.println("请您输入修改后的影片放映时间:"); StringstartTimeStr=SYS_SC.nextLine(); DatestartTime=sdf.parse(startTimeStr); // 全部数据格式无误,将信息set修改到Movie对象中movieByName.setName(name); movieByName.setActor(actor); movieByName.setTime(time); movieByName.setPrice(price); movieByName.setNumber(number); movieByName.setStartTime(startTime); System.out.println(name+"影片修改成功!"); showBusinessInfos(); return; // 排片信息修改完毕,退出该方法 } catch (NumberFormatExceptione) { e.printStackTrace(); LOGGER.error("电影时长/票价/票数格式输入错误"); } catch (ParseExceptione) { e.printStackTrace(); LOGGER.error("时间格式出现错误"); } } } else { System.out.println("未查询到"+movieName+"相关的影片信息"); } } /*** create by: 全聚德在逃烤鸭、* description: 根据名称精确查询影片对象* create time: 2022/5/16 0016 10:37** @param movieName* @return com.itheima.bean.Movie*/privatestaticMoviegetMovieByNameStrictly(StringmovieName) { // 将User对象转换为真正的Business对象(当前对象实际上就是Business对象,不存在转换失败)Businessbusiness= (Business) loginUser; // 根据商家对象作为键提取其对应的值(当前上架的排片信息)List<Movie>movies=ALL_MOVIES.get(business); // 遍历所有的电影对象,查询是否有该名称对应的电影对象for (Moviemovie : movies) { if (movie.getName().equals(movieName)) { // 采用equals精确查询returnmovie; } } returnnull; // 遍历结束后没有查询到符合条件的影片对象,返回null } /*** create by: 全聚德在逃烤鸭、* description: 下架影片* create time: 2022/5/16 0016 9:18** @param* @return void*/privatestaticvoiddeleteMovie() { System.out.println("===========wc电影商家下架电影界面==================="); // 将User对象转换为真正的Business对象(当前对象实际上就是Business对象,不存在转换失败)Businessbusiness= (Business) loginUser; // 根据商家对象作为键提取其对应的值(当前上架的排片信息)List<Movie>movies=ALL_MOVIES.get(business); if (movies.size() >0) { System.out.println("请输入要下架的电影名"); StringmovieName=SYS_SC.nextLine(); // 查询是否有movieName对应的影片List<Movie>moviesByName=getMovieByName(movieName); if (moviesByName==null||moviesByName.size() ==0) { // 若集合为空或集合长度为0说明未查询到对应的电影对象System.out.println("未查询到"+movieName+"相关的影片信息"); } else { // 否则说明查询到符合条件的电影对象System.out.println("查询结果如下:"); showMovies(moviesByName); while (true) { System.out.print("确定要删除"); for (inti=0; i<moviesByName.size(); i++) { System.out.print(i==moviesByName.size() -1?moviesByName.get(i).getName() : moviesByName.get(i).getName() +"、"); } System.out.println("的排片信息?请输入是/否?"); Stringcommand=SYS_SC.nextLine(); switch (command) { case"是": // 将查询到的电影从当前上架的排片信息中删除for (Moviemovie : moviesByName) { movies.remove(movie); } System.out.print("删除成功,已删除"); for (inti=0; i<moviesByName.size(); i++) { System.out.print(i==moviesByName.size() -1?moviesByName.get(i).getName() : moviesByName.get(i).getName() +"、"); } System.out.println("的排片信息!"); showBusinessInfos(); return; case"否": return; default: System.out.println("输入命令有误,请重新输入!"); } } } } else { System.out.println("影院当前无放映信息"); } } /*** create by: 全聚德在逃烤鸭、* description: 根据名称模糊查询影片对象* create time: 2022/5/16 0016 9:32** @param movieName* @return java.util.List<com.itheima.bean.Movie>*/privatestaticList<Movie>getMovieByName(StringmovieName) { // 将User对象转换为真正的Business对象(当前对象实际上就是Business对象,不存在转换失败)Businessbusiness= (Business) loginUser; // 根据商家对象作为键提取其对应的值(当前上架的排片信息)List<Movie>movies=ALL_MOVIES.get(business); // 创建影片map集合,存储所有符合条件的影片List<Movie>moviesByName=newArrayList<>(); // 遍历所有的电影对象,查询是否有该名称对应的电影对象for (Moviemovie : movies) { if (movie.getName().contains(movieName)) { // 采用contains查询而不是equals,可以进行模糊查询,输入影片部分名称即可查询出影片,无需精确查询moviesByName.add(movie); // 将查询到的影片信息加入到集合中 } } returnmoviesByName; // 遍历结束后将获取的影片集合返回 } /*** create by: 全聚德在逃烤鸭、* description: 上架影片* create time: 2022/5/15 0015 20:26** @param* @return void*/privatestaticvoidaddMovie() { System.out.println("===========wc电影商家上架电影界面==================="); // 将User对象转换为真正的Business对象(当前对象实际上就是Business对象,不存在转换失败)Businessbusiness= (Business) loginUser; // 根据商家对象作为键提取其对应的值(当前上架的排片信息)List<Movie>movies=ALL_MOVIES.get(business); while (true) { try { System.out.println("请您输入新片名:"); Stringname=SYS_SC.nextLine(); System.out.println("请您输入主演:"); Stringactor=SYS_SC.nextLine(); System.out.println("请您输入电影时长:"); StringtimeStr=SYS_SC.nextLine(); doubletime=Double.parseDouble(timeStr); System.out.println("请您输入票价:"); StringpriceStr=SYS_SC.nextLine(); doubleprice=Double.parseDouble(priceStr); System.out.println("请您输入票数:"); StringnumberStr=SYS_SC.nextLine(); intnumber=Integer.parseInt(numberStr); System.out.println("请您输入影片放映时间:"); StringstartTimeStr=SYS_SC.nextLine(); DatestartTime=sdf.parse(startTimeStr); // 全部数据格式无误,将信息封装成Movie对象,加入到该商家的排片List集合中Moviemovie=newMovie(name, actor, time, price, number, startTime); movies.add(movie); // 引用类型,直接通过地址改变根数据,无需再将更新后的List集合更新到该商家对应的排片信息的map集合中System.out.println(name+"影片添加成功!"); showBusinessInfos(); return; // 排片信息添加完毕,退出该方法 } catch (NumberFormatExceptione) { e.printStackTrace(); LOGGER.error("电影时长/票价/票数格式输入错误"); } catch (ParseExceptione) { e.printStackTrace(); LOGGER.error("时间格式出现错误"); } } } /*** create by: 全聚德在逃烤鸭、* description: 展示当前登陆商家的详细信息* create time: 2022/5/15 0015 19:55** @param* @return void*/privatestaticvoidshowBusinessInfos() { System.out.println("===========wc电影商家详情界面==================="); // 将User对象转换为真正的Business对象(当前对象实际上就是Business对象,不存在转换失败)Businessbusiness= (Business) loginUser; // 展示商家信息System.out.println(business.getShopName() +"\t\t电话:"+business.getPhoneNumber() +"\t\t地址:"+business.getShopAddress() +"\t\t余额:"+business.getMoney()); // 根据商家对象作为键提取其对应的值(当前上架的排片信息)List<Movie>movies=ALL_MOVIES.get(business); if (movies.size() >0) { // 展示排片信息showMovies(movies); } else { System.out.println("影院当前无放映信息"); } } /*** create by: 全聚德在逃烤鸭、* description: 展示集合中的电影详细信息* create time: 2022/5/16 0016 9:38** @param movies* @return void*/privatestaticvoidshowMovies(List<Movie>movies) { System.out.println("片名\t\t主演\t\t时长\t\t评分\t\t放映时间\t\t票价\t\t余票数量"); for (Moviemovie : movies) { System.out.println(movie.getName() +"\t\t"+movie.getActor() +"\t\t"+movie.getTime() +"\t\t"+movie.getScore() +"\t\t"+sdf.format(movie.getStartTime()) +"\t\t"// 将影片放映时间格式化为提前设定好的格式+movie.getPrice() +"\t\t"+movie.getNumber()); } } /*** create by: 全聚德在逃烤鸭、* description: 普通用户页面* create time: 2022/5/14 0014 11:14** @param* @return void*/privatestaticvoidshowCustomerMain() { while (true) { System.out.println("============wc电影客户界面==================="); System.out.println(loginUser.getUserName() + (loginUser.getSex() =='男'?"先生" : "女士"+"欢迎您进入系统"+"\t余额:"+loginUser.getMoney())); System.out.println("请您选择要操作的功能:"); System.out.println("1、展示全部影片信息功能:"); System.out.println("2、根据电影名称查询电影信息:"); System.out.println("3、评分功能:"); System.out.println("4、购票功能:"); System.out.println("5、退出系统:"); System.out.println("请输入您要操作的命令:"); Stringcommand=SYS_SC.nextLine(); switch (command) { case"1": // 展示全部排片信息showAllMovies(); break; case"2": break; case"3": // 评分功能// scoreMovie();// showAllMovies();break; case"4": // 购票功能buyMovie(); break; case"5": return; default: System.out.println("不存在该命令!!"); } } } /*** create by: 全聚德在逃烤鸭、* description: 用户购票* create time: 2022/5/16 0016 11:16** @param* @return void*/privatestaticvoidbuyMovie() { System.out.println("============用户购票界面==================="); System.out.println("请输入购票门店名称:"); StringshopName=SYS_SC.nextLine(); // 查询是否存在该商家Businessbusiness=getBusinessByName(shopName); if (business!=null) { // 查询此商家全部排片信息List<Movie>movies=ALL_MOVIES.get(business); if (movies==null||movies.size() ==0) { System.out.println("该商家尚未上架任何电影"); } else { System.out.println("请输入购票电影名称:"); StringmovieName=SYS_SC.nextLine(); // 从当前上架上架的电影集合中查询是否存在符合条件的电影对象Moviemovie=getBusinessMovieByName(movies, movieName); // 判断是否有符合条件的电影if (movie!=null) { // 存在// 开始购买while (true) { try { System.out.println("请输入购买数目:"); StringnumberStr=SYS_SC.nextLine(); intnumber=Integer.parseInt(numberStr); // 判断该电影余票是否足够if (movie.getNumber() >=number) { // double money = movie.getPrice() * number; // 当前购票总费用// double类型直接计算可能会出现精度丢失,使用BigDecimal.valueOf方法转换,再用multiply方法计算,最后在用doubleValue方法转换回double类型doublemoney=BigDecimal.valueOf(movie.getPrice()).multiply(BigDecimal.valueOf(number)).doubleValue(); // 当前购票总费用if (loginUser.getMoney() >=money) { // 更新电影票剩余数目intticketNumber=movie.getNumber() -number; movie.setNumber(ticketNumber); // 更新用户余额doublecustomerMoney=loginUser.getMoney() -money; loginUser.setMoney(customerMoney); // 更新商家余额doublebusinessMoney=business.getMoney() +money; business.setMoney(businessMoney); System.out.println(number+"张"+movieName+"电影票购买成功!,总金额为"+money+"元,当前账户余额"+loginUser.getMoney() +"元"); } else { System.out.println("余额不足,无法购买!"); } } else { System.out.println(movieName+"余票不足,无法购买"); } return; } catch (Exceptione) { e.printStackTrace(); System.out.println("数据格式有误,请重新输入!"); LOGGER.error("数据格式有误"); } } } else { // 不存在System.out.println("未查询到"+movieName+"相关的影片信息"); } } } else { System.out.println("该商家不存在"); } } /*** create by: 全聚德在逃烤鸭、* description: 从当前上架上架的电影集合中查询是否存在符合条件的电影对象* create time: 2022/5/16 0016 14:22** @param movies 该商家当前上架的影片列表* @param movieName* @return com.itheima.bean.Movie*/privatestaticMoviegetBusinessMovieByName(List<Movie>movies, StringmovieName) { for (Moviemovie : movies) { if (movie.getName().equals(movieName)) { returnmovie; } } returnnull; } /*** create by: 全聚德在逃烤鸭、* description: 根据名称查询商家对象* create time: 2022/5/16 0016 11:22** @param shopName* @return void*/privatestaticBusinessgetBusinessByName(StringshopName) { // ALL_MOVIES.forEach((business, movies) -> {// if (business.getShopName().equals(shopName)) {// return business; // ALL_MOVIES中每个值都是business = {m1, m2, m3, ... }的键值对形式,没有独立的Business对象,不能直接返回,需要取出键集合,再返回// }// });Set<Business>businesses=ALL_MOVIES.keySet(); // 遍历businesses集合,查询是否存在某一商家,店铺名称与输入的名称相同for (Businessbusiness : businesses) { if (business.getShopName().equals(shopName)) { returnbusiness; // 若存在,则将该商家对象返回 } } returnnull; // 若遍历结束后仍未查询到,说明不存在,返回null } /*** create by: 全聚德在逃烤鸭、* description: 展示全部商家及其排片信息* create time: 2022/5/16 0016 11:05** @param* @return void*/privatestaticvoidshowAllMovies() { System.out.println("============用户查询全部商家及其排片信息界面==================="); // 增强for循环仅支持Collection集合使用,map集合使用forEach循环ALL_MOVIES.forEach((business, movies) -> { System.out.println("影院名称:"+business.getShopName() +"\t\t电话:"+business.getPhoneNumber() +"\t\t地址:"+business.getShopAddress()); showMovies(movies); }); } /*** create by: 全聚德在逃烤鸭、* description: 根据用户名查询用户对象* create time: 2022/5/14 0014 10:53** @param loginName* @return com.itheima.bean.User*/privatestaticUsergetUserByLoginName(StringloginName) { // 遍历ALL_USERS集合,查询是否存在某一用户,用户名与输入的登录名相同for (Useruser : ALL_USERS) { if (user.getLoginName().equals(loginName)) { returnuser; // 若存在,则将该User对象返回 } } returnnull; // 若遍历结束后仍未查询到,说明不存在,返回null } }
参考文献
[1]Azoner.jar包的概念及作用[J/OL].https://blog.csdn.net/Azoner/article/details/123954904,2022-04-04/2022-05-12