还剩27页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
西安培训课件Java语言简介Java诞生背景平台特点Java JavaJava语言由詹姆斯·高斯林Java最显著的特点是一次编写,(James Gosling)于1995年创建,到处运行(Write Once,Run最初名为Oak,后更名为Java其Anywhere),通过Java虚拟机设计初衷是为嵌入式电子设备提供(JVM)实现跨平台特性同时,一种平台无关的编程语言,后发展Java具备优秀的安全性、可靠性和成为通用编程语言稳定性,使其成为企业级应用的首选语言在企业级应用中的地位Java作为世界上最流行的编程语言之一,Java广泛应用于Web应用开发、移动应用(Android)、大数据处理、金融系统、电子商务平台等众多领域在西安,众多IT企业对Java开发人才有着持续的需求开发环境搭建Java安装与配置JDKJDK(Java DevelopmentKit)是Java开发的核心工具包,我们推荐使用JDK17LTS版本,它提供长期支持并包含众多现代Java特性
1.访问Oracle官网下载对应操作系统的JDK安装包
2.按照安装向导完成安装过程
3.设置JAVA_HOME环境变量指向JDK安装目录
4.将%JAVA_HOME%\bin添加到PATH环境变量
5.打开命令提示符,输入java-version验证安装常用介绍IDE集成开发环境(IDE)能极大提高开发效率•IntelliJ IDEA功能强大,智能提示出色,推荐作为主要开发工具•Eclipse开源免费,插件丰富,资源占用较少•Visual StudioCode轻量级,配合插件可用于Java开发基础语法Java变量与数据类型运算符与表达式控制流程语句Java是强类型语言,变量必须先声明后使用•算术运算符+,-,*,/,%,++,--条件语句基本数据类型•关系运算符==,!=,,,=,=•整型byte8位、short16位、int32位、long64位•逻辑运算符,||,!if条件{//代码块}else if条件{//代码块}else{//代码块}switch表达式{case值1://代码块break;•浮点型float32位、double64位•位运算符,|,^,~,,,case值2://代码块break;default://代码块}•字符型char16位Unicode字符•赋值运算符=,+=,-=,*=,/=,%=•布尔型booleantrue/false•条件运算符:引用类型运算符优先级括号一元乘除加减移位关系位运算逻辑条件赋值•类Class•接口Interface•数组Array循环语句面向对象编程基础类与对象概念面向对象三大特性类是对象的模板,定义了对象的属性和行为对象是类的封装实例,是类的具体表现隐藏对象的属性和实现细节,只对外提供公共访问方//定义一个类public classStudent{//属法通过private、protected、public等访问修饰符实性(成员变量)private String name;现private int age;//构造方法public StudentStringname,int age{this.name=name;this.age继承=age;}//方法public voidstudy{System.out.printlnname+子类继承父类的特征和行为,使得子类对象具有父类正在学习Java;}}//创建对象Student的属性和方法Java中通过extends关键字实现单继承student=new Student张三,20;student.study;多态同一个行为具有多个不同表现形式Java中多态通过方法重写和接口实现,使得同一个方法调用在不同情况下有不同表现关键字thisthis关键字指向当前对象实例,主要用于•区分局部变量和成员变量•在构造方法中调用其他构造方法常用类与Java API字符串处理包装类与自动装箱拆箱常用工具类String类是不可变的,适合需要字符串内容保持不变的场每个基本数据类型都有对应的包装类Math类提供基本的数学运算景•byte→Bytedouble result=Math.sqrt16;//
4.0int•short→ShortString str1=你好;String str2=西安max=Math.max10,20;//20double random•int→Integer;String str3=str1+str2;//你好西安=Math.random;//
0.0-
1.0之间的随机数boolean contains=str
3.contains西安;•long→Long//trueString subStr=str
3.substring0,•float→Float2;//你好•double→DoubleArrays类数组操作工具类•char→Character•boolean→BooleanStringBuilder和StringBuffer用于频繁修改字符串内容的场int[]numbers={5,2,9,1,景,前者非线程安全但性能高,后者线程安全但性能略低自动装箱基本类型自动转换为包装类3};Arrays.sortnumbers;//排序int index=自动拆箱包装类自动转换为基本类型Arrays.binarySearchnumbers,9;//二分查找StringBuilder sb=newInteger num=100;//自动装箱int value=StringBuilder;sb.appendHello.appendnum;//自动拆箱Xian;String result=sb.toString;//Collections类集合操作工具类HelloXian异常处理机制异常分类结构try-catch-finallytry{//可能抛出异常的代码int result=10/0;//会抛出ArithmeticException}catch ArithmeticExceptione{//处理特定类型的异常System.out.println除数不能为零+e.getMessage;}catch Exceptione{//处理其他类型的异常System.out.println发生异常+e.getMessage;}finally{//无论是否发生异常都会执行的代码//通常用于释放资源System.out.printlnfinally块总是执行;}Java7引入的try-with-resources语法,自动关闭资源try FileReaderfr=new FileReaderfile.txt;BufferedReader br=new BufferedReaderfr{//使用资源String line=br.readLine;//资源会自动关闭,无需finally块}catch IOExceptione{e.printStackTrace;}Java异常体系结构•Throwable(所有异常的父类)•Error(严重错误,无法处理)•OutOfMemoryError自定义异常类•StackOverflowError•Exception(可处理的异常)•检查异常(编译时异常,必须处理)•IOException•SQLException•运行时异常(非检查异常)•NullPointerException•ArrayIndexOutOfBoundsException•ClassCastException集合框架详解12接口及实现类接口及实现类Collection MapCollection是Java集合框架的根接口,用于存储一组对象主要子接口包括Map用于存储键值对,键不允许重复主要实现类包括•List(有序集合,允许重复元素)•HashMap最常用的Map实现,无序,高效,非线程安全•ArrayList基于动态数组实现,随机访问高效,适合查询操作•LinkedHashMap维护键值对的插入顺序•LinkedList基于双向链表实现,插入删除高效,适合频繁修改操作•TreeMap基于红黑树实现,键按自然顺序或指定比较器排序•Vector线程安全的动态数组,性能较低,现已较少使用•Hashtable线程安全但性能较低,现已较少使用•Set(不允许重复元素)•ConcurrentHashMap线程安全且高效的Map实现,适合并发环境•HashSet基于HashMap实现,无序,高效•LinkedHashSet维护元素插入顺序Map scores=new HashMap;scores.put张三,95;scores.put李四,85;scores.put王五,90;forMap.Entry entry:scores.entrySet{System.out.printlnentry.getKey+:+entry.getValue;}•TreeSet基于红黑树实现,元素有序排列34与区别原理及使用注意点ArrayList LinkedListHashMapHashMap基于哈希表实现,通过key的hashCode定位桶位置,使用链表或红黑树解决哈希冲突特性ArrayList LinkedList主要特点内部实现动态数组双向链表•JDK8引入红黑树优化当链表长度超过8时,转为红黑树结构•默认初始容量16,负载因子
0.75随机访问O1,高效On,低效•非线程安全,多线程环境下可能导致死循环或数据丢失插入删除On,需移动元素O1,高效使用注意点内存占用较少较多(需存储前后节点引用)•自定义类作为key时必须重写equals和hashCode方法•合理指定初始容量可减少扩容次数,提高性能适用场景频繁查询,较少修改频繁插入删除,较少查询•多线程环境下应使用ConcurrentHashMap而非HashMap多线程基础线程创建方式线程生命周期与调度Java提供多种创建线程的方式//方式一继承Thread类class MyThreadextends Thread{@Override public void run{System.out.println线程运行中...;}}//使用MyThread thread=new MyThread;thread.start;//启动线程//方式二实现Runnable接口class MyRunnableimplements Runnable{@Override publicvoid run{System.out.printlnRunnable运行中...;}}//使用Thread thread=new ThreadnewMyRunnable;thread.start;//方式三Lambda表达式(Java8+)Thread thread=new Thread-{System.out.printlnLambda线程运行中...;};thread.start;//方式四使用Callable和FutureTask获取返回值Callable callable=-{return线程执行结果;};FutureTask task=new FutureTaskcallable;Threadthread=new Threadtask;thread.start;String result=task.get;//获取返回值Java线程状态(Thread.State枚举)
1.NEW线程已创建但尚未启动
2.RUNNABLE线程正在JVM中运行或等待操作系统资源
3.BLOCKED线程被阻塞,等待获取监视器锁
4.WAITING线程无限期等待,直到被另一个线程通知
5.TIMED_WAITING线程等待指定的时间
6.TERMINATED线程已执行完毕线程同步与死锁问题线程同步方式•synchronized关键字(方法或代码块)•Lock接口及实现类(ReentrantLock等)输入输出()Java IO字节流字符流对象序列化用于处理二进制数据,如图片、音频、视频等用于处理文本数据,自动处理Unicode字符编码转换将Java对象转换为字节序列的过程,便于存储或传输•基本流InputStream、OutputStream•基本流Reader、Writer•要序列化的类必须实现Serializable接口•文件流FileInputStream、FileOutputStream•文件流FileReader、FileWriter•使用ObjectOutputStream写出对象•缓冲流BufferedInputStream、BufferedOutputStream•缓冲流BufferedReader、BufferedWriter•使用ObjectInputStream读入对象•数据流DataInputStream、DataOutputStream•转换流InputStreamReader、OutputStreamWriter•transient关键字标记不需序列化的字段•对象流ObjectInputStream、ObjectOutputStream•打印流PrintWriter•serialVersionUID用于版本控制//文件复制示例(字节流)try FileInputStreamfis=new//文本文件读写示例(字符流)try BufferedReaderreader=newFileInputStreamsource.jpg;FileOutputStream fos=new BufferedReadernewFileReaderinput.txt;FileOutputStreamtarget.jpg{byte[]buffer=new BufferedWriterwriter=new BufferedWriternewbyte
[1024];int len;while len=fis.readbuffer!=FileWriteroutput.txt{String line;while line-1{fos.writebuffer,0,len;}}=reader.readLine!=null{writer.writeline;writer.newLine;}}网络编程基础Java协议简介编程示例TCP/IP SocketTCP/IP(传输控制协议/网际协议)是互联网的基础通信协议,由多个协议组成Socket是网络通信的端点,Java提供Socket和ServerSocket类实现TCP通信•应用层HTTP、FTP、SMTP、DNS等•传输层TCP(可靠传输)、UDP(快速传输)•网络层IP、ICMP、IGMP等•链路层以太网、Wi-Fi等TCP特点•面向连接通信前需先建立连接•可靠传输保证数据完整性•流量控制防止发送方过快发送数据•拥塞控制避免网络拥塞UDP特点•无连接不需预先建立连接•不可靠不保证数据到达顺序•高效快速适合实时应用•支持广播和多播新特性介绍(及以上)Java Java8表达式流操作类使用Lambda StreamOptionalLambda表达式是Java8引入的一种简洁表示匿名函数的方式,极大简化了函数式编程Stream API提供了函数式编程风格的集合操作,支持并行处理,使代码更简洁高效Optional类是Java8引入的容器类,可以包含或不包含值,用于避免空指针异常基本语法参数-{表达式}Stream操作分为//创建Optional对象Optional optional1=Optional.ofHello;//非空•创建Stream Collection.stream、Arrays.stream、Stream.of等值Optional optional2=Optional.empty;//空值Optional optional3=//传统匿名内部类Runnable r1=new Runnable{@Override public•中间操作filter、map、sorted、distinct、limit等Optional.ofNullablegetString;//可能为null的值//检查是否存在值ifvoid run{System.out.println传统方式;}};//Lambda表达式Runnable r2=-System.out.printlnLambda方式;//带参数的•终端操作forEach、collect、reduce、count、min、max等optional
1.isPresent{System.out.println存在值+optional
1.get;}//如果有值则执行操作optional
1.ifPresents-LambdaComparator c=s1,s2-s
1.length-s
2.length;//带类型声System.out.printlns;//获取值或默认值String value1=明的LambdaBiFunction add=Integer a,Integer b-a+b;//多行List names=Arrays.asList张三,李四,王五,赵六;//筛选长度optional
2.orElse默认值;String value2=optional
2.orElseGet-Lambda表达式Consumer printer=s-{System.out.println开始打印大于1的名字并转为大写List filtered=names.stream.filtername-generateDefault;String value3=optional
2.orElseThrow-new;System.out.printlns;System.out.println打印结束;};name.length NoSuchElementException;//转换值Optional length=
1.mapString::toUpperCase.collectCollectors.toList;//optional
1.mapString::length;//链式调用String result=统计平均长度double avg=optional
3.filters-s.length names.stream.mapToIntString::length.average.orElse
5.mapString::toUpperCase.orElseUNKNOWN;0;//并行处理names.parallelStream.forEachname-processname;Java8以后的其他重要新特性•Java9模块系统、jShell、集合工厂方法•Java10局部变量类型推断var•Java11HTTP客户端API、字符串新方法•Java14Switch表达式•Java15文本块、密封类数据库基础与JDBC关系型数据库简介连接数据库步骤JDBC关系型数据库基于关系模型,数据以表格形式存储,行表示记录,列表示字段JDBC(Java DatabaseConnectivity)是Java访问数据库的标准API常见关系型数据库系统
1.加载JDBC驱动程序
2.建立数据库连接•MySQL开源、广泛应用、性能良好
3.创建Statement对象•Oracle企业级、高性能、高可用
4.执行SQL语句•SQL Server微软产品、易于管理
5.处理结果集•PostgreSQL功能丰富、开源
6.关闭资源•SQLite轻量级、嵌入式SQL语言基础//
1.注册驱动(MySQL
8.0+)Class.forNamecom.mysql.cj.jdbc.Driver;//
2.获取连接String url=jdbc:mysql://localhost:3306/mydbuseSSL=false;String username=root;String password=•DDL(数据定义语言)CREATE、ALTER、DROPpassword;Connection conn=DriverManager.getConnectionurl,username,password;//
3.创建StatementStatement•DML(数据操作语言)INSERT、UPDATE、DELETEstmt=conn.createStatement;//
4.执行SQLString sql=SELECT*FROM students;ResultSet rs=•DQL(数据查询语言)SELECT stmt.executeQuerysql;//
5.处理结果集while rs.next{int id=rs.getIntid;Stringname=•DCL(数据控制语言)GRANT、REVOKE rs.getStringname;intage=rs.getIntage;System.out.printlnID:+id+,姓名:+name+,年龄:+age;}//
6.关闭资源rs.close;stmt.close;conn.close;•TCL(事务控制语言)COMMIT、ROLLBACK操作示例代码CRUD项目管理MavenMaven简介与安装1Maven是一个项目管理和构建自动化工具,基于项目对象模型(POM)概念,可以通过一小段描述信息管理项目的构建、报告和文档Maven主要功能•依赖管理自动下载和管理项目依赖2POM文件结构解析•构建管理编译、测试、打包、部署POM(Project ObjectModel)是Maven项目的核心配置文件,以XML格式定义•项目信息管理生成文档、报告•项目模板快速创建标准化项目结构project xmlns=http://maven.apache.org/POM/
4.
0.0xmlns:xsi=http://www.w
3.org/2001/XMLSchema-instance xsi:schemaLocation=http://maven.apache.org/POM/
4.
0.0安装步骤http://maven.apache.org/xsd/maven-
4.
0.
0.xsd modelVersion
4.
0.0/modelVersion!--基本信息
1.下载Maven压缩包并解压--groupIdcom.example/groupId!--组织标识--artifactIdmy-app/artifactId!--项目标识--version
1.0-SNAPSHOT/version!--版本号--packagingjar/packaging
2.设置MAVEN_HOME环境变量!--打包方式--name我的应用/name!--项目名称--description示例项
3.将%MAVEN_HOME%\bin添加到PATH目/description!--项目描述--!--依赖配置--dependencies dependency
4.验证安装mvn-v groupIdjunit/groupId artifactIdjunit/artifactId version
4.
13.2/versionscopetest/scope/dependency/dependencies!--构建配置--buildplugins plugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactId version
3.
8.1/versionconfiguration source17/source target17/target/configuration/plugin/plugins/build/project依赖管理与构建生命周期3Maven依赖管理•坐标系统groupId:artifactId:version•依赖范围compile、provided、runtime、test、system、import•传递性依赖自动包含间接依赖•依赖冲突解决最近依赖优先、第一声明优先Maven生命周期•清理生命周期clean•默认生命周期validate、compile、test、package、verify、install、deploy•站点生命周期site常用Maven命令•mvn clean清理项目•mvn compile编译源代码•mvn test运行测试框架入门Spring核心容器与原理的生命周期Spring IOCBeanSpring框架是Java平台的开源应用框架,提供全面的基础架构支持,简化企业级应用开发Spring Bean的完整生命周期Spring的核心模块
1.实例化容器创建Bean实例
2.属性赋值设置属性值•Core核心工具类,其他模块基础
3.初始化前BeanPostProcessor.postProcessBeforeInitialization•Beans Bean工厂,实现IOC/DI
4.初始化@PostConstruct、InitializingBean.afterPropertiesSet、init-method•Context应用上下文,资源加载
5.初始化后BeanPostProcessor.postProcessAfterInitialization•SpEL Spring表达式语言
6.使用中应用程序使用Bean•AOP面向切面编程支持
7.销毁前@PreDestroy、DisposableBean.destroy、destroy-methodIOC(控制反转)原理简单的配置示例Spring传统编程中,对象创建和依赖关系维护由程序员负责而在Spring中,IOC容器接管了这些职责XML配置方式•控制对象创建、生命周期管理•反转由容器控制而非开发者!--applicationContext.xml--beans xmlns=http://www.springframework.org/schema/beans•依赖注入(DI)容器动态地将依赖关系注入到组件中xmlns:xsi=http://www.w
3.org/2001/XMLSchema-instancexsi:schemaLocation=http://www.springframework.org/schema/beans//创建ApplicationContext(IOC容器)ApplicationContext context=new http://www.springframework.org/schema/beans/spring-beans.xsd!--定义Bean--bean id=userDaoClassPathXmlApplicationContextapplicationContext.xml;//从容器获取BeanUserService userService=class=com.example.dao.UserDaoImpl/!--依赖注入--bean id=userServicecontext.getBeanuserService,UserService.class;//使用BeanuserService.addUser;class=com.example.service.UserServiceImpl property name=userDao ref=userDao//bean/beans注解配置方式基础Spring MVC客户端请求DispatcherServlet浏览器发送HTTP请求到Web服务器前端控制器接收请求并协调整个处理过程响应返回处理器映射渲染结果作为HTTP响应返回给客户端HandlerMapping确定请求应由哪个Controller处理视图解析处理ControllerViewResolver查找合适的视图并渲染结果控制器执行业务逻辑并返回ModelAndViewSpring MVC是Spring框架的一个模块,专注于Web应用开发,实现了模型-视图-控制器(MVC)设计模式设计模式介绍配置与实现MVC Spring MVCMVC将应用程序分为三个核心组件基本配置(web.xml)•模型(Model)包含业务数据和业务逻辑servlet servlet-namedispatcher/servlet-name servlet-class•视图(View)负责数据展示,如HTML页面org.springframework.web.servlet.DispatcherServlet/servlet-class init-param param-•控制器(Controller)处理用户请求,协调模型和视图namecontextConfigLocation/param-name param-value/WEB-INF/spring-mvc.xml/param-value/init-param load-on-startup1/load-on-startup/servletservlet-mapping servlet-MVC优势namedispatcher/servlet-name url-pattern//url-pattern/servlet-mapping•关注点分离,提高代码可维护性•松耦合架构,组件可独立开发和测试•支持多视图,同一模型可有不同表现形式•适合团队协作开发持久层框架MyBatis工作原理配置文件与映射文件MyBatisMyBatis是一个优秀的持久层框架,支持自定义SQL、存储过程和高级映射,消除了几乎所有JDBC代码和参数设置、结果集获取的工作主配置文件mybatis-config.xml MyBatis工作流程xml version=
1.0encoding=UTF-8!DOCTYPE configurationPUBLIC-//mybatis.org//DTD Config
3.0//EN
1.读取MyBatis配置文件mybatis-config.xml http://mybatis.org/dtd/mybatis-3-config.dtdconfiguration environmentsdefault=development
2.加载映射文件*Mapper.xml environmentid=development transactionManagertype=JDBC/dataSource type=POOLEDproperty name=driver value=com.mysql.cj.jdbc.Driver/property name=url
3.构建SqlSessionFactoryvalue=jdbc:mysql://localhost:3306/mydb/propertyname=username value=root/property
4.创建SqlSession对象name=password value=password//dataSource/environment/environments mappers
5.执行SQL语句mapper resource=UserMapper.xml//mappers/configuration
6.获取结果集并映射到Java对象
7.关闭会话映射文件UserMapper.xml xmlversion=
1.0encoding=UTF-8!DOCTYPE mapperPUBLIC-//mybatis.org//DTD Mapper
3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespace=com.example.mapper.UserMapper selectid=getUserById parameterType=int resultType=com.example.entity.User SELECT*FROM users WHERE id=#{id}/select insertid=insertUser parameterType=com.example.entity.User INSERTINTO usersusername,email,age VALUES#{username},#{email},#{age}/insert updateid=updateUserparameterType=com.example.entity.User UPDATEusers SETusername=#{username},email=#{email},age=#{age}WHERE id=#{id}/update deleteid=deleteUser parameterType=intDELETE FROMusersWHEREid=#{id}/delete/mapperMyBatis的核心组件•SqlSessionFactoryBuilder构建SqlSessionFactory•SqlSessionFactory生产SqlSession的工厂前端基础与简介Vue.js基础核心概念与后端集成HTML/CSS/JavaScript Vue.js VueJava前端三大核心技术Vue.js是一个渐进式JavaScript框架,用于构建用户界面前后端分离架构•HTML结构层,定义页面内容和结构•响应式数据绑定数据变化自动更新视图•前端Vue.js负责页面渲染和用户交互•CSS表现层,控制页面样式和布局•组件化开发界面拆分为独立可复用的组件•后端Spring Boot提供RESTful API•JavaScript行为层,实现页面交互和动态效果•虚拟DOM提高渲染性能•通信使用JSON格式通过HTTP/HTTPS交换数据•指令系统v-if、v-for、v-bind等扩展HTML能力•认证JWT JSONWeb Token实现无状态认证基本示例前后端数据交互示例Vue.js前端Vue组件!--HTML模板--div id=app h1{{message}}/h1input v-model=message buttonv-on:click=reverseMessage反转消息/button ulli v-for=item initems:key=item.id{{item.text}}/li/ul/div!--Vue实例--scriptnew Vue{el:#app,data:{message:你好,template divh2用户列表/h2button@click=loadUsers加载用户/button ulli v-Vue!,items:[{id:1,text:学习Java},{id:2,text:学习Spring Boot},{id:3,for=user inusers:key=user.id{{user.username}}-{{user.email}}/li/ultext:学习Vue.js}]},methods:{reverseMessage:function{this.message=/div/templatescriptimport axiosfrom axios;export default{data{return{users:[]}},methods:{loadUsersthis.message.split.reverse.join}}}/script{axios.gethttp://localhost:8080/api/users.thenresponse={this.users=response.data;}.catcherror={console.error加载用户失败,error;};}}}/script设计RESTful API123架构风格原则快速搭建服务数据格式处理REST Spring Boot RESTJSONREST(Representational StateTransfer)是一种架构风格,提供了设计网络应用的指导创建Spring Boot项目JSON(JavaScript ObjectNotation)是一种轻量级的数据交换格式,易于人阅读和编写,原则同时也易于机器解析和生成
1.添加依赖spring-boot-starter-web、spring-boot-starter-data-jpa
1.资源标识每个资源都有唯一的URI
2.创建实体类使用@Entity注解Spring Boot中的JSON处理
2.统一接口使用标准HTTP方法
3.创建Repository继承JpaRepository•默认使用Jackson库自动转换Java对象和JSON•GET获取资源
4.创建Service业务逻辑处理•@RequestBody将JSON请求体转为Java对象•POST创建资源
5.创建Controller使用@RestController注解•@ResponseBody将Java对象转为JSON响应体•PUT更新资源•@RestController组合了@Controller和@ResponseBody•DELETE删除资源@RestController@RequestMapping/api/productspublic classJackson注解•PATCH部分更新ProductController{@Autowired privateProductServiceproductService;@GetMapping publicList getAllProducts•@JsonProperty指定JSON属性名
3.无状态每个请求包含所有必要信息{return productService.findAll;}•@JsonIgnore忽略某个属性
4.资源表述资源可以有多种表现形式(JSON、XML等)@GetMapping/{id}public ResponseEntity•@JsonFormat格式化日期等
5.HATEOAS超媒体作为应用状态引擎getProductById@PathVariable Longid{Product product=•@JsonInclude控制哪些属性被序列化productService.findByIdid;if product!=nullRESTful API设计最佳实践{return ResponseEntity.okproduct;}•使用名词而非动词表示资源return ResponseEntity.notFound.build;}@PostMapping•使用复数名词表示集合资源public ResponseEntitycreateProduct@RequestBody Productproduct{Product saved=productService.saveproduct;URI•使用HTTP状态码表示操作结果location=•提供分页、过滤和排序功能ServletUriComponentsBuilder.fromCurrentRequest•版本控制(如/api/v1/users).path/{id}.buildAndExpandsaved.getId.toUri;returnResponseEntity.createdlocation.bodysaved;}@PutMapping/{id}public ResponseEntityupdateProduct@PathVariable Longid,@RequestBodyProduct product{product.setIdid;Product updated=productService.updateproduct;returnResponseEntity.okupdated;}@DeleteMapping/{id}public ResponseEntitydeleteProduct@PathVariable Longid{productService.deleteByIdid;returnResponseEntity.noContent.build;}}项目实战学生管理系统需求分析与系统设计数据库设计与表结构学生管理系统主要功能主要数据表设计•学生信息管理添加、查询、修改、删除学生基本信息--学生表CREATE TABLEstudentid INTPRIMARY KEY AUTO_INCREMENT,student_no VARCHAR20NOT NULL•课程管理课程信息维护、学生选课COMMENT学号,name VARCHAR50NOT NULLCOMMENT姓名,gender CHAR1COMMENT性别,birthday DATE•成绩管理录入成绩、查询成绩、成绩统计分析COMMENT出生日期,class_id INTCOMMENT班级ID,address VARCHAR200COMMENT地址,phone•用户管理管理员、教师、学生角色,权限控制VARCHAR20COMMENT电话,email VARCHAR100COMMENT邮箱,status TINYINT DEFAULT1COMMENT状态,create_time DATETIMEDEFAULT CURRENT_TIMESTAMP,UNIQUE KEYuk_student_no student_no;--课程表CREATE TABLE技术选型courseid INTPRIMARY KEY AUTO_INCREMENT,course_no VARCHAR20NOT NULLCOMMENT课程编号,nameVARCHAR100NOT NULLCOMMENT课程名称,credit DECIMAL3,1COMMENT学分,teacher_id INTCOMMENT教师•后端Spring Boot+MyBatis+MySQLID,description TEXTCOMMENT课程描述,status TINYINTDEFAULT1COMMENT状态,UNIQUE KEY•前端Vue.js+Element UIuk_course_no course_no;--选课表CREATE TABLEstudent_courseid INTPRIMARY KEY AUTO_INCREMENT,•安全Spring Security+JWT student_id INT NOT NULLCOMMENT学生ID,course_id INTNOT NULLCOMMENT课程ID,score DECIMAL5,2•项目管理Maven COMMENT成绩,semester VARCHAR20COMMENT学期,select_time DATETIMEDEFAULT CURRENT_TIMESTAMP,UNIQUE KEYuk_student_course student_id,course_id,semester;--用户表CREATE TABLEuserid INTPRIMARY系统架构KEYAUTO_INCREMENT,username VARCHAR50NOT NULL,password VARCHAR100NOT NULL,role VARCHAR20NOT NULLCOMMENT角色,real_name VARCHAR50COMMENT真实姓名,email VARCHAR100,last_login•表现层前端Vue组件,后端ControllerDATETIME,status TINYINTDEFAULT1,UNIQUE KEYuk_username username;•业务层Service接口及实现类•持久层Mapper接口及XML映射文件•数据层MySQL数据库项目实战电商后台管理123用户权限与角色管理商品管理模块实现订单处理流程设计系统角色设计商品管理主要功能订单状态流转•超级管理员系统全部权限•商品分类管理多级分类结构
1.待付款用户下单但未支付•运营管理员商品、订单、营销管理•商品属性管理规格、参数定义
2.已付款/待发货用户已支付,等待商家发货•财务人员订单、支付、退款管理•商品信息管理基本信息、图片、价格、库存
3.已发货/待收货商家已发货,等待用户收货•客服人员订单查询、客户反馈处理•商品上下架管理状态控制
4.已完成用户确认收货,订单完成权限实现方案商品相关表结构
5.已取消订单被取消(超时未支付、用户主动取消等)
1.RBAC(基于角色的访问控制)模型用户-角色-权限三层结构
6.退款/退货售后处理流程
2.使用Spring Security实现认证与授权--商品分类表CREATE TABLEproduct_categoryid INTPRIMARY KEY订单相关表结构AUTO_INCREMENT,parent_id INTDEFAULT0,name VARCHAR50NOT
3.前后端分离架构下采用JWT进行无状态认证NULL,level TINYINT,sort INTDEFAULT0,icon VARCHAR200,--订单表CREATE TABLE`order`id BIGINT PRIMARY KEY
4.菜单和按钮级别的权限控制status TINYINTDEFAULT1;--商品表CREATE TABLEproductid INTAUTO_INCREMENT,order_no VARCHAR50NOT NULL,user_id INTNOT权限相关表结构PRIMARY KEYAUTO_INCREMENT,product_no VARCHAR50NOT NULL,NULL,total_amount DECIMAL10,2NOT NULL,pay_amountname VARCHAR200NOT NULL,category_id INTNOT NULL,brand_idDECIMAL10,2NOT NULL,freight_amount DECIMAL10,2,INT,price DECIMAL10,2,original_price DECIMAL10,2,--用户表CREATE TABLE sys_userid INTPRIMARY KEYAUTO_INCREMENT,promotion_amount DECIMAL10,2DEFAULT0,payment_type TINYINTstockINTDEFAULT0,sales INTDEFAULT0,keywordsusername VARCHAR50NOT NULL,password VARCHAR100NOT NULL,COMMENT1:支付宝,2:微信,status TINYINTCOMMENT0:待付款,1:待发VARCHAR200,description TEXT,main_image VARCHAR255,real_name VARCHAR50,phone VARCHAR20,email VARCHAR100,货,2:待收货,3:已完成,4:已取消,5:售后中,receiver_name VARCHAR50,detail_content TEXT,status TINYINTDEFAULT0COMMENT0:下架,1:上status TINYINTDEFAULT1,create_time DATETIMEDEFAULT receiver_phone VARCHAR20,receiver_address VARCHAR200,架,create_time DATETIMEDEFAULT CURRENT_TIMESTAMP;--商品属性表CURRENT_TIMESTAMP,UNIQUE KEYuk_username username;--角色表note VARCHAR500,payment_time DATETIME,delivery_timeCREATE TABLEproduct_attributeid INTPRIMARY KEYCREATE TABLE sys_roleid INTPRIMARY KEYAUTO_INCREMENT,DATETIME,receive_time DATETIME,create_time DATETIMEDEFAULTAUTO_INCREMENT,product_id INTNOT NULL,name VARCHAR50NOTrole_name VARCHAR50NOT NULL,role_code VARCHAR50NOT NULL,CURRENT_TIMESTAMP,UNIQUE KEYuk_order_no order_no;--订单商品NULL,value VARCHAR200NOT NULL;--商品图片表CREATE TABLEdescriptionVARCHAR200,create_time DATETIMEDEFAULT表CREATE TABLEorder_itemid BIGINTPRIMARY KEYAUTO_INCREMENT,product_imageid INTPRIMARY KEYAUTO_INCREMENT,product_idCURRENT_TIMESTAMP,UNIQUE KEYuk_role_code role_code;--权限表order_id BIGINTNOT NULL,product_id INTNOT NULL,INTNOT NULL,image_url VARCHAR255NOT NULL,sort INTCREATE TABLEsys_permissionid INTPRIMARY KEYAUTO_INCREMENT,product_name VARCHAR200,product_image VARCHAR255,DEFAULT0;parent_id INT,name VARCHAR50NOT NULL,type TINYINTCOMMENT unit_price DECIMAL10,2,quantity INT,total_price1:菜单,2:按钮,permission_code VARCHAR50,path VARCHAR100,DECIMAL10,2;--订单操作历史表CREATE TABLEorder_historyidicon VARCHAR50,sort INTDEFAULT0,create_time DATETIMEBIGINTPRIMARY KEYAUTO_INCREMENT,order_id BIGINTNOT NULL,DEFAULT CURRENT_TIMESTAMP;--用户角色关联表CREATETABLEsys_user_role operator_user_id INT,operator_username VARCHAR50,id INTPRIMARYKEYAUTO_INCREMENT,user_id INTNOT NULL,order_status TINYINT,note VARCHAR500,create_time DATETIMErole_id INTNOT NULL,UNIQUE KEYuk_user_role user_id,DEFAULT CURRENT_TIMESTAMP;role_id;--角色权限关联表CREATETABLEsys_role_permissionidINT PRIMARYKEYAUTO_INCREMENT,role_id INTNOT NULL,permission_id INTNOTNULL,UNIQUE KEYuk_role_permissionrole_id,permission_id;单元测试与JUnit1单元测试重要性2JUnit框架使用3编写测试用例示例单元测试是软件测试的基础层次,针对代码的最小可测试单元(通常是方法)进行验证JUnit是Java生态系统中最流行的单元测试框架被测试类Maven依赖配置单元测试的好处public classCalculator{public intaddint a,int b{return a+b;}public intdivideint a,int b•提早发现缺陷,降低修复成本dependency groupIdorg.junit.jupiter/groupId{if b==0{throw newArithmeticExceptionartifactIdjunit-jupiter/artifactId version
5.
9.1/version•帮助理解和文档化代码行为除数不能为零;}return a/b;}publicscopetest/scope/dependency•为重构提供安全保障List getEvenNumbersListnumbers{returnnumbers.stream.filtern-n%2==•促进良好的代码设计
0.collectCollectors.toList;}}•自动化验证功能正确性•提高团队协作效率单元测试的特点JUnit5的主要组件•自动化可重复执行,无需人工干预•JUnit Platform在JVM上启动测试框架的基础•独立性测试之间互不影响•JUnit Jupiter新的编程和扩展模型•快速执行速度快,提供即时反馈•JUnit Vintage兼容JUnit3和JUnit4的测试•确定性在任何环境下都应产生相同结果常用注解•@Test标记测试方法•@BeforeEach每个测试方法前执行•@AfterEach每个测试方法后执行•@BeforeAll所有测试方法前执行一次(静态方法)测试类•@AfterAll所有测试方法后执行一次(静态方法)•@Disabled临时禁用测试•@DisplayName自定义测试名称•@ParameterizedTest参数化测试断言方法•assertEquals判断值是否相等•assertTrue/assertFalse判断条件是否为真/假•assertNull/assertNotNull判断对象是否为null•assertThrows判断是否抛出指定异常•assertAll组合多个断言•assertTimeout判断执行是否超时性能优化与调试技巧内存结构与垃圾回收常用调试工具介绍JVMJDK自带工具•jps列出Java进程•jstat监视虚拟机运行状态•jinfo查看和修改JVM参数•jmap生成堆转储快照•jhat分析堆转储文件•jstack生成线程快照•jcmd执行JVM诊断命令可视化工具•JConsole监视和管理Java应用•VisualVM多合一故障诊断工具•JMC(Java MissionControl)低开销监控工具•MAT(Memory AnalyzerTool)内存分析工具•Arthas阿里开源的Java诊断工具JVM内存区域调试技巧•堆(Heap)存储对象实例,是垃圾回收的主要区域•IDE断点调试条件断点、异常断点、表达式求值•新生代(Young Generation)Eden和两个Survivor区•日志分析使用合适的日志级别和信息•老年代(Old Generation)长期存活的对象•远程调试使用JPDA连接远程JVM•方法区(Method Area)存储类信息、常量、静态变量等•热部署使用JRebel等工具避免重启•JDK8前永久代(PermGen)性能监控与代码优化建议•JDK8后元空间(Metaspace)性能指标•Java栈(Java Stack)线程私有,存储局部变量和方法调用•本地方法栈(Native MethodStack)执行本地方法•响应时间请求处理的时间•程序计数器(Program CounterRegister)记录当前线程执行位置•吞吐量单位时间内处理的请求数垃圾回收算法•并发数系统同时处理的请求数•资源利用率CPU、内存、网络、磁盘等•标记-清除(Mark-Sweep)标记不再使用的对象,然后清除常见性能问题•复制(Copying)将存活对象复制到另一区域,清空原区域•标记-整理(Mark-Compact)标记后将存活对象移到一端,清除其他•内存泄漏对象无法被垃圾回收•分代收集(Generational)根据对象生命周期采用不同策略•线程竞争锁争用导致阻塞垃圾收集器•IO阻塞磁盘或网络操作阻塞线程•过度同步不必要的同步影响并发性能•Serial单线程收集器,适合小内存场景•算法低效时间复杂度过高•ParNew Serial的多线程版本优化建议•Parallel Scavenge注重吞吐量的多线程收集器常见设计模式单例模式工厂模式观察者模式确保一个类只有一个实例,并提供全局访问点工厂模式将对象的创建与使用分离,分为简单工厂、工厂方法和抽象工厂三种形式定义对象间的一种一对多依赖关系,使得当一个对象状态改变时,所有依赖它的对象都会得到通知并更新简单工厂//饿汉式单例(线程安全)public classEagerSingleton{privatestatic finalEagerSingleton INSTANCE=new EagerSingleton;//观察者接口public interfaceObserver{void updateString//产品接口public interfaceShape{void draw;}//具体产品publicprivate EagerSingleton{}public staticEagerSingleton message;}//具体观察者public classUser implementsObserverclass Circleimplements Shape{@Override publicvoid drawgetInstance{return INSTANCE;}}//懒汉式单例(双重检查锁,{private Stringname;public UserStringname{System.out.println画一个圆形;}}public classRectangle线程安全)public classLazySingleton{private staticvolatile{this.name=name;}@Override publicvoidimplements Shape{@Override publicvoid drawLazySingletoninstance;private LazySingleton{}updateString message{System.out.printlnname+收到通知:{System.out.println画一个矩形;}}//简单工厂public classpublic static LazySingletongetInstance{if instance==+message;}}//主题接口public interfaceSubject{voidShapeFactory{public staticShape createShapeStringtypenull{synchronized LazySingleton.class registerObserverObserverobserver;void removeObserverObserver{if circle.equalsIgnoreCasetype{return new{if instance==null{instance observer;void notifyObservers;}//具体主题public classCircle;}else ifrectangle.equalsIgnoreCasetype=new LazySingleton;}}}MessagePublisher implementsSubject{private Listobservers=new{return newRectangle;}throw newreturninstance;}}//静态内部类方式(线程安全,延迟加载)public ArrayList;private Stringmessage;@Override publicIllegalArgumentException不支持的图形类型;}}//使用Shape circleclassStaticInnerSingleton{private StaticInnerSingleton{}void registerObserverObserverobserver=ShapeFactory.createShapecircle;circle.draw;private staticclass SingletonHolder{private staticfinal{observers.addobserver;}@Override publicStaticInnerSingletonINSTANCE=new voidremoveObserverObserver observerStaticInnerSingleton;}publicstatic{observers.removeobserver;}@Override publicStaticInnerSingletongetInstance{return voidnotifyObservers{for Observerobserver:observersSingletonHolder.INSTANCE;}}//枚举方式(线程安全,防止序列化问题){observer.updatemessage;}}publicpublic enumEnumSingleton{INSTANCE;publicvoidvoid publishMessageStringmessage{this.message=message;doSomething{//业务方法}}notifyObservers;}}//使用MessagePublisher publisher=newMessagePublisher;Observer user1=new User张三;Observer user2=new User李四;publisher.registerObserveruser1;publisher.registerObserveruser2;publisher.publishMessage系统将于今晚进行维护;工厂方法软件开发流程与团队协作敏捷开发与介绍需求管理与版本发布Scrum敏捷开发是一种以人为核心、迭代、循序渐进的开发方法,强调需求管理流程•个体和互动高于流程和工具
1.需求收集从用户、客户、市场等来源收集需求•工作的软件高于详尽的文档
2.需求分析理解和明确需求,创建用户故事•客户合作高于合同谈判
3.需求优先级排序根据业务价值和紧急程度排序•响应变化高于遵循计划
4.需求规格说明形成需求文档或用户故事
5.需求跟踪监控需求实现状态
6.需求变更控制管理需求变更的流程版本发布管理•语义化版本号(Semantic Versioning)主版本.次版本.修订号•主版本(Major)不兼容的API变更•次版本(Minor)向后兼容的功能性新增•修订号(Patch)向后兼容的问题修正•发布策略•定期发布按固定时间周期发布•功能驱动发布完成特定功能集后发布•持续交付随时可发布的状态•发布流程•代码冻结(Code Freeze)•版本构建(Build)•测试验证(Testing)•发布准备(Release Preparation)•部署(Deployment)•监控与回滚机制(MonitoringRollback)团队协作工具推荐Scrum是最流行的敏捷开发框架,其核心要素包括需求与项目管理•角色•产品负责人(Product Owner)定义产品需求•JIRA需求管理、任务跟踪、敏捷项目管理•Scrum主管(Scrum Master)促进团队遵循Scrum流程•Trello轻量级看板工具•开发团队(Development Team)交付产品增量•禅道国产项目管理软件•事件•冲刺(Sprint)通常2-4周的工作周期代码管理与CI/CD•冲刺规划会议(Sprint Planning)规划冲刺工作•GitHub/GitLab代码托管、版本控制•每日站会(Daily Scrum)15分钟团队同步•Jenkins持续集成服务器•冲刺评审会议(Sprint Review)展示完成的工作•SonarQube代码质量管理平台•冲刺回顾会议(Sprint Retrospective)总结经验面试技巧与职业规划简历准备精心准备简历是求职的第一步,一份好的简历应当•突出个人技能和专业背景•量化成就和贡献面试应对•重点突出与应聘职位相关的经验•保持简洁明了,通常不超过2页自我介绍简洁有力,1-2分钟,包含教育背景、工作经验和技能特长•避免拼写和语法错误技术问题回答技巧简历中的项目描述应当遵循STAR法则•理解问题再回答•情境(Situation)项目背景•思考过程要口述•任务(Task)你的责任•不确定时坦诚表示•行动(Action)你做了什么•结合实际项目经验•结果(Result)取得了什么成果行为问题回答技巧使用STAR法则展示经历1234面试准备面试跟进面试前的准备工作面试后24-48小时内发送感谢邮件•研究公司背景和文化•感谢面试机会•了解职位要求和职责•重申对职位的兴趣•准备常见问题的回答•简要提及面试中的讨论点•复习技术知识点•表达期待下一步的交流•准备向面试官提问的问题跟进询问如一周后未收到回复,可礼貌跟进面试着装商务休闲或正装,视公司文化而定面试礼仪准时到达,关闭手机,保持积极的肢体语言开发常见面试题Java基础多线程与并发Java
1.Java的特点有哪些?
1.线程的创建方式有哪些?
2.基本数据类型和引用类型的区别?
2.什么是线程安全?如何实现?
3.==和equals的区别?
3.synchronized和Lock的区别?
4.final,finally,finalize的区别?
4.线程池的原理及使用场景?
5.重载和重写的区别?
5.死锁的条件及如何避免?
6.抽象类和接口的区别?
6.volatile关键字的作用?
7.String,StringBuilder,StringBuffer的区别?
7.ThreadLocal的原理及使用场景?西安培训机构介绍Java千锋教育西安华清学院西安尚硅谷IT千锋教育是全国连锁的IT培训机构,在西安设有分校华清IT学院是西安本地知名的IT培训机构尚硅谷是专注于Java培训的机构,西安校区课程全面•课程特色全日制实战班,项目驱动教学•课程特色小班授课,理论结合实践•课程特色完整的Java技术栈,企业级项目实战•师资力量来自一线互联网企业的讲师团队•师资力量多年开发经验的资深讲师•师资力量平均5年以上开发经验的讲师•就业服务提供就业指导和推荐•就业服务与本地企业合作,提供就业机会•就业服务提供终身就业服务•适合人群零基础转行者,有强烈就业意向的学员•适合人群计算机相关专业毕业生,有基础想深造的学员•适合人群有编程基础想转Java方向的学员课程内容与就业保障课程内容对比就业保障措施培训机构通常提供以下就业服务培训机构课程周期课程内容学费范围•简历指导专业HR指导简历制作千锋教育4-6个月Java基础、Web开发、框架、15000-20000元•面试技巧模拟面试训练微服务、项目实战•企业推荐合作企业优先推荐华清IT学院3-5个月Java核心、企业开发、主流框12000-18000元•就业跟踪持续跟进就业情况架、项目实训•薪资谈判提供薪资谈判建议尚硅谷5-6个月Java全栈、大数据、云原生、16000-22000元注意事项DevOps•了解就业协议的具体条款•查询历届学员的真实就业情况教学方式•警惕过高的就业承诺•理论讲解基础知识讲解,编程原理•考虑自身学习能力和就业预期•案例分析分析实际项目中的代码实现学员成功案例分享未来技术趋势云原生人工智能与机器学习云原生是设计和运行应用程序以充分利用云计算模式的方法AI技术与Java结合的发展方向•容器化Docker,Podman•Java机器学习框架Deeplearning4j,Weka•编排Kubernetes,OpenShift•自然语言处理OpenNLP,Stanford NLP•微服务架构Spring Cloud,Istio•智能应用开发结合Spring和AI服务•DevOps持续集成/持续部署•预测分析数据挖掘和模式识别•无服务器计算AWS Lambda,Azure Functions•AI辅助编程代码生成和智能补全物联网大数据处理Java在IoT中的角色Java在大数据领域的应用•嵌入式Java JavaME,JavaCard•数据处理框架Hadoop,Spark•IoT平台Eclipse IoT,AWS IoT4•流处理Kafka,Flink•边缘计算Apache EdgeX•NoSQL数据库MongoDB,Cassandra•设备管理和监控Spring forIoT•数据可视化ECharts,D
3.js•数据收集和分析MQTT,CoAP•实时分析Storm,Druid微服务架构微服务是一种架构风格,将应用程序构建为一组小型服务,每个服务运行在自己的进程中,通过轻量级机制通信微服务架构的特点•服务独立部署和扩展•技术栈多样性•业务领域划分•分布式数据管理•弹性设计Java微服务技术栈•SpringBoot快速开发微服务课程总结与答疑基础阶段Java掌握Java语言核心概念、面向对象编程、异常处理、集合框架、IO操作等基础内容,为进阶学习打下坚实基础开发阶段Web学习JDBC、Servlet、JSP、数据库操作等Web开发必备技术,了解HTTP协议和Web应用工作原理框架应用阶段深入学习Spring、SpringMVC、MyBatis等主流框架,掌握依赖注入、AOP、ORM等核心概念,提升开发效率项目实战阶段通过完整的项目实践,综合运用所学知识,培养系统分析、设计和实现能力,积累实际工作经验高级技术阶段学习微服务、分布式系统、性能优化等高级主题,了解前沿技术趋势,为职业发展奠定基础学习资源推荐常见问题答疑书籍推荐Q:Java学习周期大概需要多久?•《Java核心技术》全面介绍Java基础知识A:从零基础到能够独立开发项目,一般需要6-12个月的全职学习掌握基础语法可能只需1-2个月,但成为合格的Java开发工程师需要更多实践和项目经验•《Effective Java》Java编程最佳实践•《深入理解Java虚拟机》JVM原理与优化Q:自学和参加培训班哪个更好?•《Spring实战》Spring框架学习指南A:这取决于个人学习习惯和时间安排自学灵活性高,成本低,但需要强大的自律性和解决问题的能力;培训班有系统的课程设置和专业指导,•《设计模式》GoF经典著作但费用较高建议结合个人情况选择•《阿里巴巴Java开发手册》企业级开发规范Q:Java和Python哪个更适合新手学习?在线资源A:Python语法简洁,入门门槛低,适合快速上手;Java相对严谨,面向对象特性强,企业级应用广泛从长期就业和发展来看,两者各有优势,•官方文档Java API文档、Spring官方指南可根据个人兴趣和职业规划选择•视频教程B站尚硅谷和黑马程序员Java教程Q:西安Java开发工程师的就业前景如何?•实践平台LeetCode、牛客网编程题A:西安作为西北地区科技中心,IT行业发展迅速,Java开发人才需求稳定特别是随着西安高新区的发展,金融科技、企业服务等领域对Java•技术社区GitHub、StackOverflow、掘金开发工程师的需求持续增长•博客美团技术团队、阿里中间件团队Q:如何提高编程能力?开发工具A:多写代码,多实践项目;阅读优质开源项目代码;参与技术社区讨论;坚持刷题训练算法思维;保持学习新技术的热情编程能力提升是一•IDE IntelliJIDEA(推荐)、Eclipse个循序渐进的过程,需要持之以恒•构建工具Maven、Gradle•版本控制Git、GitHub/GitLab•接口测试Postman、Swagger。
个人认证
优秀文档
获得点赞 0