Java SE基础知识详解第[14]期—日志框架、阶段项目

简介: Java SE基础知识详解第[14]期—日志框架、阶段项目

日志框架、阶段项目

1.日志框架

1.1日志技术的概述

日志技术具备的优势

可以将系统执行的信息选择性的记录到指定的位置(控制台、文件中、数据库中)。

可以随时开关的形式控制是否记录日志,无需修改源代码。

日志技术的具体优势

 

输出语句

日志技术

输出位置

只能是控制台

可以将日志信息写入到文件或者数据库中

取消日志

需要修改代码,灵活性较差

不需要修改代码,灵活性较好

多线程

性能较差

性能较好

 

1.2日志技术体系结构

日志体系结构如下图所示。

LogSystem.png 

日志规范:一些接口,提供给日志的实现框架设计的标准。

日志框架:者第三方公司已经做好的日志记录实现代码,后来者直接可以拿去使用。

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

AddJar1.png

2):如下图所示,将提前下载好的jar包文件全部复制,粘贴到lib文件夹下。

AddJar2_1.png

如下图所示,在弹出的【复制】对话框中选择重构即可完成导入。

AddJar2_2.png

3):如下图所示,全部选中导入的jar包,右键选择添加为库

AddJar3_1.png

在弹出的【Creat Library】对话框中选择确定即可完成将jar包添加到项目依赖库。

AddJar3_2.png

4):如下图所示,每个jar包前都有下拉菜单按钮,且能查看其中详细文件,代表jar包整合进工程成功。

AddJar4.png

②:将Logback的核心配置文件logback.xml(xml文件是项目的核心配置文件,其中进行相关功能的配置和控制)直接拷贝到src目录下(必须是src下)

③:如下图所示,在代码中获取日志的对象。

LOGGER.png

④:使用日志对象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个日志输出位置:一个是控制台、一个是系统文件中。

输出到控制台的配置标志如下图所示。

AppenderConsole.png

输出到系统文件的配置标志如下图所示。

AppenderFile.png

logback.xml文件示例代码如下:

<?xmlversion="1.0" encoding="UTF-8"?><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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
4天前
|
Java 数据安全/隐私保护 Spring
Java 中 Spring Boot 框架下的 Email 开发
Java 中 Spring Boot 框架下的 Email 开发
34 2
|
1天前
|
安全 Java 容器
Java一分钟之-高级集合框架:并发集合(Collections.synchronizedXXX)
【5月更文挑战第18天】Java集合框架的`Collections.synchronizedXXX`方法可将普通集合转为线程安全,但使用时需注意常见问题和易错点。错误的同步范围(仅同步单个操作而非迭代)可能导致并发修改异常;错误地同步整个集合类可能引起死锁;并发遍历和修改集合需使用`Iterator`避免`ConcurrentModificationException`。示例代码展示了正确使用同步集合的方法。在复杂并发场景下,推荐使用`java.util.concurrent`包中的并发集合以提高性能。
9 3
|
1天前
|
Java 开发者
Java一分钟之-高级集合框架:优先队列(PriorityQueue)
【5月更文挑战第18天】`PriorityQueue`是Java集合框架中的无界优先队列,基于堆数据结构实现,保证队头元素总是最小。常见操作包括`add(E e)`、`offer(E e)`、`poll()`和`peek()`。元素排序遵循自然排序或自定义`Comparator`。常见问题包括错误的排序逻辑、可变对象排序属性修改和混淆`poll()`与`peek()`。示例展示了自然排序和使用`Comparator`的排序方式。正确理解和使用`PriorityQueue`能提升应用性能。
14 6
|
1天前
|
存储 Java
Java一分钟之-高级集合框架:Queue与Deque接口
【5月更文挑战第18天】本文探讨Java集合框架中的`Queue`和`Deque`接口,两者都是元素序列的数据结构。`Queue`遵循FIFO原则,主要操作有`add/remove/element/peek`,空队列操作会抛出`NoSuchElementException`。`Deque`扩展`Queue`,支持首尾插入删除,同样需注意空`Deque`操作。理解并正确使用这两个接口,结合具体需求选择合适数据结构,能提升代码效率和可维护性。
12 4
|
2天前
|
前端开发 JavaScript Java
Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)五(前端页面
Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)五(前端页面
Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)五(前端页面
|
2天前
|
存储 Java 容器
Java一分钟之-高级集合框架:LinkedList与TreeSet
【5月更文挑战第17天】这篇博客对比了Java集合框架中的LinkedList和TreeSet。LinkedList是双向链表,适合中间插入删除,但遍历效率低且占用空间大;TreeSet基于红黑树,保证元素有序且不重复,插入删除速度较LinkedList慢但查找快。选择时需根据操作需求和性能考虑。
12 2
|
3天前
|
Java
java使用AOP切面获取请求日志并记录
java使用AOP切面获取请求日志并记录
|
3天前
|
存储 算法 Java
Java 集合框架
5月更文挑战第10天
|
3天前
|
运维 监控 安全
Java一分钟之-Log4j与日志记录的重要性
【5月更文挑战第16天】Log4j是Java常用的日志框架,用于灵活地记录程序状态和调试问题。通过设置日志级别和过滤器,可避免日志输出混乱。为防止日志文件过大,可配置滚动策略。关注日志安全性,如Log4j 2.x的CVE-2021-44228漏洞,及时更新至安全版本。合理使用日志能提升故障排查和系统监控效率。
14 0
|
4天前
|
SQL 缓存 Java
Java一分钟之-Hibernate:ORM框架实践
【5月更文挑战第15天】Hibernate是Java的ORM框架,简化数据库操作。本文列举并解决了一些常见问题: 1. 配置SessionFactory,检查数据库连接和JDBC驱动。 2. 实体类需标记主键,属性映射应匹配数据库列。 3. 使用事务管理Session,记得关闭。 4. CRUD操作时注意对象状态和查询结果转换。 5. 使用正确HQL语法,防止SQL注入。 6. 根据需求配置缓存。 7. 懒加载需在事务内处理,避免`LazyInitializationException`。理解和避免这些问题能提升开发效率。
19 0

热门文章

最新文章