精华内容
下载资源
问答
  • 计算机三Linux应用与开发技术

    千次阅读 2021-08-23 09:31:25
    、选择题 1.操作系统负责管理计算机系统的(C),其中包括处理器、储存器、设备和文件。 A.程序 B.文件 C.资源 D.进程 2.操作系统是种(B)。 A应用软件B系统软件C通用软件D工具软件 3.操作系统是组(C)...

    第1章 计算机体系结构与操作系统

    一、选择题

    1.操作系统负责管理计算机系统的(C),其中包括处理器、储存器、设备和文件。

    A.程序 B.文件 C.资源 D.进程

    2.操作系统是一种(B)。

    A应用软件B系统软件C通用软件D工具软件

    3.操作系统是一组(C)。

    A文件管理程序 B中断处理程序 C资源管理程序 D设备管理程序

    4.多个进程的实体能存在同一内存中,在一段时间内都得到运行。这种性质称作进程的(B)。

    A动态性 B并发性 C调度性 D异步性

    5.在下列进程状态转换中,哪一个是不正确的(C)。

    A就绪 执行 B执行 就绪 C就绪 等待 D等待 就绪

    6.为了描述进程的动态变化过程,采用了一个与进程相关联的(C)系统,根据它感知进程的存在。

    A进程状态字 B进程优先数 C进程控制块 D进程起始地址

    7.已经获得除(C)以外的所有运行所需资源的进程处于就绪状态。

    A.储存器 B.打印机 C.CPU D.磁盘空间

    8.进程是(B)。

    A与程序等效的概念B在并发环境中程序的执行过程C一个系统软件D存放在内存中的程旭

    9.文件控制块的的英文缩写符号是(C)。

    A. PCB B. DCB C. FCB D. JCB

    10.操作系统的主要功能有(C)。

    A.进程管理、存储器管理、设备管理、处理器管理

    B.虚拟存储管理、处理器管理、进程调度、文件系统

    C.处理器管理、存储器管理、设备管理、文件系统

    D.进程管理、存储器管理、设备管理、中断管理

    11.计算机系统结构设计者所关心的是(C)所看到的计算机结构。

    A.硬件设计人员

    B.逻辑设计人员

    C.机器语言或汇编语言程序员

    D.高级语言程序员

    12.(D)不是RISC的特点。

    A.减少指令的平均执行周期数业

    B.规范指令格式C.减少指令和寻址方式的种类D.增加指令的功能

    13. RISC的含义是(C)。

    A. Reduced Instruction System Computer

    B. Reproduced Instruction Set Computer

    C. Reduced Instruction Set Computer

    D. Reduced Instruction System Computer

    14.虚拟存储器主要是为了(A)。

    A.扩大存储系统的容量

    B.提高存储系统的速度

    C.扩大存储系统的容量和提高存储系统的速度

    D.便于程序的访存操作

    15.在配置了通道的计算机系统中,用户程序需要输入/输出时,引起的终中断是(A)。

    A.访管中断

    B. I/O中断

    C.程序性中断

    D.外部中断

    二、填空题

    1. 按照冯诺依曼结构设计的计算机由运算器、控制器、储存器、输入设备、输出设备5部分组成。

    2. 计算机系统是由硬件软件组成。

    3. 操作系统是一个计算机系统支持的所有机器指令的集合,它常被看作软硬件之间的分界面。

    4. 根据操作数的数量不同,可以将指令格式分为零地址指令、一地址指令、二地址指令、三地址指令多地址指令

    5. 按指令的寻址空间来分,寻址方式可以分为立即数寻址、寄存器寻址、主存寻址和堆栈寻址4种。

    6. 按照指令系统复杂程度的不同,ISA可分为CISCRISC两大阵营。

    7. 程序访问的局部性包含时间局部性空间局部性两方面。

    8. Cache与主存储器间最基本的地址映射方式有3种:直接映射全相联映射组相联映射

    9. 在采用全相联映射和组相联映射的系统中,当主存向Cache传送一个新块而Cache已满时,就需要使用替换算法将Cache中的某一块换出。常用的替换算法有随机法、先进先出法和最近最少使用法

    10. Cache与主存之间的数据一- 致性通过Cache特定的写操作方式来保证,两种常用的Cache 写方式为写直达和写回

    11. MESI是最为经典的缓存一致性协议。MESI协议将CacheLine的状态分成修改、独占、共享和失效

    12. 按照冯诺依曼体系结构,传统的单核CPU由运算器控制器这两个主要部件组成。

    13. 按照计算内核对等与否,多核处理器可分为同构多核和异构多核

    14. 操作系统应具备五大基本功能:处理器管理、储存管理、设备管理、文件管理和作业管理

    15. 处理器的运行状态一般分为内核态和用户态

    16. 进程控制块是进程存在的唯一标志。

    三、简答题

    1.简述冯.诺依曼体系结构的要点。

    计算机的数字采用二进制程序,指令和数据统一储存,计算机应该按照程序顺序执行。按照冯诺依曼结构设计的计算机,由控制器,运算器,储存器,输入设备,输出设备五部分组成。

    2.简述计算机系统的层次结构。

    把计算机系统按功能可以分为多级层次结构,第零层是数字逻辑层,第一层是微体系结构层。第二层是传统机器层,第三层是操作系统层,第四层是汇编语言层,第五层是高级语言层,第六层是应用程序层

    3.计算机中的存储系统通常是什么样的层次结构?

    现代通用计算机中的储存系统通常是第一层为寄存器组。第二层为高速缓冲存储器cache第三层为主储存器,第四层为辅助储存器,第五层为脱机存储器。存储介质越往上速度越快,价格越高,越往下容量越大。

    4.简述时间局部性与空间局部性。

    时间局部性是指最近访问过的内容很可能会在短期内被再次访问。如程序中的循环循环体的指令要被反复执行。空间局部性是指某个储存单元被访问,短时间内其附近的存储单元也会被访问。

    5.操作系统的基本特征有哪些?

    现代通用操作系统一般都具有并发共享,虚拟和异步这四个基本特征,并发是指两个或多个事件在同一时间间隔内发生。共享是指计算机系统中的软硬件资源可被多个并发执行的进程共同使用,而不是被一个进程所独占。虚拟是指把一个物理上的实体变为一个或多个逻辑上的对应物。异步又称随机性或不确定性,是指在相同的计算机环境及相同的初始条件下。同一数据集上运行的同一程序,每次执行的顺序和所需时间都不一定相同。

    6.进程与程序有什么区别?

    进程是一个动态概念,而程序则是一个静态概念。进程具有并发特征,而程序没有进程有生命期。他只在计算机运行期间才有可能存在。程序可以在外存上长期保存,进程与程序之间并不总是一一对应的,一个程序执行在不同的数据集上。就成为不同的进程,进程与程序的组成不同。进程实体的组成包括程序,数据和进程控制块。

    第二章 Linux系统概述

    一、选择题

    1.以下操作系统不属于Linux家族的是(C)。

    A. Ubuntu B. CentOs C. Solaris D. Red Hat

    2.Linux之父是(B)。

    A. Andrew S.Tanenbaum

    B. Linus Torvalds

    C. Dennis Ritchie

    D. Ken Thompson

    二、填空题

    1. 从技术上来说,Linus Torvalds开发的Linux只是一个内核。内核指的是一个提供设备驱动、文件系统、进程管理、网络通信等功能的系统软件,内核并不是一套完整的操作系统,他只是操作系统的核心。

    2. 安卓系统是基于LINUX的开源系统,主要适用于便携设备,如智能手机和平板计算机等,是Goole公司为移动端打造的真正的开放和完整的移动软件。

    第三章 Linux系统使用基础

    一、选择题

    1.可以设定使用者密码的指令是(C)。

    A. pwd

    B. newpwd

    C. passwd

    D. password

    2.echo 指令表示不换行的选项是(B)。

    A. -m

    B. -n

    C. -l

    D. -e

    3.切换工作目录的命令是(B)。

    A. pwd

    B. cd

    C. who

    D. ls

    二、填空题

    1. 用户登录Linux系统后,打开shell,看到命令提示符,载默认的情况下,如果是超级用户,提示符是#,家目录在/root,如果是普通用户,提示符就是$,家目录在/home/登录名.

    2. Linux命令的基本格式是命令 [选项] [参数].

    3. 执行[root@localhost ~ ]# echo -e “ab\bc”的结果是ac.

    4. Linux下的软件包可分为两种,分别是源码包二进制包

    5. 目前Linux下主要又两大主流的二进制报管理系统:RPMDPKG

    第四章 shell脚本编程基础

    一、选择题

    1.已知,执行“[student@localhost~] $ ls”的结果是:chapter chapter1 chapter123 oschapter1那么,执行“[student@localhost~] $ cat chapter[0-9]”的结果是(A).

    A. chapter1 chapter123

    B. chapter chapter1 chapter123

    C. chapter1 chapter123 chapter1

    D. chapter chapter1 chapter123 oschapter1

    2.已知,执行“[student@localhost~] $ cat file”的结果是:

    This is chapter.

    This is chapter123

    This is oschapter1

    则执行“[student@localhost~] $ grep chapter[0-9]*file”的结果是:D

    A. This is chapter.

    This is chapter123

    B. This is chapter123.

    This is oschapter1

    C. This is chapter.

    This is chapter1

    D. This is chapter.

    This is chapter123

    This is oschapter1

    3.执行“[student@localhost~] $ x=”命令后,需要输出字符,则应执行的命令是(D)。

    A.echo *

    B.echo $x

    C.echo ‘$x’

    D.echo “$x”

    4.执行“[student@localhost~] $ nu = aaa”命令后,希望nu的值是aaabbb,则应执行的命令是(C)。

    A.nu = $nubbb

    B.nu = {$nu}bbb

    C.nu = ${nu}bbb

    D.echo $(nu)bbb

    5.在bash中,在一条命令后加入“2>&1”,表示(C)。

    A.标准错误输出重定向到标准输入

    B.标准输入重定向到标准错误输出

    C.标准错误输出重定向到标准输出

    D.标准输出重定向到标准输入

    二、填空题

    1. shell本身是一个用C语言编写的程序,他是连接用户Unix/Linux内核和桥梁,用户的大部分分工作都是通过shell完成的。

    2. 脚本的第一行“#!/bin/bash”的作用是说明该脚本是用哪一种shell编写的,通常放在脚本的第一行,从而调用相应的解释程序予以执行

    3. 环境变量PATH党的作用是决定了shell将到哪些目录中寻找命令或可执行程序,当用户运行一个命令或可执行程序时,Linux在这些目录下按顺序一次搜寻

    4. 当用户启动shell时,这个shell是交互的,当他执行完一条命令后,接着显示另一个提示符,始终在前台等待用户。还有一种shell是非交互的,当在交互shell中运行一个外部命令或者执行一个脚本时,交互shell会创建一个子shell,运行结束后子shell进程结束。

    5. 后台进程在运行过程中与用户无交互,五交互是指不响应用户的输入和中断控制信号,在后台运行的·命令一样会将结果输出到显示器上。

    第五章 用户管理

    一、选择题

    1.在默认情况下,管理员创建了一个用户,就会在(B)目录下创建一个用户主目录。

    A./usr

    B./home

    C./root

    D./etc

    2.存放用户密码信息的目录是(B)。

    A./boot

    B./etc

    C./var

    D./dev

    3.删除一个用户的同时,删除用户家目录的参数是(C)。

    A.rmuser -r

    B.deluser -r

    C.userdel -r

    D.usermgr -r

    4.在以下命令中,可以将用户身份临时改变为root的是(B)

    A.SU

    B.su

    C.login

    D.logout

    5.显示Linux系统中注册用户数(包含用户系统)的命令是(D)

    A.account -l

    B.nl /etc/passwd |head

    C.wc –users /etc/passwd

    D.wc –lines /etc/passwd

    二、填空题

    1. 用户密码信息存放在Linux系统中/etc下的shadow文件中。

    2. /etc/passwd文件的权限是rw-r--r--,/etc/shadow 文件的权限是r-- --- ---

    3. 每个用户都可以加入多个附加组,但是只能属于一个初始

    4. 使用su命令时,有 – 和没有 – 是完全不同的, - 选项表示在切换用户身份的同时,将当前使用的环境变量也切换成指定用户

    5. 普通用户只能使用passwd命令修改自己的密码,而不能修改其他用户的密码。超级用户root既可以使用passwd命令修改自己的密码,也可以修改其他用户的的密码。

    第六章 文件管理

    一、选择题

    1.用ls -l 命令列出下面的文件列表,(D)是软连接文件。

    A.-rw-rw-rw- 2 stu users 56 Sep 09 11:05 file1

    B.-rwxrwxrwx 2 stu users 56 Sep 09 11:05 ex1

    C.drwxr—r—1 stu users 1024 Sep 10 08 :10 zhang

    D.lrwxr—r—1 stu users 2024 Sep 12 08:12 cheng

    2.为了达到使文件的所有者有读和写权限的目的,而同组用户和其他用户只能进行只读访问,在设置文件的许可值时,应当设为(B)。

    A.566

    B.644

    C.655

    D.744

    3.用户编写了一个文件file,想将该文件名称改为text,下列能实现该功能的命令是(D)。

    A.cd file text

    B.echo file > text

    C.rm file text

    D.cat file > text

    4.使用ln命令生成了一个指向文件old的符号链接new,如果将文件old删除,是否还能够访问文件中的数据?A

    A.不可能再访问

    B.仍然可以访问

    C.能否访问取决于文件的所有者

    D.能否访问取决于文件的权限

    5.cd ~命令的含义是(D)。

    A.到当前目录

    B.到根目录

    C.到/root目录

    D.到用户的家目录

    二、填空题

    1. 在Linux系统中,所有的文件和目录都被组织成以(根节点“/”)开始的倒置的树状结构,文件系统(按名)访问文件。

    2. 说明目录或文件名位置的方法有两种,分别使用(绝对路径)(相对路径)。前者指的是从根目录(/)开始写起的文件或目录名称,而后者则指的是相对于当前路径的文件或目录名称。

    3. 根据文件数据项是否具有结构,可以将文件分成两大类:(无结构文件)(有结构文件)。但是通常情况下是这样划分Linux文件类型的,即(普通文件)、(目录文件)、(设备文件)、及(符号链接文件)

    4. 硬链接的限制比较多,既不能跨(文件系统),也不能链接(目录)

    5. Linux操作系统中默认的文件权限是0022,但第1个0代表的是文件(特殊权限)权限。

    第七章 进程管理

    一、选择题

    1.使进程无条件终止,使用的命令是(A)。

    A.kill -9

    B.kill -15

    C.killall -1

    D.kill -3

    2.在应用程序启动时,设置进程的优先级的命令是(B)。

    A.priority

    B.nice

    C.renice

    D.setpri

    3.在ps命令中用来显示所有用户进程的参数是(A)。

    A.a

    B.b

    C.u

    D.x

    4.在使用kill命令来终止一个很消耗资源的进程的时候,最合适的信号值是(B)。

    A.15

    B.9

    C.1

    D.0

    5.以下哪个命令可以终止一个用户的所有进程(D)。

    A.skillall

    B.skill

    C.kill

    D.killall

    二、填空题

    1. 僵尸进程的产生一般是由于进程(非正常停止)或程序编写错误,因此(子进程)先于(父进程)结束,而(父进程)又没有正确的回收(子进程),从而(子进程)一直存在内存当中,这就是僵尸进程。

    2. 缓存是在读取硬盘中的数据时,把最常用的数据保存在(内存)的缓存区中,再次读取该数据时,就不去(硬盘)读取了,而在(内存)中读取。缓冲是在向硬盘写入数据时,先把数据放入(内存缓冲区),然后再一起向硬盘写入,把(分散的写操作)集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。

    3. kill命令用来向进程发送一个信号,默认信号是15,表示(正常结束进程);-9信号表示(强制结束进程)

    4. 在Linux系统中,有两个参数表示进程优先级:(PRI)(NI)。其中,(PRI)是由内核动态调整的,用户不能直接修改。所以用户只能通过修改(NI)来影响(PRI)值,从而间接的调整进程优先级。

    第八章 储存管理

    一、选择题

    1.从当前系统中卸载一个已装载的文件系统的命令是(A)。

    A.umount

    B.dismount

    C.mount -u

    D.从/etc/fstab中删除这个文件系统项

    2.用来装载所有在/etc/fatab中定义的文件系统的命令是(B)。

    A.amount

    B.mount -a

    C.fmount

    D.mount -f

    3.用来显示系统各个分区中inode使用情况的命令是(A)。

    A.df -i

    B.df -H

    C.free -b

    D.du -a -c /

    4.使用fdisk工具进行磁盘分区操作时,最后要保存所做的修改,应该使用命令(B)。

    A.q

    B.w

    C.s

    D.d

    5.为了能够把新建立的文件系统装载到系统目录中,还需要指定该文件系统在整个目录结构中的位置,称为(B)。

    A子目录

    B挂载点

    C新分区

    D目录树

    二、填空题

    1. 机械硬盘的逻辑结构主要分为(磁道)、(扇区)和(柱面)

    2. 固态硬盘和传统的机械硬盘最大的区别就是不在采用盘片进行数据存储,而采用(存储芯片)进行数据存储。

    3. 所有的硬件设备必须(挂载)之后才能使用,有些硬件设备(比如硬盘)在每次系统启动时会(自动挂载),而有些(比如U盘、光盘)则需要(手动挂载)

    4. 挂载指的是将硬件设备的(文件系统)和LINUX系统中的文件系统通过(指定目录(作为挂载点))进行关联。

    第九章 设备管理

    一、选择题

    1.在大多数Linux系统发行版本中,以下属于块设备的是( B)。

    A.串行口

    B.硬盘

    C.虚拟终端

    D.打印机

    2.可以查看Linux系统启动信息的命令是(B)。

    A.mesg -d

    B.dmesg

    C.cat /etc/mesg

    D.cat /var/mesg

    3.在 Linux系统中,第一块IDE磁盘的名字为(C)。

    A./dev/sdb

    B./dev/sdc

    C./dev/sda

    D,dev/sdd

    4.查看swap空间使用情况的命令是(C)

    A.df

    B.swapon

    C. free

    D.fdisk

    5.在 MBR的组成中,前446字节(D)。

    A.存储主分区的信息

    B.存储逻辑分区的信息

    C.用于系统进行跳转,将CPU控制权交给某一个操作系统

    D.用于存储 Linux系统引导信息

    二、填空题

    1. Linux 系统采用(设备文件)统一管理硬件设备,从而将硬件设备的特性及管理细节对用户隐藏起来,实现用户程序与设备无关性。从用户的角度来看,对设备的使用和一般文件的使用一样。

    2. 在/dev目录下,每一个驱动器以一个单独的设备文件来表现;设备的文件名一般由两部分构成,第一部分是(主设备号),第二部分是(次设备号)

    3. /dev/null文件是空设备,看作“黑洞”,它等价于一个(只写文件),所有写入它的内容都会永远丢失。

    4. 按照是否对应物理实体,设备可以分为两种:一种是(物理设备),即对实际存在的物理硬件的抽象;另一种是(虚拟设备),即不依赖于特定的物理硬件,仅是内核自身提供的某种功能。

    第十章 网络管理

    一、选择题

    1.在Linux系统中,可能是以太网网络接口的是( B)。

    A.10

    B.eth2

    C. net0

    D.neta

    2.可列出所有当前活跃的网络接口的命令是( C)。

    A. ifconfig

    B.lsnet

    C.shownet

    D.以上都不是

    3.第一个以太网接口的设备节点是( C)。

    A./dev/net0

    B./dev/eth0

    C./ dev/net/eth0

    D.问题有误导性,因为网络接口不与设备节点关联

    4.习惯上分配给回环接口的IP地址和子网掩码是(B)。

    A.127.0.0.0/255.255.255.0

    B.127.0.0.1/255.255.0.0

    C.127.0.0.1/255.0.0.0

    D.127.0.0.0/255.255.0.0

    5.与B类IP网络关联的子网掩码是(C)。

    A.255.255.255.255

    B. 255.255.255.0

    C.255.255.0.0

    6.用来将以以太网MAC地址和一个IP地址关联起来的网络协议是( C)。

    A.IP

    B.TCP

    C.ARP

    D.255.0.0.0

    7.定义本地主机名和IP地址间转换的文件是(D)。

    A./etc/ ip.conf

    B./etc/ resolv.conf

    C./etc/ hosts

    D./etc/sysconfig/ dns

    8.用来将主机名解析为地址的网络协议是(B)。

    A.IP

    B. DNS

    C. ARP

    D. TCP

    9.可直接检验LinuX内核当前定义的主机名的命令是(D)。

    A. ipname

    B. host

    C. ifconfig

    D.hostname

    10.可将 Linux 内核的主机名设置为stationl.example.com的命令是(A )。

    A. hostname station.example.com

    B.hostname-sstation.example.com

    C. ipconfig-h station.example.com

    D. ipconfig station.example.com

    11.可准确定义 Linux内核的主机名,并使其在启动时被自动设定的文件是(D)。

    A./etc/sysctl.conf

    B./etc/sysconfig/network-scripts/ ifefg-eth0

    C./etc/ resolv.conf

    D./etc/hosts

    12.可启用安装了红帽 Linux系统的机器,使其充当路由器角色的文件是( B)。

    A./etc/sysctl.conf

    B./etc/sysconfig/ network

    C./etc/resolv.eonf

    D./etc/sysconfig/ network/scripts/ifcfg-eth0

    13.在适当的文件中,用来启用路由功能的参数名称是( C)。

    A.kernel.sysrq

    B. net. ipv4.conf.default.ip_filter

    C. net.ipv4.ip_filter

    D. net.ipv4.route

    14.可用来确定两台机器间底层IP连接性的程序是(D )。

    A. host

    B.netstat

    C.ifconfig

    D.ping

    15.用来直接执行DNS 主机名解析的程序是(C)。

    A. tcpdump

    B. host

    C. system-config-network-tui

    D.ifconfig

    16.用来追踪数据包在IP网络间穿行路径的程序是( A)。

    A. traceroute

    B.ping

    C. host

    D. tcpdump

    17.用来截取使用HTTP协议(端口80)的网页浏览器和网页服务器间数据传输的命令是(B)。(只在端口80将数据传送给网而服务器,并将传输记录用二进制格式保存在文件 http.capture中)

    A. tcpdump -o http.capture-p 80

    B. tcpdump-p 80>http..capture

    C. tcpdump 80

    D. tepdump-c http.capture-s 80

    二、填空题

    1. Linux网络接口配置文件名都以(ifcfg)为前缀,文件中变量(DEVICE)用来定义该文件含有哪个接口的配置信息。

    2. 通讨DHCD 获得信息的机器没有固定的IP地址,用(ifup)命令增加网络接口时,系统动态获得一个IP地址,用(ifdown)命令减少网络接口时,系统就释放一个IP地址。

    3. ping命令可以测试网络中本机系统是否能到达(一台远程主机),所以常常用于测试网络的(连通性)

    4. DNS实际上是分布在Internet上的主机信息的数据库,其作用是实现(IP地址)(主机名)之间的转换。

    5. Apache是实现WWW服务器功能的应用程序,通常所说的“浏览Web服务器”,在(服务器端)为用户提供浏览(Web服务)的就是 Apache应用程序。

    三、简答题

    1.计算机的基本网络参数包括哪些?

    (1)IP地址:一个IP地址标识一块网卡接口,主要由网络号和主机号组成。

    (2)子网掩码:IP地址必须和子网掩码成对出现,子网掩码用来确定网络部分的位数,在I地址中对应子网掩码为1的位为网络部分。

    (3)网关:网关的功能是跨区域通信。

    (4)DNS: DNS将域名和IP进行映射。

    2.HTTP协议的全称是什么?它是起什么作用的协议?

    HTTP 协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写。HTTP 协议与TCP/P协议族内的其他众多的协议相同,用于客户端和服务器之间的通信。

    3.ifconfig可以配置网卡的IP地址等参数,这与修改配置文件有什么差别?

    ifconfig暂时改变网络参数,并不写入配置文件,因此当计算机重新启动后,还是从配置文件中设置网络参数。

    第十一章 系统服务与日志

    一、选择题

    1、在Linux终端启动 Apache的命令为( A)。

    A. service httpd start

    B. service start

    C.httpd start

    D.start

    2.在终端输入service named restart命令将(C)服务器。

    A.启动

    B.停止

    C.重启

    D.配置

    3.Linux系统的日志文件通常保存在( A)。

    A./var/log

    B./usr/adm

    C./etc/

    D./var/ run

    二、填空题

    1. Linux系统服务有时也称为(守护程序),是在 Linux系统启动时(自动加载)并在Linux系统退出时自动停止的系统任务。

    2. 如果依据守护程序的启动与管理方式来区分,基本上可以将守护程序分为(可独立启动的服务)(通过一个总管程序来同一管理的服务)这两大类。

    3. 独立的服务要想启动,主要有两种方法,一种是(使用/etc/init.d/目录中的启动脚本来启动独立服务),另一种是(使用service命令来启动独立的服务)

    4. 系统中的绝大多数日志文件是由(rsyslogd服务)来统一管理的,只要各个进程将信息给予这个服务,它就会自动地把日志按照特定的格式记录到不同的日志文件中。也就是说,采用(rsyslogd服务)管理的日志文件,它们的格式应该是统一的。

    5. rsyslogd服务是依赖其配置文件(/etc/rsyslog.conf)来确定哪个服务的什么等级的日志信息会被记录在哪个位置的。

    第十二章 VI编辑器

    一、选择题

    1.在命令模式下进入文本编辑模式的操作是( A)。

    A.输入a/i/o等

    B.按ESC键

    C.按:键

    D.按Z键两次

    2.在VI编辑器中打开文档,默认是不显示行号的,输人(B)让它显示行号。

    A. set ruler

    B. set nu

    C. set ic

    D.set nonu

    3.下列命令不属于删除操作的是(B)。

    A.5db

    B.5yb

    C. 5dw

    D.5dd

    4.用户在编辑模式下误删了一个字符,按(D)键可以撤销删除的内容。

    A.Ctrl+Z

    B.Ctrl+Y

    C.D

    D.U

    5.在VI编辑器最后一行显示“4 lines yanked”,则所输入的命令是(C)。

    A.4yb

    B.4p

    C. 4yy

    D.4yw

    6.如果用户想在每次对文件进行编辑时都收到反馈信息,可以输入(D)。

    A. set scroll =0

    B.set shiftwidth =0

    C. set wrapmargin=0

    D.set report=0

    7.在VI编辑器中打开文档后,想把10—15行中的第一个“abc”替换为“efg”,应输入的命令是(A )。

    A.10,15s/abc/efg

    B. 10,15s/abc/ efg/g

    C. 10,15s/efg/abc

    D.10,15s/efg/ abc/g

    8.如果用户希望显示简短的错误信息,需要设置(B)参数。

    A.ignorecase

    B. terse

    C.showmode

    D.autoindent

    二、填空题

    1. VI的工作模式主要有(命令模式)(文本编辑模式)(末行模式)

    2. 写出下列命令的含义:

      (1)$:(移动到当前行的行尾)
      (2)? VI:(在文本内容中查找与“VI”对应的内容)
      (3)5dd:(删除从当前行开始的五行)
      (4)1,$ s/VI/Emacs/g:(在整个文件中用“Emacs”替换所有“VI”)
      (5)3yy GP:(复制从当前行开始的第三行,并粘贴到文件末行的行首)

    1. set命令用来设置选项,这些选项可以分为: (布尔触发器)(数学式)(串)

    2. 编辑examnle.txt文件把第3行到10行之间的字符串is都替换为are,在末行模式下输入(3,10/is/are/g)

    3. 缓冲区命令格式为(缓冲区名+命令)

    4. 删除从16行到20行的所有内容,应输入命令(16G 5dd)

    5. 输入命令2p的含义是(将缓冲区2的内容复制到光标所在位置)

    6. 用vi命令打开一个文档后,让光标跳到第4行,应输入命令(4G),跳到最后一行,应输入命令(G)

    7. 将3至7行的内容复制到第1行行首应输入命令(3G 5yy 1G P)

    第十三章 Emacs

    一、选择题

    1.在 Emacs的界面中显示状态信息的是(B)。

    A回显行

    B.模式行

    C.窗口区域

    D.标题栏

    2.可以实现打开另一个文件以巷换当前打开文件的操作是(D )。

    A.先按Ctrl+X组合键,再按 Ctrl+I组合键

    B.先按 Ctrl+X组合键,再按 Ctrl+F组合键

    C.先按 Ctrl+X组合键,再按Ctrl+B组合键

    D.先按 Ctrl+X组合键,再按 Ctrl+V组合键

    3.将光标向前移动一屏的命令组合键是(A)。

    A. Ctrl+V

    B.Alt+V

    C.Ctrl+B

    D. Alt+B

    4.如果用户想要撤销上次的修改,可以使用的命令是(A)。

    A.先按Ctrl+X组合键,再按U键

    B.先按Ctrl+X组合键,再按Backspace键

    C.按 Backspace键

    D.按空格键

    5.命令“先按Ctr1+X组合键,再按3键”表示的含义是(D)。

    A.删除当前窗口

    B.删除当前窗口外的所有窗口

    C.将当前窗口水平分割为两个窗口

    D.将当前窗口垂直分割为两个窗口

    6.模式行的显示模式字段中“%%”表示(C )。

    A,缓冲区未被编辑

    B.缓冲区中的文本已经被修改

    C.缓冲区中的文本未被修改

    D.只读缓冲区中的文本已经被修改

    7.下列不属于光标移动命令的组合键是(C)。

    A. Ctrl+F

    B.Ctrl+A

    C. Alt+D

    D. Alt+B

    8.如果用户发现输入了错误的命令,可以使用的撤销命令是(A)。

    A.同时按Ctrl+G组合键

    B.先按Ctrl+X组合键,再按U键

    C.先按Ctrl+X组合键,再按Backspace键

    D.Ctrl+空格键

    二、填空题

    1. Emacs的界面包括(标题栏)(菜单栏)(窗口区域)(模式行)(回显行)

    2. 模式行显示信息为“U: - example. Txt All L3 (Text)”,则光标处于第(3)**行。

    3. 写出下列命令按键的含义:

      (1)Ctrl+E:(将光标移动到当前行的行尾)

      (2)Ctrl+R:(向后递增搜索)

      (3)Ctrl+W:(删除两个位置之间的所有文本)

      (4)Alt+D:(删除光标后的一个单词)

      (5)Alt+C:(首字母改为大写)

    4. 写出下列含义所对应的命令:

      (1) 保存文件并退出 Emacs:(先按Ctrl+X组合键,再按Ctrl+S组合键)

      (2) 不保存文件退出 Emacs:(先按Ctrl+X组合键,再按Ctrl+C组合键)

      (3) 另存为文件:(先按Ctrl+X组合键,再按Ctrl+W组合键)

    5. 重排是对文本中的内容进行操作,选中的一段文字表示区域,区域的起点叫作(标记),光标移动到的位置和标记之间就是区域,光标在文本中的位置叫作(光标点)

    6. 若回显行显示“Find file:/tmp/,说明用户执行了搜索并打开文件命令(先按Ctrl+X组合键,再按Ctrl+F组合键)

    7. 如果用户在使用Emacs时遇到问题,可以使用命令(Ctrl+H)调用 Emacs的帮助。

    8. 用户如果想查看在 Emacs中保存的文件,可以通过(Enter键)命令查看文件列表。

    第十四章 OpenSSH

    一、选择题

    1.SSH是(A)协议。

    A.安全外壳

    B、请求-响应

    C.地址解析

    D.动态主机配置

    2.在以下协议中,为远程登录会话和其他网络服务提供安全性的协议是(C)。

    A. FTP

    B. HTTP

    C.SSH

    D. ICMP

    3.SSH 采用的加密算法为(B )。

    A. MD5

    B.RSA

    C. DES

    D.PGP

    4.以下关于OpenSSH 描述正确的是(C)。

    A.是一个用于地址解析的程序

    B.OpenSSH常用于为http协议加密

    C. OpenSSH 用于提高远程登录访问的安全性

    D.它和 telnet 实用同样的端口号

    5.OpenSSH的默认端口号为(D )。

    A.80

    B.8080

    C.21

    D.22

    二、填空题

    1. SSH是由IETF(the Internet Engineering Task Force)制定的建立在应用层基础上的(安全网络)协议。

    2. SSH是专为(远程登录)会话和其他网络服务提供安全性的协议。

    3. SSH 采用了(非对称加密技术)加密所有传输的数据。

    4. (SFTP)是安全文件传送协议,可以为传输文件提供一种安全的加密方法。

    5. (SCP)是用来进行远程文件复制的,并且整个复制过程是加密的。

    6. 开启防火墙的22号端口命令为:

      #sudo firewall-cmd --zone = public(--and-port=22/tcp)--permanent

    第十五章 Linux系统的应用程序开发技术

    一、选择题

    1.使用gdb命令对源码进行查找时,应选择的命令是(C)。

    A. run

    B.clear

    C.list

    D. print

    2.使用gdb命令查看某个恋量的类型时,应使用的命令是(B)。

    A. set

    B. whatis

    C.kill

    D. print

    3.在使用gcc命令时,如果想产生调试信息.需要加人的选项是( C)。

    A.-w

    B.-I

    C.-g

    D. -d

    4.下面关于make命令,说法错误的是( C)。

    A. make工具可以用来维护程序模块关系和生成可执行程序

    B.make命令是GNU的工程化编译工具,它用干编译大量百相关联的源代码

    C. makefile文件中目标文件后面跟的是源文件,最后是生成源文件的命令

    D.make命令从 makefile文件中获取模块之间的依赖关系

    二、填空题

    1. 在执行make命令后, make工具会首先在当前目录下查找(makefile)文件。

    2. 如果想让程序继续运行到下一个断点或运行完整个程序,可以使用(”continue”)命令。

    3. 可以使用(”info breakpoint”)命令查看当前所有的断点。

    4. 在使用gcc命令对源文件test.c进行编译时,使用(-E)选项生成中间文件 test.i。

    5. 编译器gcc会在系统默认的路径中(如usr/lib)寻找所需的库文件,当使用了。(-L)选项后,会首先到指定的目录下去寻找相关库文件。

    三、简答题

    头文件#include<my.h>和#include" my.h”中的<>和“”有什么区别?

    答:<>表示编译器将在系统预设的头文件目录下搜索头文件;“”表示先在当前目录下搜索,找不到时再去系统头文件目录下搜索头文件。

    第十六章 Web服务器搭建、应用开发与部署

    一、选择题

    1.Java 环境设置时,不需要配置(B)选项。

    A.PATH

    B. JRE

    C. JAVA_HOME

    D. CLASSPATH

    2.配置MySQL时设置的参数basedir的用途是(B)。

    A.设置端口

    B.设置安装目录

    C.设置数据的存放目录

    D.最大连接数

    3.FTP是(C)协议。

    A.域名系统

    B.动态主机配置

    C.文件传输

    D.文件解析

    二、填空题

    1. 在 Linux环境下,能实现域名解析的功能软件模块是(BIND)

    2. DNS 服务使用的端口是(53)

    3. MVC设计模式将应用程序分为模型、(视图)和控制器。

    展开全文
  • 这不但增加了开发人员的工作量,而且提高了代码的出错。 ----为了解决这问题,AOP思想随之产生。AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码...

    1 Spring

    目标:

    • ApplicationContext容器使用 属性setter方法注入的实现(掌握)
    • Spring中的IoC和DI(熟悉)
    • Spring的概念和优点(了解)

    1.1 概述

    Spring是分层的轻量级开源框架,以IOC(控制反转)AOP(面向切面编程) 为内核,使用基本的javaBean来完成以前只能由EJB完成的工作。

    1.1.1 什么是Spring

    在实际开发中,通常服务器端在采用三层体系架构,分别为表示层(Web)业务逻辑层(Service)持久层(Dao), Spring对每一层都提供了技术支持
    在这里插入图片描述

    1.1.2 Spring的特点

    Spring拥有简单可测试松耦合等特点

    1.1.3 Spring体系结构

    Spring框架采用的是分层架构,它的一系列功能要素分为20个模块。
    在这里插入图片描述

    核心容器

    • Beans
      提供了BeanFactory,Spring将管理对象成为Bean
    • Core
      提供了Spring框架的基本组成部分,包括IOC和DI功能。
    • Context
      建立在Beans和Core模块的基础上,他是访问定义和配置任何对象的媒介

    1.1.4 Spring的目录结构

    Spring开发需要的jar包包括Spring框架包、和第三方依赖包

    1.2 Spring的核心容器

    Spring提供了两种核心容器BeanFactoryApplicationContext

    1.2.1 BeanFactory

    创建beanFactory实例

    BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("F:/applicationContext.xml"));
    //这种加载方式在实际开发中不常见,仅了解即可
    

    1.2.2 ApplicationContext

    不仅包含了BeanFactory的所有功能,还添加了对国际化、资源访问、事件传播等方面的支持。

    创建applicationContext实例

    //1 java项目中通过该方法实例化
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("F:/applicationContext.xml");
    //
    
    //2
    ApplicationContext applicationContext =new FileSystemXmlApplicationContext("F:/applicationContext.xml");
    

    web项目中applicationContext的实例化工作由web服务器完成。通常由ContextLoaderListener实现,此方式需要在web.xml中添加如下代码

           <context-param>
                   <param-name>contextConfigLocation</param-name> 
                   <param-value>
                              classpath:spring/applicationContext.xml
                   </param-value>
           </context-param> 
           <listener>
                   <listener-class>
                             org.springframework.web.context.ContextLoaderListener
                   </listener-class>
           </listener>
    

    Spring获取Bean实例
    Object getBean(String name);
    T getBean(Class requredType);

    1.3 依赖注入DI

    依赖注入和控制反转的含义相同,只不过这两个称呼是从两个角度描述的同一个概念

    控制反转

    在使用Spring框架之后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。

    控制权由应用代码转移到了Spring容器,控制权发生了反转,这就是控制反转。

    依赖注入

    Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入。

    1.3.1 依赖注入的实现

    • 为调用者需要注入的成员变量提供setter方法
    • 在配置文件中写好配置, 例如调用者userService中的成员变量userDao。下面会将对象userDao注入对象userService的成员变量userDao。
            <bean id="userService" class="com.itheima.ioc.UserServiceImpl"> 
                     <property name="userDao" ref="userDao" />
            </bean>
    

    思考

    • 请简述Spring框架的优点。
    • 请简述什么是Spring的IoC和DI。

    2 Spring中的Bean

    目标:

    • 实例化Bean的三种方式和Bean的三种装配方式(掌握)
    • Bean的作用域和生命周期(熟悉)
    • Bean的常用属性及其子元素(了解)

    2.1 Bean的配置

    如果把Spring看做一个大型工厂,则Spring容器中的Bean就是该工厂的产品。要想使用这个工厂生产和管理Bean,就需要在配置文件中告诉它需要哪些Bean,以及需要使用何种方式将这些Bean装配到一起。

    一般只配置id和class,如果不指定id或者name,默认使用class作为id名

    <bean id="bean1" class="com.itheima.Bean1" />
    

    在这里插入图片描述

    2.2 Bean的实例化

    有三种方式:构造器实例化(最常用)静态工厂方式实例化实例工厂方式实例化

    构造器实例化

    指Spring容器通过Bean对应的类中默认的构造函数来实例化Bean。

    • 创建Web项目,导入相关Jar包
    • 创建java类
    • 创建Spring配置文件,并配置java类的bean

    静态工厂化

    静态工厂是实例化Bean的另一种方式。该方式要求自己创建一个静态工厂的方法来创建Bean的实例。

    • 创建一个Java类
    • 创建一个生产该Java类的工厂类,工厂类中提供静态方法获得Java类
    • 创建Spring配置文件,并配置工厂类的bean

    实例工厂化

    • 创建一个Java类
    • 创建一个生产该Java类的工厂类,工厂类中提供非静态方法获得Java类
    • 创建Spring配置文件,并配置工厂类的bean

    2.3 Bean的作用域

    2.3.1 作用域的种类

    一共有7种作用域,其中singleton(Spring容器默认)prototype最常用。

    在这里插入图片描述

    2.3.2 singleton的作用域

    singleton作用域对于无会话状态的Bean(如Dao 组件、Service组件)来说,是最理想的选择。
    配置:

    <bean id="scope" class="com.itheima.scope.Scope" scope="singleton"/>
    

    2.3.3 prototype的作用域

    对需要保持会话状态的Bean(如Struts 2的Action类)应该使用prototype作用域。在使用prototype作用域时,Spring容器会为每个对该Bean的请求都创建一个新的实例。

    2.4 Bean的生命周期

    了解的意义

    了解Spring中Bean的生命周期的意义就在于,可以利用Bean在其存活期间的特定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,常会在Bean的postinitiation(初始化后)predestruction(销毁前) 执行一些相关操作。

    Spring容器可以管理生命周期的Bean

    • singleton作用域的bean,在此作用域下,Spring能够精确的知道该Bean何时被创建,何时初始化完成,以及何时被销毁。
    • prototype作用域下的bean不行,当容器创建了Bean实例后Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。

    2.5 Bean的装配方式

    3种,

    • 基于XML的装配
    • 基于注解(Annotation)的装配
    • 自动装配(其中最常用的是基于注解的装配)

    2.5.1 基于XML的装配

    • 设值注入(必须有一个无参构造方法为属性提供setter方法),在配置文件中,使用property为bean赋值
    • 构造注入(必须提供有参构造方法),在配置文件中,使用constructor-arg为bean赋值
          <bean id="user1" class="com.itheima.assemble.User">
    	     <constructor-arg index="0" value="张三" />
            ...
          </bean>
          <bean id="user2" class="com.itheima.assemble.User">
     	   <property name=“username” value=“张三”  />
            ...
          </bean>
    

    2.5.2 基于注解的装配

    注解

    • @Component:用于描述Spring中的Bean,它是一个泛化的概念,仅仅表示一个组件。
    • @Repository:用于将数据访问层(DAO)的类标识为Spring中的Bean 。
    • @Controller:用于将控制层(Controller)的类标识为Spring中的Bean 。
    • @Service:用于将业务层(Service)的类标识为Spring中的Bean。
    • @Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。
    • @Resource:其作用与Autowired一样。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。
    • @Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。

    例子
    配置文件中的配置。

    <!--扫描这些bean中的注解,并为bean中的成员进行赋值-->
       <context:annotation-config />
       <bean id="userDao" class="com.itheima.annotation.UserDaoImpl" />
       <bean id="userService" class="com.itheima.annotation.UserServiceImpl" />
       <bean id="userController" class="com.itheima.annotation.UserController" />
    
    

    除了可以像示例中通过元素来配置Bean外,还可以通过包扫描的形式来配置一个包下的所有Bean:
    <context:component-scan base-package=“com.itheima.annotation” />

    2.5.3 自动装配

    所谓自动装配,就是将一个Bean自动的注入到到其他Bean的Property中。
    可以通过设置bean的autowire实现
    在这里插入图片描述

    <bean id="userDao" class="com.itheima.annotation.UserDaoImpl" />
    <bean id="userService" class="com.itheima.annotation.UserServiceImpl" autowire="byName" />
    <bean id="userController" class="com.itheima.annotation.UserController" autowire="byName" />
    

    思考

    • 请简述Bean的生命周期。
      一阶段:Bean的实例化和DI(dependency injection)
      二阶段:检查Spring Awareness
      三阶段:创建bean生命周期回调
      四阶段:销毁bean生命周期回调
    • 请简述Bean的几种装配方式的基本用法。

    3 Spring AOP

    目标:

    • 基于代理类的AOP实现和基于XML和注解的AspectJ开发(掌握)
    • 两种动态代理方式的区别(熟悉)
    • AOP中的相关术语(理解)
    • AOP的概念和作用(了解)

    3.1 Spring AOP简介

    3.1.1 AOP简介

    全称:Aspect-Oriented Programming,面向切面编程。
    ----在传统的业务处理代码中,通常都会进行事务处理、日志记录等操作。虽然使用OOP可以通过组合或者继承的方式来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码仍然会分散到各个方法中。这样,如果想要关闭某个功能,或者对其进行修改,就必须要修改所有的相关方法。这不但增加了开发人员的工作量,而且提高了代码的出错率。
    ----为了解决这一问题,AOP思想随之产生。AOP采取横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码应用到需要执行的地方。这种采用横向抽取机制的方式,采用传统的OOP思想显然是无法办到的,因为OOP只能实现父子关系的纵向的重用。虽然AOP是一种新的编程思想,但却不是OOP的替代品,它只是OOP的延伸和补充

    3.1.2 AOP术语

    在这里插入图片描述

    3.2 动态代理

    3.2.1 JDK动态代理

    JDK动态代理是通过java.lang.reflect.Proxy 类来实现的,我们可以调用Proxy类newProxyInstance() 方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现AOP。

    实现

    1.创建目标类,SomeServiceImpl目标类,我们要给它的doSome,doOhter方法增加开头结尾。
    2.创建InvocationHandler接口的实现类,在这个类实现,给目标方法增加功能。
    3.使用jdk中 类proxy,创建代理对象。实现创建对象的能力。
    
    2.
    //实现动态代理接口
    MyincationHandler.java
    public class MyIncationHandler implements InvocationHandler {
    
        //目标对象
        private Object target;    //SomeServiceImpl类
    
        public void setTarget(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //通过动态代理执行方法时,会执行这个invoke()方法
            Object res = null;
            System.out.println("在方法前添加东西");
            //执行目标类的方法,通过method类实现
            res = method.invoke(target,args);
            //目标执行的结果
            System.out.println("在方法后添加东西");
            return res;
        }
    }
    3.创建代理对象
        SomeService target = new SomeServiceImpl();
        InvocationHandler handler = new MyIncationHandler(target);
    //使用Proxy创建代理
    	SomeService proxy = (SomeService) Proxy.newProxyInstance(
    		target.getClass().getClassLoader(),
    		target.getClass().getInterfaces(),
    		handler
    	);
    	proxy.doSome();     //通过代理执行方法,会执行InvocationHandler中的invoke。
    

    3.2.2 CGLIB代理

    3.3 基于代理类的AOP实现

    3.3.1 Spring的通知类型

    • org.springframework.aop.MethodBeforeAdvice(前置通知)
      在目标方法执行前实施增强,可以应用于权限管理等功能。
    • org.springframework.aop.AfterReturningAdvice(后置通知)
      在目标方法执行后实施增强,可以应用于关闭流、上传文件、删除临时文件等功能。
    • org.aopalliance.intercept.MethodInterceptor(环绕通知)
      在目标方法执行前后实施增强,可以应用于日志、事务管理等功能。
    • org.springframework.aop.ThrowsAdvice(异常抛出通知)
      在方法抛出异常后实施增强,可以应用于处理异常记录日志等功能。
    • org.springframework.aop.IntroductionInterceptor(引介通知)
      在目标类中添加一些新的方法和属性,可以应用于修改老版本程序。
      ProxyFactoryBean是FactoryBean接口的实现类,FactoryBean负责实例化一个Bean,而ProxyFactoryBean**负责为其他

    Bean创建代理实例**。在Spring中,使用ProxyFactoryBean是创建AOP代理的基本方式。
    ProxyFactoryBean类中的常用可配置属性如下:

    在这里插入图片描述

    3.4 AspectJ开发

    AspectJ是一个基于Java语言的AOP框架。实现AOP有种方式

    • 基于XML的声明式AspectJ
    • 基于注解的声明式AspectJ

    3.4.1 基于XML的声明式AspectJ

    通过XML文件来定义切面切入点通知,所有的切面、切入点和通知都必须定义在< aop:config >元素内。

    配置切面:
    在这里插入图片描述

    1. 配置切面
      < aop:aspect id=“aspect” ref=“myAspect” >

    配置切面使用的是< aop:aspect >元素,该元素会将一个已定义好的Spring Bean转换成切面Bean,所以要在配置文件中先定义一个普通的Spring Bean。配置切面 aop:aspect时通常配置id和ref属性
    在这里插入图片描述

    1. 配置切入点
      < aop:pointcut expression=“execution(* com.itheima.jdk.*.*(…))” id=“myPointCut” / >
      当< aop:pointcut >元素作为< aop:config >元素的子元素定义时,表示该切入点是全局切入点,它可被多个切面所共享;
      当< aop:pointcut >元素作为< aop:aspect >元素的子元素时,表示该切入点只对当前切面有效
      execution(* com.itheima.jdk.*.*(…)) 是定义的切入点表达式,该切入点表达式的意思是匹配com.itheima.jdk包中任意类的任意方法的执行。 返回类型 包名.类名.方法(参数)。

    2. 配置通知
      使用< aop:aspect >的子元素可以配置5种常用通知,这5个子元素不支持使用子元素,但在使用时可以指定一些属性,其常用属性及其描述如下:
      在这里插入图片描述

    3.4.2基于注解的声明式AspectJ

    在这里插入图片描述

    例子

    @Aspect
    public class MyAspect {
        //AfterReturning是切入的时间点,     value是目标类
        @AfterReturning(value="execution(public void com.vashon.service.impl.SomeServiceImpl.doSome())",returning="res")
        public void myAfter(JoinPoint jp, Object res) {                //当方法调用该切面方法,这个方法的返回值会赋值给res
            System.out.println("后置通知");
            System.out.println(res);
        }
    }
    

    思考

    • 请列举你所知道的AOP专业术语并解释。
    • 请列举你所知道的Spring的通知类型并解释。

    4 Spring的数据库开发

    目标:

    • JdbcTemplate类中几个常用方法的使用(掌握)
    • Spring JDBC的配置(熟悉)
    • Spring中JDBC模块的作用(了解)

    4.1 Spring JDBC

    JDBC模块的作用

    Spring的JDBC模块负责数据库资源管理错误处理,大大简化了开发人员对数据库的操作,使得开发人员可以从繁琐的数据库操作中解脱出来,从而将更多的精力投入到编写业务逻辑当中。

    4.1.1 Spring JdbcTemplate的解析

    JdbcTemplate类是Spring JDBC的核心类,继承结构如下:
    在这里插入图片描述

    JdbcTemplate类的直接父类是JdbcAccessor,该类为子类提供了一些访问数据库时使用的公共属性

    • DataSource
      其主要功能是获取数据库连接,还可以引入对数据库连接的缓冲池和分布式事务的支持,它可以作为访问数据库资源的标准接口。
    • SQLExceptionTranslator
      该接口负责对SQLException进行转译工作。通过必要的设置获取SQLExceptionTranslator中的方法,可以使JdbcTemplate在需要处理SQLException时,委托SQLExceptionTranslator的实现类来完成相关的转译工作。

    JdbcOperations接口定义了在JdbcTemplate类中可以使用的操作集合,包括添加、修改、查询和删除等操作。

    4.1.2 Spring JDBC的配置

    Spring JDBC模块主要由4个包组成,分别是core(核心包)、dataSource(数据源包)、object(对象包)和support(支持包)。
    JdbcTemplate类core(核心包) 中。
    在这里插入图片描述
    配置文件
    在这里插入图片描述
    其中dataSource中的四个属性
    在这里插入图片描述

    4.2 Spring JdbcTemplate的常用方法

    在JdbcTemplate核心类中,提供了大量的更新查询数据库的方法,我们就是使用的这些方法来操作数据库的。

    • execute()
      execute(String sql)方法可用于执行sql语句
    • update()
      update()用于执行插入、更新和删除操作
    • query()
      query()用于执行数据查询操作

    4.2.1 execute()的使用

        public class JdbcTemplateTest {
             public static void main(String[] args) {
                 ApplicationContext applicationContext = 
      		              new ClassPathXmlApplicationContext("applicationContext.xml");
                JdbcTemplate jdTemplate = (JdbcTemplate) applicationContext.getBean("jdbcTemplate");
                
                //此处使用了jdbc Template类的execute方法
                jdTemplate.execute("create table account(" id int primary key auto_increment," +
    				         "username varchar(50)," + 
    				          "balance double)");
            }
       }
    

    JUnit就是一个进行单元测试的开源框架。

    4.2.2 update()的使用

    update()方法可以完成插入更新删除数据的操作。在JdbcTemplate类中,提供了一系列的update()方法,其常用方法下表所示:
    在这里插入图片描述
    update的使用

        // 添加账户
    	public int addAccount(Account account) {
    		// 定义SQL
    		String sql = "insert into account(username,balance) value(?,?)";
    		// 定义数组来存放SQL语句中的参数
    		Object[] obj = new Object[] { 
                               account.getUsername(), 
                               account.getBalance() 
             };
    		// 执行添加操作,返回的是受SQL语句影响的记录条数
    		int num = this.jdbcTemplate.update(sql, obj);###此处执行update(String sql,PreparedStatementSetter pss)方法
    		return num;
    	}
    
    	// 删除账户
    	public int deleteAccount(int id) {
    		// 定义SQL
    		String sql = "delete  from account where id = ? ";
    		// 执行添加操作,返回的是受SQL语句影响的记录条数
    		int num = this.jdbcTemplate.update(sql, id);       ###此处执行update(String sql,Object...args)方法
    		return num;
    	}
    

    4.2.3 query()的使用

    JdbcTemplate类中还提供了大量的query()方法来处理各种对数据库表的查询操作。其中,常用的几个query()方法如下表所示:
    在这里插入图片描述

    	// 通过id查询账户数据信息
    	public Account findAccountById(int id) {
    	    //定义SQL语句
    	    String sql = "select * from account where id = ?";
    	    // 创建一个新的BeanPropertyRowMapper对象
    	    RowMapper<Account> rowMapper = 
    	new BeanPropertyRowMapper<Account>(Account.class);
    	    // 将id绑定到SQL语句中,并通过RowMapper返回一个Object类型的单行记录
    	    return this.jdbcTemplate.queryForObject(sql, rowMapper, id);       ###此处执行queryForObject方法
    	}
    	// 查询所有账户信息
    	public List<Account> findAllAccount() {
    	    // 定义SQL语句
    	    String sql = "select * from account";
    	    // 创建一个新的BeanPropertyRowMapper对象
    	    RowMapper<Account> rowMapper = 
    	new BeanPropertyRowMapper<Account>(Account.class);
    	    // 执行静态的SQL查询,并通过RowMapper返回结果
    	    return this.jdbcTemplate.query(sql, rowMapper);                 ###此处执行query方法
    	}
    

    思考

    • 请简述Spring JDBC是如何进行配置的。
    • 请简述Spring JdbcTemplate类中几个常用方法的作用。

    5 Spring的事务管理

    目标:

    • 基于XML和Annotation的声明式事务的使用(掌握)
    • Spring事务管理的三个核心接口(熟悉)
    • Spring事务管理的两种方式(了解)

    5.1 Spring事务管理概述

    在实际开发中,操作数据库时都会涉及到事务管理问题,为此Spring提供了专门用于事务处理的API。Spring的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。

    5.1.1 核心接口文件

    有3个接口文件PlatformTransactionManagerTransactionDefinitionTransactionStatus

    1. Platform TransactionManager
      PlatformTransactionManager接口是Spring提供的平台事务管理器,主要用于管理事务。该接口中提供了三个事务操作的方法,具体如下:
      1. TransactionStatus getTransaction(TransactionDefinition definition);
      用于获取事务状态信息
      2. void commit(TransactionStatus status);
      用于提交事务
      3. void rollback(TransactionStatus status);
      用于回滚事务
      实现类:
      1. org.springframework.jdbc.datasource.DataSourceTransactionManager
      用于配置JDBC数据源的事务管理器
      2. org.springframework.orm.hibernate4.HibernateTransactionManager
      用于配置Hibernate的事务管理器
      3. org.springframework.transaction.jta.JtaTransactionManager
      用于配置全局事务管理器

    2. TransactionDefinition
      TransactionDefinition接口是事务定义(描述)的对象,该对象中定义了事务规则,并提供了获取事务相关信息的方法,具体如下:

    在这里插入图片描述

    传播行为:(默认required)
    在这里插入图片描述
    3. TransactionStatus
    TransactionStatus接口是事务的状态,它描述了某一时间点上事务的状态信息。该接口中包含6个方法,具体如下:
    在这里插入图片描述

    5.1.2 事务管理的方式

    有两种方式

    • 编程式事务管理
      通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交和异常时的事务回滚
    • 声明式事务管理
      通过AOP技术实现的事务管理,主要思想是将事务作为一个“切面”代码单独编写,然后通过AOP技术将事务管理的“切面”植入到业务目标类中

    声明式事务管理最大的优点在于开发者无需通过编程的方式来管理事务,只需在配置文件中进行相关的事务规则声明,就可以将事务应用到业务逻辑中。这使得开发人员可以更加专注于核心业务逻辑代码的编写,在一定程度上减少了工作量,提高了开发效率,所以在实际开发中,通常都推荐使用声明式事务管理。

    5.2 声明式事务管理

    可以通过种方式来实现,一种是基于XML的方式,另一种是基于Annotation的方式。

    5.2.1 基于XML方式的声明式事务

    基于XML方式的声明式事务是在配置文件中通过<tx:advice>元素配置事务规则来实现的。当配置了事务的增强处理后,就可以通过编写的AOP配置,让Spring自动对目标生成代理。<tx:advice>元素及其子元素如下图所示:
    在这里插入图片描述
    配置< tx:advice >元素的重点是配置< tx:method >子元素,上图中使用灰色标注的几个属性是< tx:method >元素中的常用属性。其属性描述具体如下:
    在这里插入图片描述
    配置文件:

       <!-- 4.事务管理器,依赖于数据源 -->
       <bean id="transactionManager" class=
       "org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource" />
       </bean>	
       <!-- 5.编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节 -->
       <tx:advice id="txAdvice" transaction-manager="transactionManager">
    		<tx:attributes>
    			<!-- name:*表示任意方法名称 -->
    			<tx:method name="*" propagation="REQUIRED" 
                               isolation="DEFAULT" read-only="false" />
    		</tx:attributes>
       </tx:advice>
    	<!-- 6.编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式 -->
    <aop:config>
    	<!-- 切入点 -->
    	<aop:pointcut expression="execution(* com.itheima.jdbc.*.*(..))" id="txPointCut" />
    	<!-- 切面:将切入点与通知整合 -->
    	<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
    </aop:config>
    

    5.2.2 基于Annotation方式的声明式事务

    1. 在Spring容器中注册事务注解驱动;
      < tx:annotation-driven transaction-manager=“transactionManager”/>
    2. 在需要事务管理的类或方法上使用@Transactional注解。
      如果将注解添加在Bean类上,则表示事务的设置对整个Bean类所有方法都起作用;
      如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该方法有效。

    使用**@Transactional注解**时,可以通过参数配置事务详情:
    在这里插入图片描述
    配置文件:

    	<!-- 4.事务管理器,依赖于数据源 -->
    	<bean id="transactionManager" class=
         "org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="dataSource" />
    	</bean>	
        <!-- 5.注册事务管理器驱动 -->
    	<tx:annotation-driven transaction-manager="transactionManager"/>
    

    使用注解:

    
    	@Transactional(propagation = Propagation.REQUIRED, 
                isolation = Isolation.DEFAULT, readOnly = false)
    	public void transfer(String outUser, String inUser, Double money) {
    	    // 收款时,收款用户的余额=现有余额+所汇金额
    	    this.jdbcTemplate.update("update account set balance = balance +? "
    	            + "where username = ?",money, inUser);
    	    // 模拟系统运行时的突发性问题
    	    int i = 1/0;
    	    // 汇款时,汇款用户的余额=现有余额-所汇金额
    	    this.jdbcTemplate.update("update account set balance = balance-? "
    	            + "where username = ?",money, outUser);
    	}
    

    思考

    • 请简述Spring中事务管理的两种方式
    • 请简述如何使用Annotation方式进行声明式事务管理。

    6 初始Mybatis

    目标:

    • MyBatis入门程序的编写(掌握)
    • MyBatis的工作原理(熟悉)
    • MyBatis的基础知识(了解)

    6.1 什么是MyBatis

    MyBatis(前身是iBatis)是一个支持普通SQL查询、存储过程以及高级映射的持久层框架

    MyBatis框架也被称之为ORM(Object/Relation Mapping,即对象关系映射)框架。所谓的ORM就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。
    在这里插入图片描述

    Hibernate与MyBatis有什么区别?
    Hibernate是一个全表映射的框架。

    • 通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过Hibernate提供的方法完成持久层操作。
    • 开发者并不需要熟练的掌握SQL语句的编写,Hibernate会根据制定的存储逻辑,自动的生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis。
    • Hibernate也存在一些缺点,例如它在多表关联时,对SQL查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SQL来优化性能等。

    MyBatis是一个半自动映射的框架。

    • “半自动”是相对于Hibernate全表映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系,而Hibernate只需提供POJO和映射关系即可。
    • 与Hibernate相比,虽然使用MyBatis手动编写SQL要比使用Hibernate的工作量大,但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。

    6.2 MyBatis的下载和使用

    6.3 MyBatis的工作原理

    在这里插入图片描述

    6.4 MyBatis入门程序

    6.4.1查询用户

    Mapper.xml

           <?xml version="1.0" encoding="UTF-8"?>
           <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
           <mapper namespace="com.itheima.mapper.CustomerMapper">    //namesace指的是对应的Dao类,此处为CustomerMapper
    	<select id="findCustomerById" parameterType="Integer"
    		resultType="com.itheima.po.Customer">
    		select * from t_customer where id = #{id}
    	</select>
           </mapper>
    
    

    mybatis.xml

           <?xml version="1.0" encoding="UTF-8" ?>
           <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
             "http://mybatis.org/dtd/mybatis-3-config.dtd">
           <configuration>      //配置数据库
                  <environments default="mysql"> 
                         <environment id="mysql"> 
                               <transactionManager type="JDBC" /> 
                                   <dataSource type="POOLED">
    	                  <property name="driver" value="com.mysql.jdbc.Driver" />
                                      <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />              
    	                  <property name="username" value="root" />
    	                  <property name="password" value="root" />
                                    </dataSource>
                               </environment>
                          </environments> 
                 <mappers>
    	     <mapper resource="com/itheima/mapper/CustomerMapper.xml" />  //扫描到上面那个xml文件
                 </mappers>
            </configuration>
    

    使用

    public class MybatisTest {
        public void findCustomerByIdTest() throws Exception {		                     
        	String resource = "mybatis-config.xml";
        	InputStream inputStream = Resources.getResourceAsStream(resource);
        	//3 创建会话工厂
    	    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
    	    //4 获得会话对象	
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //5 使用会话
            Customer customer = sqlSession.selectOne("com.itheima.mapper" +.CustomerMapper.findCustomerById”, 1); 
    		System.out.println(customer.toString()); 
    		sqlSession.close();
        }
    }
    

    sqlSession对象的各个方法。

    • sqlSession.selectList(“com.autohome.mapper.User.queryUsers”);
    • sqlSession.selectOne(“com.autohome.mapper.User.queryUserById”,2);
    • sqlSession.insert(“com.autohome.mapper.User.insertUsers”,user);
    • sqlSession.update(“com.autohome.mapper.User.updateUsers”,user);
    • sqlSession.delete(“com.autohome.mapper.User.deleteUsers”,49);

    思考

    • 请简述MyBatis框架与Hibernate框架的区别。
    • 请简述MyBatis的工作执行流程。

    7 MyBatis的核心配置

    目标:

    • 映射文件中常用元素的使用(掌握)
    • 配置文件中各个元素的作用(熟悉)
    • 核心对象的作用(了解)

    7.1 MyBatis的核心对象

    7.1.1 SqlSessionFactory

    SqlSessionFactory是MyBatis框架中十分重要的对象,它是单个数据库映射关系经过编译后的内存镜像,其主要作用是创建SqlSession。
    SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象来构建,而SqlSessionFactoryBuilder则可以通过XML配置文件或一个预先定义好的Configuration实例构建出SqlSessionFactory的实例

    InputStream inputStream = Resources.getResourceAsStream("配置文件位置");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    

    7.1.2 SqlSession

    SqlSession是MyBatis框架中另一个重要的对象,它是应用程序与持久层之间执行交互操作的一个单线程对象,其主要作用是执行持久化操作
    每一个线程都应该有一个自己的SqlSession实例,并且该实例是不能被共享的。同时,SqlSession实例也是线程不安全的,因此其使用范围最好在一次请求或一个方法中,绝不能将其放在一个类的静态字段、实例字段或任何类型的管理范围(如Servlet的HttpSession)中使用。
    使用完SqlSession对象后要及时关闭,通常可以将其放在finally块中关闭。

    除了增删改查,其他方法:

    void commit();   提交事务的方法。
    void rollback();   回滚事务的方法。
    void close();   关闭SqlSession对象。
    <T> T getMapper(Class<T> type);   返回Mapper接口的代理对象。
    Connection getConnection();   获取JDBC数据库连接对象的方法。
    

    7.2 配置文件

    7.2.1 主要元素

    在这里插入图片描述

    7.2.2 < properties >元素

    < properties >是一个配置属性的元素,该元素通常用来将内部的配置外在化,即通过外部的配置来动态的替换内部定义的属性。例如,数据库的连接等属性,就可以通过典型的Java属性文件中的配置来替换,具体方式如下:
    db.properties

         jdbc.driver=com.mysql.jdbc.Driver
         jdbc.url=jdbc:mysql://localhost:3306/mybatis
         jdbc.username=root
         jdbc.password=root
    

    mybatis.xml

    <properties resource="db.properties" />  ###引入外部配置文件
    
    <dataSource type="POOLED">
        <!-- 数据库驱动 -->
        <property name="driver" value="${jdbc.driver}" />
        <!-- 连接数据库的url -->
        <property name="url" value="${jdbc.url}" />
        <!-- 连接数据库的用户名 -->
        <property name="username" value="${jdbc.username}" />
        <!-- 连接数据库的密码 -->
        <property name="password" value="${jdbc.password}" />
    </dataSource>
    

    7.2.3 < settings >元素

    < settings >元素主要用于改变MyBatis运行时的行为,例如开启二级缓存、开启延迟加载等。
    mybatis.xml

         <!-- 设置 了解即可-->
         <settings>
             <setting name="cacheEnabled" value="true" />
             <setting name="lazyLoadingEnabled" value="true" />
             <setting name="multipleResultSetsEnabled" value="true" />
             <setting name="useColumnLabel" value="true" />
             <setting name="useGeneratedKeys" value="false" />
             <setting name="autoMappingBehavior" value="PARTIAL" />
             ...
         </settings>
    

    7.2.4 < typeAliases >元素

    < typeAliases >元素用于为配置文件中的Java类型设置一个简短的名字,即设置别名。别名的设置与XML配置相关,其使用的意义在于减少全限定类名的冗余。 (以后用到全限定类名称时,可以其简写)

         <typeAliases>
                 <typeAlias alias="user" type="com.itheima.po.User"/>
         </typeAliases>
         当pojo类过多时,使用下面设置,别名为其注解的值
              <typeAliases>
                 <package name="com.itheima.po"/>
         </typeAliases>
    

    默认别名
    在这里插入图片描述

    7.2.5 < typeHandler >元素

    typeHandler的作用就是将预处理语句中传入的参数javaType(Java类型)转换为jdbcType(JDBC类型),或者从数据库取出结果时jdbcType转换为javaType
    < typeHandler >元素可以在配置文件中注册自定义的类型处理器,它的使用方式有两种。

    • 注册一个类的类型处理器
         <typeHandlers> 
              <typeHandler handler="com.itheima.type.CustomtypeHandler" />
         </typeHandlers>
    
    • 注册一个包中所有的类型处理器
         <typeHandlers> 
              <package name="com.itheima.type" />
         </typeHandlers>
    

    7.2.6 < objectFactory >元素(不怎么用)

    MyBatis中默认的ObjectFactory的作用是实例化目标类,它既可以通过默认构造方法实例化,也可以在参数映射存在的时候通过参数构造方法来实例化。通常使用默认的ObjectFactory即可。

    7.2.7 < plugins >元素(你得会写mybatis插件)

    < plugins >元素的作用就是配置用户所开发的插件

    7.2.8 < environments >元素

    < environments >元素用于对环境进行配置。MyBatis的环境配置实际上就是数据源的配置,我们可以通过< environments >元素配置多种数据源,即配置多种数据库。

         <environments default="development">  表示默认使用id为development数据源
              <environment id="development">
          		<transactionManager type="JDBC" />
                <dataSource type="POOLED">
                       <property name="driver" value="${jdbc.driver}" />
                       <property name="url" value="${jdbc.url}" />
                       <property name="username" value="${jdbc.username}" />
                       <property name="password" value="${jdbc.password}" />
             	</dataSource>
              </environment>
                ...
         </environments>
    
    

    在MyBatis中,可以配置两种类型的事务管理器,分别是JDBCMANAGED。关于这两个事务管理器的描述如下:

    • JDBC:此配置直接使用了JDBC的提交和回滚设置,它依赖于从数据源得到的连接来管理事务的作用域。
    • MANAGED:此配置从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。默认情况下,它会关闭连接,但一些容器并不希望这样,为此可以将closeConnection属性设置为false来阻止它默认的关闭行为。

    注意:
    如果项目中使用的是Spring+ MyBatis,则没有必要在MyBatis中配置事务管理器,因为实际开发中,会使用Spring自带的管理器来实现事务管理。

    数据源的配置
    在这里插入图片描述

    7.2.9 < mappers >元素

    < mappers >元素用于指定MyBatis映射文件的位置,一般可以使用以下4种方法引入映射器文件,具体如下。
    2、3不常用
    1.使用类路径引入

    <mappers>
        <mapper resource="com/itheima/mapper/UserMapper.xml"/>
    </mappers>
    

    2.使用本地文件路径引入

    <mappers>
        <mapper url="file:///D:/com/itheima/mapper/UserMapper.xml"/>
    </mappers>
    

    3.使用接口类引入

    <mappers>
        <mapper class="com.itheima.mapper.UserMapper"/>
    </mappers>
    

    4.使用包名引入

    <mappers>
        <package name="com.itheima.mapper"/>
    </mappers>
    

    7.3 映射文件

    7.3.1 主要元素

    在映射文件中,< mapper >元素是映射文件的根元素,其他元素都是它的子元素。

    <mapper namespace="org.example.dao.StudentDao">
        <select id="selectStudent" resultType="org.example.doman.Student">
        select * from student order by id;
      </select>
    	...
    </mapper>
    

    在这里插入图片描述

    7.3.2 < select >元素

    < select >元素用来映射查询语句,它可以帮助我们从数据库中读取出数据,并组装数据给业务开发人员。

    <select id="findCustomerById" parameterType="Integer"
                resultType="com.itheima.po.Customer">
                select * from t_customer where id = #{id}
    </select>
    

    常用属性
    在这里插入图片描述

    7.3.3 < insert >元素

    < insert >元素用于映射插入语句,在执行完元素中定义的SQL语句后,会返回一个表示插入记录数的整数。

    <insert id="addCustomer" parameterType="com.itheima.po.Customer"
                keyProperty="id" useGeneratedKeys="true" >
          insert into t_customer(username,jobs,phone)
          values(#{username},#{jobs},#{phone})
    </insert>
    

    insert的属性
    在这里插入图片描述
    插入后返回主键值(此处支持主键自动增长的数据库)

    <insert id="addCustomer" parameterType="com.itheima.po.Customer"
                keyProperty="id" useGeneratedKeys="true" >
          insert into t_customer(username,jobs,phone)
          values(#{username},#{jobs},#{phone})
    </insert>
    

    7.3.4 < update >和< delete >元素

    常用属性如下:

    <update
          id="updateCustomer"
          parameterType="com.itheima.po.Customer"
          flushCache="true"
          statementType="PREPARED"
          timeout="20">
    <delete
          id="deleteCustomer"
          parameterType="com.itheima.po.Customer"
          flushCache="true"
          statementType="PREPARED"
          timeout="20">
    

    示例:

    <update id="updateCustomer" parameterType="com.itheima.po.Customer">
           update t_customer 
           set username=#{username},jobs=#{jobs},phone=#{phone}
           where id=#{id}
    </update>
    <delete id="deleteCustomer" parameterType="Integer">
            delete from t_customer where id=#{id}
    </delete>
    

    7.3.5 < sql >元素

    < sql >元素的作用就是定义可重用SQL代码片段,然后在文件中其他的sql语句中引用这一代码片段。

    <sql id="customerColumns">id,username,jobs,phone</sql>
    
    <select id="findCustomerById" parameterType="Integer"
                resultType="com.itheima.po.Customer">
        select <include refid="customerColumns"/>  ###使用了这一个代码片段
        from t_customer 
        where id = #{id}
    </select>
    

    又一例子

    <!--定义表的前缀名 -->
    <sql id="tablename">
        ${prefix}customer
    </sql>
    <!--定义要查询的表 -->
    <sql id="someinclude">
        from
        <include refid="${include_target}" />		
    </sql>
    <!--定义查询列 -->
    <sql id="customerColumns">
       id,username,jobs,phone
    </sql>
    <select id="findCustomerById" parameterType="Integer" 
             resultType="com.itheima.po.Customer">
        select 
        <include refid="customerColumns"/>
        <include refid="someinclude">
            <property name="prefix" value="t_" />
            <property name="include_target" value="tablename" />
        </include>
        where id = #{id}
    </select>
    
    select id,username,jobs,phone
    from t_customer
    where id = ?;
    

    7.3.6 < resultMap >元素

    < resultMap >元素表示结果映射集,是MyBatis中最重要也是最强大的元素。它的主要作用是定义映射规则、级联的更新以及定义类型转化器等。

    <resultMap type="" id="">
           <constructor>    <!-- 类在实例化时,用来注入结果到构造方法中-->
                 <idArg/>      <!-- ID参数;标记结果作为ID-->
                 <arg/>          <!-- 注入到构造方法的一个普通结果-->
           </constructor>  
           <id/>                 <!-- 用于表示哪个列是主键-->
           <result/>           <!-- 注入到字段或JavaBean属性的普通结果-->
           <association property="" />        <!-- 用于一对一关联 -->
           <collection property="" />          <!-- 用于一对多关联 -->
           <discriminator javaType="">      <!-- 使用结果值来决定使用哪个结果映射-->
                <case value="" />                   <!-- 基于某些值的结果映射 -->
           </discriminator>	
    </resultMap>
    

    思考

    • 简述MyBatis核心对象SqlSessionFactory的获取方式。
    • 简述MyBatis映射文件中的主要元素及其作用。

    8 动态SQL

    目标:

    • 动态SQL中主要元素的使用(掌握)
    • 常用的动态SQL元素及其作用(了解)

    8.1 动态SQL中的元素

    作用:
    开发人员在使用JDBC或其他类似的框架进行数据库开发时,通常都要根据需求去手动拼装SQL,这是一个非常麻烦且痛苦的工作,而MyBatis提供的对SQL语句动态组装的功能,恰能很好的解决这一麻烦工作
    元素如下:
    在这里插入图片描述

    8.2 < if >元素

    在MyBatis中,< if >元素是最常用的判断语句,它类似于Java中的if语句,主要用于实现某些简单的条件选择。其基本使用示例如下:

         select * from t_customer where 1=1 
        <if test="username !=null and username !=''">         
       <!--当username不为空或者null时,才会往sql语句添加and username like concat('%',#{username}, '%')-->
       and username like concat('%',#{username}, '%')
        </if>
        <if test="jobs !=null and jobs !=''">
       and jobs= #{jobs}
        </if>
    

    8.3 < choose >及其子元素

    当客户名称不为空,则只根据客户名称进行客户筛选;
    当客户名称为空,而客户职业不为空,则只根据客户职业进行客户筛选。
    当客户名称和客户职业都为空,则要求查询出所有电话不为空的客户信息。”

          select * from t_customer where 1=1
          <choose>
          <!--三者选一-->
               <when test="username !=null and username !=''">
                           and username like concat('%',#{username}, '%')
               </when>
               <when test="jobs !=null and jobs !=''">
                           and jobs= #{jobs}
               </when>
               <otherwise>
                       and phone is not null
               </otherwise>
          </choose>
    

    8.4 < when >、< trim >元素

    动态SQL处理“where 1=1”

    • < where >元素处理
      < where >会自动判断SQL语句,只有< where >内的条件成立时,才会在拼接SQL中加入where关键字,否则将不会添加;还会去除多余的“AND”或“OR”。
          select * from t_customer
          <where>
               <if test="username !=null and username !=''">
                     and username like concat('%',#{username}, '%')
               </if>
               <if test="jobs !=null and jobs !=''">
                     and jobs= #{jobs}
               </if>
          </where>
    
    • < trim >元素处理
      < trim >的作用是去除特殊的字符串,它的prefix属性代表语句的前缀prefixOverrides属性代表需要去除的哪些特殊字符串,功能和< where >基本是等效的。
         select * from t_customer
         <trim prefix="where" prefixOverrides="and">
                <if test="username !=null and username !=''">
                      and username like concat('%',#{username}, '%')
                </if>
                <if test="jobs !=null and jobs !=''">
                      and jobs= #{jobs}
                </if>
         </trim>
    

    8.5 < set >元素

    Hibernate中,想要更新某个对象,就需要发送所有的字段给持久化对象,这种想更新的每一条数据都要将其所有的属性都更新一遍的方法,其执行效率是非常差的。为此,在MyBatis中可以使用动态SQL中的< set >元素进行处理:

    <update id="updateCustomer"  parameterType="com.itheima.po.Customer">
            update t_customer 
            <!--使用<set>和<if>元素对username和jobs进行更新判断,并动态组装SQL。这样就只需要传入想要更新的字段即可-->
            <set>
                <if test="username !=null and username !=''">
                      username=#{username},
                </if>
                <if test="jobs !=null and jobs !=''">
                      jobs=#{jobs},
                </if>
            </set>
            where id=#{id}
    </update>
    

    8.6 < foreach >元素

    在一个客户表中有1000条数据,现在需要将id值小于100的客户信息全部查询出来,这要怎么做呢?

         <select id="findCustomerByIds" parameterType="List"
                             resultType="com.itheima.po.Customer">
               select * from t_customer where id in
                <foreach item="id" index="index" collection="list" 
                                open="(" separator="," close=")">
                       #{id}
                </foreach>
         </select>
    

    若想调用上面的sql需传入一个list集合。供foreach遍历。

    关于上述示例中< foreach >元素中使用的几种属性的描述具体如下:

    • item:配置的是循环中当前的元素
    • index:配置的是当前元素在集合的位置下标
    • collection:配置的list是传递过来参数类型(首字母小写),它可以是一个array、list(或collection)、Map集合的键、POJO- 包装类中数组或集合类型的属性名等。
    • open和close:配置的是以什么符号将这些集合元素包装起来
    • separator:配置的是各个元素间隔符

    对于collection

    • 如果传入的是单参数且参数类型是一个数组或者List的时候,collection属性值分别为array和list(或collection)。
    • 如果传入的参数是多个的时候,就需要把它们封装成一个Map了,当然单参数也可以封装成Map集合,这时候collection属性值就为Map的键。
    • 如果传入的参数是POJO包装类的时候,collection属性值就为该包装类中需要进行遍历的数组或集合的属性名。

    8.7 < bind >元素

    模糊查询

    select * from t_customer where username like '%${value}%'
    

    存在的问题:

    • 如果使用“${}”进行字符串拼接,则无法防止SQL注入问题;
    • 如果改用concat函数进行拼接,则只针对MySQL数据库有效;
    • 如果改用“||”进行字符串拼接,则只针对Oracle数据库有效。
      < bind >元素来解决这一问题。可解决这一问题
         <select id="findCustomerByName" parameterType="com.itheima.po.Customer"
                     resultType="com.itheima.po.Customer">
              <bind name="pattern_username" value="'%'+_parameter.getUsername()+'%'" />
              <!--_parameter.getUsername()表示传递进来的参数(也可以直接写成对应的参数变量名,如username)-->
               select * from t_customer 
               where 
               username like #{pattern_username}
         </select>
    

    思考

    • 请简述MyBatis框架动态SQL中的主要元素及其作用。
    • 请简述MyBatis框架动态SQL中< foreach >元素collection属性的注意事项。

    9 MyBatis的关联映射

    目标:

    • 一对一、一对多和多对多关联映射的使用(掌握)
    • 关联关系中的嵌套查询和嵌套结果(熟悉)
    • 数据表之间以及对象之间的三种关联关系(了解)

    9.1 关联关系概述

    为什么学习MyBatis关联关系?
    实际的开发中,对数据库的操作常常会涉及到多张表,这在面向对象中就涉及到了对象与对象之间的关联关系。针对多表之间的操作,MyBatis提供了关联映射,通过关联映射就可以很好的处理对象与对象之间的关联关系。本章中,将对MyBatis的关联关系映射进行详细的讲解。

    在关系型数据库中,多表之间存在着三种关联关系,分别为一对一一对多多对多

    • 一对一 在任意一方引入对方主键作为外键;
    • 一对多 在“多”的一方,添加“一”的一方的主键作为外键;
    • 多对多 产生中间关系表,引入两张表的主键作为外键,两个主键成为联合主键或使用新的字段作为主键。

    在Java中,通过对象也可以进行关联关系描述

    在这里插入图片描述

    • 一对一 在本类中定义对方类型的对象,如A类中定义B类类型的属性b,B类中定义A类类型的属性a;
    • 一对多 一个A类类型对应多个B类类型的情况,需要在A类中以集合的方式引入B类类型的对象,在B类中定义A类类型的属性a;
    • 多对多 在A类中定义B类类型的集合,在B类中定义A类类型的集合。

    9.2 一对一

    在现实生活中,一对一关联关系是十分常见的。例如,一个人只能有一个身份证,同时一个身份证也只会对应一个人。
    < resultMap >元素中,包含了一个< association >子元素,MyBatis就是通过该元素来处理一对一关联关系的。

    在< association >元素中,通常可以配置以下属性:
    在这里插入图片描述
    MyBatis加载关联关系对象主要通过两种方式:嵌套查询嵌套结果

    • 嵌套查询
      嵌套查询是通过执行另外一条SQL映射语句来返回预期的复杂类型。
      嵌套查询是在查询SQL中嵌入一个子查询SQL;
      嵌套查询会执行多条SQL语句;
      嵌套查询SQL语句编写较为简单;
    • 嵌套结果
      嵌套结果是使用嵌套结果映射来处理重复的联合结果的子集。
      嵌套结果是一个嵌套的多表查询SQL;
      嵌套结果只会执行一条复杂的SQL语句;
      嵌套结果SQL语句编写比较复杂;

    嵌套查询存在的问题
    虽然使用嵌套查询的方式比较简单,但是嵌套查询的方式要执行多条SQL语句,这对于大型数据集合和列表展示不是很好,因为这样可能会导致成百上千条关联的SQL语句被执行,从而极大的消耗数据库性能并且会降低查询效率
    解决
    使用MyBatis的延迟加载在一定程度上可以降低运行消耗提高查询效率。MyBatis默认没有开启延迟加载,需要在核心配置文件中的< settings >元素内进行配置,具体配置方式如下:

        <settings>
                <setting name="lazyLoadingEnabled" value="true" />  
                <setting name="aggressiveLazyLoading" value="false"/>  
        </settings>
    

    在映射文件中,< association >元素和< collection >元素中都已默认配置了延迟加载属性,即默认属性fetchType=“lazy”(属性fetchType="eager"表示立即加载),所以在配置文件中开启延迟加载后,无需在映射文件中再做配置

    在这里插入图片描述
    在这里插入图片描述

    9.3 一对多

    开发人员接触更多的关联关系是一对多(或多对一)。例如,一个用户可以有多个订单,同时多个订单归一个用户所有。
    < resultMap >元素中,包含了一个< collection >子元素,MyBatis就是通过该元素来处理一对多关联关系的。

    < collection >子元素的属性大部分与< association >元素相同,但其还包含一个特殊属性–ofType
    ofType属性与javaType属性对应,它用于指定实体对象中集合类属性所包含的元素类型
    在这里插入图片描述

    9.4 多对多

    在实际项目开发中,多对多的关联关系也是非常常见的。以订单和商品为例,一个订单可以包含多种商品,而一种商品又可以属于多个订单。
    多对多的关联关系通常使用一个中间表来维护
    在这里插入图片描述
    在MyBatis中,多对多的关联关系查询,同样可以使用前面介绍的< collection >元素进行处理(其用法和一对多关联关系查询语句用法基本相同)。

    思考

    • 请简述不同对象之间的三种关联关系。
    • 请简述MyBatis关联查询映射的两种处理方式

    10 MyBatis与Spring的整合

    目标:

    • 传统DAO方式的开发整合(掌握)
      Mapper接口方式的开发整合(掌握)

    10.1 整合环境搭建

    10.1.1 准备所需JAR包

    1. 导入Spring框架需要的jar包
    2. 导入Mybatis框架需要的jar包
    3. 导入Spring和Mybatis整合的中间jar
    4. 导入数据库驱动jar
    5. 导入数据源所需jar

    10.1.2 编写配置文件

    1. 编写db.properties
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
    jdbc.username=root
    jdbc.password=root
    jdbc.maxTotal=30
    jdbc.maxIdle=10
    jdbc.initialSize=5
    
    1. 编写Spring配置文件applicationContext.xml
     <beans xmlns="http://www.springframework.org/schema/beans"
        ...
        <context:property-placeholder location="classpath:db.properties"/>###读取db.properties
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"> ###配置数据源
            	<property name="driverClassName" value="${jdbc.driver}" />
           	 <property name="url" value="${jdbc.url}" />
           	 <property name="username" value="${jdbc.username}" />
    	 <property name="password" value="${jdbc.password}" />
    	 <property name="maxTotal" value="${jdbc.maxTotal}" />
    	 <property name="maxIdle" value="${jdbc.maxIdle}" />
    	 <property name="initialSize" value="${jdbc.initialSize}" />
        </bean>
        ###配置事务管理器
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            	<property name="dataSource" ref="dataSource" />
        </bean>	
        ### 开启事务注解
        <tx:annotation-driven transaction-manager="transactionManager"/>
        ### 配置MyBatis工厂
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
                     <property name="dataSource" ref="dataSource" />
                     <property name="configLocation" value="classpath:mybatis-config.xml"/>
       </bean>
    </beans>
    
    1. 编写MyBatis配置文件mybatis-config.xml
    <?xml version="1.0" encoding="UTF-8" ?><configuration> 
          <typeAliases>
                 <package name="com.itheima.po" />
          </typeAliases> 
    	    <mappers> 
                    ...
    	   </mappers>
    </configuration>
    
    1. 引入log4j.properties
    # Global logging configuration
    log4j.rootLogger=ERROR, stdout
    # MyBatis logging configuration...
    log4j.logger.com.itheima=DEBUG
    # Console output...
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    

    10.2 传统DAO方式的开发整合

    采用传统DAO开发方式进行MyBatis与Spring框架的整合时,可以使用mybatis-spring包中所提供的SqlSessionTemplate类或SqlSessionDaoSupport类来实现。

    • SqlSessionTemplate
      是mybatis-spring的核心类,它负责管理MyBatis的SqlSession,调用MyBatis的SQL方法。当调用SQL方法时,SqlSessionTemplate将会保证使用的SqlSession和当前Spring的事务是相关的。它还管理SqlSession的生命周期,包含必要的关闭、提交和回滚操作。
    • SqlSessionDaoSupport:是一个抽象支持类,它继承了DaoSupport类,主要是作为DAO的基类来使用。可以通过SqlSessionDaoSupport类的getSqlSession()方法来获取所需的SqlSession。

    需要实现抽象Daol类的实现类

    10.3 Mapper接口方式的开发整合

    在MyBatis+Spring的项目中,虽然使用传统的DAO开发方式可以实现所需功能,但是采用这种方式在实现类中会出现大量的重复代码,在方法中也需要指定映射文件中执行语句的id,并且不能保证编写时id的正确性(运行时才能知道)。
    为此,我们可以使用MyBatis提供的另外一种编程方式,即使用Mapper接口编程。

    MapperFactoryBean是MyBatis-Spring团队提供的一个用于根据Mapper接口生成Mapper对象的类,该类在Spring配置文件中使用时可以配置以下参数:

    • mapperInterface:用于指定接口;
    • SqlSessionFactory:用于指定SqlSessionFactory;
    • SqlSessionTemplate:用于指定SqlSessionTemplate。如果与SqlSessionFactory同时设定,则只会启用SqlSessionTemplate。

    application.xml

    	<!-- Mapper代理开发(基于MapperFactoryBean) -->
    	<bean id="customerMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    	    <property name="mapperInterface" value="com.itheima.mapper.CustomerMapper" />
    	    <property name="sqlSessionFactory" ref="sqlSessionFactory" />  
    	</bean> 
    	<!-- Mapper代理开发(基于MapperScannerConfigurer) -->
    	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    	     <property name="basePackage" value="com.itheima.mapper" />
    	</bean>
    

    mybatis.xml

           <!-- Mapper接口开发方式 -->
    	   <mapper resource="com/itheima/mapper/CustomerMapper.xml" /> 
    

    10.3.1 基于MapperFactoryBean的整合

    规范

    • Mapper接口的名称和对应的Mapper.xml映射文件的名称必须一致。
    • Mapper.xml文件中的namespace与Mapper接口的类路径相同。
    • Mapper接口中的方法名和Mapper.xml中定义的每个执行语句的id相同。
    • Mapper接口中方法的输入参数类型要和Mapper.xml中定义的每个sql的parameterType的类型相同。
    • Mapper接口方法的输出参数类型要和Mapper.xml中定义的每个sql的resultType的类型相同。

    10.3.2 基于MapperScannerConfigurer的整合

    MapperScannerConfigurer的作用是完成抽象Dao类的实现。
    MapperScannerConfigurer类在Spring配置文件中可以配置以下属性:

    • basePackage:指定映射接口文件所在的包路径,当需要扫描多个包时可以使用分号或逗号作为分隔符。指定包路径后,会扫描该包及其子包中的所有文件。
    • annotationClass:指定了要扫描的注解名称,只有被注解标识的类才会被配置为映射器。
    • sqlSessionFactoryBeanName:指定在Spring中定义的SqlSessionFactory的Bean名称。
    • sqlSessionTemplateBeanName:指定在Spring中定义的SqlSessionTemplate的Bean名称。如果定义此属性,则sqlSessionFactoryBeanName将不起作用。
    • markerInterface:指定创建映射器的接口。

    applicationContext.xml

    <!-- Mapper代理开发(基于MapperScannerConfigurer) -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
         <property name="basePackage" value="com.itheima.mapper" />     ###通过basePackage属性指定需要扫描的包即可
    </bean>
    

    10.4 测试事务

    在项目中,Service层既是处理业务的地方,又是管理数据库事务的地方。要对事务进行测试,首先需要创建Service层,并在Service层编写添加客户操作的代码;然后在添加操作的代码后,有意的添加一段异常代码(如int i = 1/0;)来模拟现实中的意外情况;最后编写测试方法,调用业务层的添加方法。这样,程序在执行到错误代码时就会出现异常。
    在没有事务管理的情况下,即使出现了异常,数据也会被存储到数据表中;
    如果添加了事务管理,并且事务管理的配置正确,那么在执行上述操作时,所添加的数据将不能够插入到数据表中

    思考

    • 请简述MyBatis与Spring整合所需JAR包的种类。
    • 请简述MapperFactoryBean和MapperScannerConfigurer的作用。

    11 Spring MVC入门

    目标:

    • Spirng MVC入门程序的编写(掌握)
    • Spring MVC的工作流程(熟悉)
    • Spring MVC的特点(了解)

    1.1 Spring MVC概述

    Spring MVC是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架。它与Struts2框架一样,都属于MVC框架,但其使用和性能等方面比Struts2更加优异。

    特点:

    • 是Spring框架的一部分,可以方便的利用Spring所提供的其他功能。
    • 灵活性强,易于与其他框架集成。
    • 提供了一个前端控制器DispatcherServlet,使开发人员无需额外开发控制器对象。
    • 可自动绑定用户输入,并能正确的转换数据类型。
    • 内置了常见的校验器,可以校验用户输入。如果校验不能通过,那么就会重定向到输入表单。
    • 支持国际化。可以根据用户区域显示多国语言。
    • 支持多种视图技术。它支持JSP、Velocity和FreeMarker等视图技术。
    • 使用基于XML的配置文件,在编辑后,不需要重新编译应用程序。

    11.2 第一个Spring MVC应用

    1. 在web.xml中,配置Spring MVC的前端控制器DispatcherServlet。
      在这里插入图片描述

    2. 在src目录下,创建一个com.itheima.controller包,并在包中创建控制器类FirstController,该类需要实现Controller接口,编辑后如下所示。
      在这里插入图片描述

    3. 在src目录下,创建配置文件springmvc-config.xml,并在文件中配置控制器信息。
      在这里插入图片描述

    4. 在WEB-INF目录下,创建一个jsp文件夹,并在文件夹中创建一个页面文件first.jsp,在该页面中使用EL表达式获取msg中的信息,如下所示。
      5.

    11.3 Spring MVC的工作流程

    在这里插入图片描述
    用户通过浏览器向服务器发送请求,请求会被Spring MVC的前端控制器DispatcherServlet所拦截;
    ②DispatcherServlet拦截到请求后,会调用HandlerMapping处理器映射器;
    ③处理器映射器根据请求URL找到具体的处理器,生成处理器对象处理器拦截器(如果有则生成)一并返回DispatcherServlet;
    ④DispatcherServlet会通过返回信息选择合适的HandlerAdapter(处理器适配器);
    HandlerAdapter会调用并执行Handler(处理器),这里的处理器指的就是程序中编写的Controller类,也被称之为后端控制器;
    Controller执行完成后,会返回一个ModelAndView对象,该对象中会包含视图名或包含模型和视图名;
    HandlerAdapterModelAndView对象返回给DispatcherServlet;
    DispatcherServlet会根据ModelAndView对象选择一个合适的ViewReslover(视图解析器);
    ⑨ViewReslover解析后,会向DispatcherServlet中返回具体的View(视图);
    ⑩DispatcherServlet对View进行渲染(即将模型数据填充至视图中);
    ⑪视图渲染结果会返回给客户端浏览器显示。

    思考

    • 请简述Spring MVC框架的优点。
    • 请简述Spring MVC框架的工作执行流程。

    12 Spring MVC的核心类和注解

    目标:

    • Spring MVC常用注解的使用(掌握)
    • Spring MVC核心类的作用(了解)

    12.1 DispatcherServlet

    DispatcherServlet的全名是org.springframework.web.servlet.DispatcherServlet,它在程序中充当着前端控制器的角色。在使用时,只需将其配置在项目的web.xml文件中,其配置代码如下:

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>
              org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <!--如果没有通过<init-param>元素配置,则应用程序会默认去WEB-INF目录下寻找以servletName-servlet.xml方式命名的配置文件,
        这里servletName指下面的springmvc-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    

    12.2 @Controller注解类型

    org.springframework.stereotype.Controller注解类型用于指示Spring类的实例一个控制器,其注解形式为@Controller。该注解在使用时不需要再实现Controller接口,只需要将@Controller注解加入到控制器类上,然后通过Spring的扫描机制找到标注了该注解的控制器即可。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:context="http://www.springframework.org/schema/context"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                                                 http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                                                 http://www.springframework.org/schema/context 
                                                 http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    	<context:component-scan base-package="com.itheima.controller" /> ###要扫描的包
    </beans> 
    

    12.3 @RequestMapping注解类型

    12.3.1 RequestMapping注解的使用

    Spring通过**@Controller注解找到相应的控制器类后,还需要知道控制器内部对每一个请求是如何处理的,这就需要使用@RequestMapping注解类型**,它用于映射一个请求一个方法。使用时,可以标注在一个方法一个类上

    12.3.2 RequestMapping注解的属性

    @RequestMapping注解除了可以指定value属性外,还可以指定其他一些属性,如下表所示。
    在这里插入图片描述
    表中所有属性都是可选的,但其默认属性是value。当value是其唯一属性时,
    可以省略属性名。例如,下面两种标注的含义相同:
    @RequestMapping(value="/firstController")
    @RequestMapping("/firstController")

    12.3.3 组合注解

    • @GetMapping:匹配GET方式的请求;
      以@GetMapping为例,该组合注解是@RequestMapping(method = RequestMethod.GET)的缩写,它会将HTTP GET请求映射到特定的处理方法上。
    @GetMapping(value="/user/{id}")
    public String selectUserById(String id){
        ...
    }
    
    • @PostMapping:匹配POST方式的请求;
    • @PutMapping:匹配PUT方式的请求;
    • @DeleteMapping:匹配DELETE方式的请求;
    • @PatchMapping:匹配PATCH方式的请求。

    12.3.4 请求处理方法的参数和返回类型

    在控制器类中,每一个请求处理方法都可以有多个不同类型的参数,以及一个多种类型的返回结果
    在这里插入图片描述

    Spring MVC所支持的常见方法返回类型如下:
    在这里插入图片描述
    由于ModelAndView类型****未能实现数据与视图之间的解耦,所以在企业开发时,方法的返回类型通常都会使用String。
    通过Model参数类型,即可添加需要在视图中显示的属性,其示例代码如下:

    @RequestMapping(value="/firstController")
    public String handleRequest(HttpServletRequest request,
                                                   HttpServletResponse response, Model model) {
            model.addAttribute("msg", "这是我的第一个Spring MVC程序");
            return "/WEB-INF/jsp/first.jsp";
    }
    

    String类型除了可以返回上述代码中的视图页面外,还可以进行重定向与请求转发,具体方式如下:

    1. **redirect 重定向。**例如,在修改用户信息操作后,将请求重定向到用户查询方法的实现代码如下:
    @RequestMapping(value="/update")
    public String update(HttpServletRequest request,HttpServletResponse response, Model model){
           ... 
           return "redirect:queryUser";
    }
    
    1. **forward 请求转发。**例如,用户执行修改操作时,转发到用户修改页面的实现代码如下:
    @RequestMapping(value="/toEdit")
    public String update(HttpServletRequest request,HttpServletResponse response, Model model){
           ... 
           return "forward:editUser";
    }
    

    12.4 ViewResolver

    Spring MVC中的视图解析器负责解析视图。可以通过在配置文件中定义一个ViewResolver来配置视图解析器,其配置示例如下:

    <bean id="viewResolver"    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/" /> ##前缀
            <property name="suffix" value=".jsp" />   ##后缀
    </bean>
    

    在上述代码中,定义了一个视图解析器,并设置了视图的前缀和后缀属性。这样设置后,方法中所定义的view路径将可以简化。例如,入门案例中的逻辑视图名只需设置为“first”,而不再需要设置为“/WEB-INF/jsp/first.jsp”,在访问时视图解析器会自动的增加前缀和后缀

    12.5 基于注解的Spring MVC应用

    思考

    • 请简述Controller注解的使用步骤。
    • 请列举请求处理方法的参数类型和返回类型(至少5个)。

    13 数据绑定

    目标:

    • Spring MVC数据绑定的使用(掌握)
    • Spring MVC中的几种数据绑定类型(熟悉)
    • Spring MVC中数据绑定的概念(了解)

    13.1 数据绑定介绍

    在执行程序时,Spring MVC会根据客户端请求参数的不同,将请求消息中的信息以一定的方式转换并绑定到控制器类的方法参数中。这种将请求消息数据后台方法参数 建立连接的过程就是Spring MVC中的数据绑定。

    Spring MVC是怎样完成数据绑定
    在数据绑定过程中,Spring MVC框架会通过**数据绑定组件(DataBinder)**将请求参数串的内容进行类型转换,然后将转换后的值赋给控制器类中方法的形参,这样后台方法就可以正确绑定并获取客户端请求携带的参数了。接下来,将通过一张数据流程图来介绍数据绑定的过程。
    在这里插入图片描述
    ①Spring MVC将ServletRequest对象传递给DataBinder;
    ②将处理方法的入参对象传递给DataBinder;
    ③DataBinder调用ConversionService组件进行数据类型转换、数据格式化等工作,并将ServletRequest对象中的消息填充到参数对象中;
    ④调用Validator组件对已经绑定了请求消息数据的参数对象进行数据合法性校验;
    ⑤校验完成后会生成数据绑定结果BindingResult对象,Spring MVC会将BindingResult对象中的内容赋给处理方法的相应参数。

    13.2 简单数据绑定

    根据客户端请求参数类型和个数的不同,我们将Spring MVC中的数据绑定主要分为简单数据绑定复杂数据绑定,接下来的几个小节中,就对这两种类型数据绑定进行详细讲解。
    当前端请求的参数比较简单时,可以在后台方法的形参中直接使用Spring MVC提供的默认参数类型进行数据绑定。

    • HttpServletRequest:通过request对象获取请求信息;
    • HttpServletResponse:通过response处理响应信息;
    • HttpSession:通过session对象得到session中存放的对象;
    • Model/ModelMap:Model是一个接口,ModelMap是一个接口实现,作用是将model数据填充到request域。

    13.2.1 绑定默认数据类型

          @Controller
          public class UserController {
              @RequestMapping("/selectUser")
              public String selectUser(HttpServletRequest request) {
    	      String id = request.getParameter("id");	
    	      System.out.println("id="+id);
    	      return "success";
    	}
         }
    

    13.2.2 绑定简单数据类型

    简单数据类型的绑定,就是指Java中几种基本数据类型的绑定,例如int、String、Double等类型。这里仍然以上一小节中的参数id为1的请求为例,来讲解简单数据类型的绑定。

    @RequestMapping("/selectUser")
    public String selectUser(Integer id) {
        System.out.println("id="+id);
        return "success";
    }
    

    这里需要注意的是,有时候前端请求中参数名后台控制器类方法中形参名不一样,这就会导致后台无法正确绑定并接收到前端请求的参数。
    使用Spring MVC提供的@RequestParam注解类型来进行间接数据绑定。
    @RequestParam注解的属性声明如下:
    在这里插入图片描述

    @RequestMapping("/selectUser")
    public String selectUser(@RequestParam(value="user_id")Integer id) {
         System.out.println("id="+id);
         return "success";
    }
    

    13.2.3 绑定POJO类型

    在使用简单数据类型绑定时,可以很容易的根据具体需求来定义方法中的形参类型和个数,然而在实际应用中,客户端请求可能会传递多个不同类型的参数数据,如果还使用简单数据类型进行绑定,那么就需要手动编写多个不同类型的参数,这种操作显然比较繁琐。
    针对多类型、多参数的请求,可以使用POJO类型进行数据绑定
    POJO类型的数据绑定就是将所有关联的请求参数 封装在一个POJO中,然后在方法中直接使用该POJO作为形参来完成数据绑定。

    在前端请求中,难免会有中文信息传递,此时后台方法绑定接收的中文信息却就会出现了中文乱码,为了防止前端传入的中文数据出现乱码问题,我们可以在web.xml中配置Spring提供的编码过滤器来统一编码。

    <filter>
            <filter-name>CharacterEncodingFilter</filter-name>		
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                       <param-name>encoding</param-name>
                       <param-value>UTF-8</param-value>
            </init-param>
    </filter>
    <filter-mapping>
    		<!--拦截所有URL请求,交由编码过滤器-->
           <filter-name>CharacterEncodingFilter</filter-name>
           <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    13.2.4 绑定包装POJO

    在用户查询订单时,页面传递的参数可能包括:订单编号、用户名称等信息,这就包含了订单和用户两个对象的信息,此时后台方法如何绑定请求信息呢?
    所谓的包装POJO,就是在一个POJO****中包含另一个简单POJO。例如,在订单对象中包含用户对象。这样在使用时,就可以通过订单查询到用户信息。

    public class Orders {
    	private Integer ordersId; 
    	private User user;         
        //...省略getter/setter方法
    }
    

    前端传递参数
    在这里插入图片描述
    后端获取参数

    @RequestMapping("/findOrdersWithUser")
    public String findOrdersWithUser(Orders orders) {
    	 Integer orderId = orders.getOrdersId();
    	 User user = orders.getUser();
    	 String username = user.getUsername();
    	 System.out.println("orderId="+orderId);
    	 System.out.println("username="+username);
    	 return "success";
    }
    

    13.2.5 自定义数据绑定

    针对特殊数据类型,就需要开发者自定义转换器(Converter)格式化(Formatter) 来进行数据绑定。

    Spring框架提供了一个Converter用于将一种类型的对象转换为另一种类型的对象。
    自定义Converter类需要实现 org.springframework.core.convert.converter.Converter接口

    Formatter与Converter的作用相同,只是Formatter源类型必须是一个String类型,而Converter可以是任意类型。
    使用Formatter自定义转换器类需要实现org.springframework.format.Formatter接口。

    /**
     * 自定义日期转换器
     */
    public class DateConverter implements Converter<String, Date> {
    	// 定义日期格式
    	private String datePattern = "yyyy-MM-dd HH:mm:ss";
    	@Override
    	public Date convert(String source) {
             // 格式化日期
    		SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
    		try {
    			return sdf.parse(source);
    		} catch (ParseException e) {
    			throw new IllegalArgumentException(
    					"无效的日期格式,请使用这种格式:"+datePattern);
    		}
    	}
    }
    
    /**
     * 使用Formatter自定义日期转换器
     */
    public class DateFormatter implements Formatter<Date>{
        // 定义日期格式
    	String datePattern = "yyyy-MM-dd HH:mm:ss";
    	// 声明SimpleDateFormat对象
        private SimpleDateFormat simpleDateFormat;   
    	@Override
    	public String print(Date date, Locale locale) {
    		return new SimpleDateFormat().format(date);
    	}
    	@Override
         public Date parse(String source, Locale locale) throws ParseException
         {
    		simpleDateFormat = new SimpleDateFormat(datePattern);
    		return simpleDateFormat.parse(source);
    	}
    }
    

    application.xml

    	<!-- 显示的装配自定义类型转换器 --> 
    	<mvc:annotation-driven conversion-service="conversionService" />
    	<!-- 自定义类型转换器配置 -->
    <!-- 	<bean id="conversionService" class=
         "org.springframework.context.support.ConversionServiceFactoryBean">
    		<property name="converters">
    			<set>
    				<bean class="com.itheima.convert.DateConverter" />
    			</set>
    		</property>
    	</bean> -->
    	<!-- 自定义类型格式化转换器配置 -->
    	<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        	<property name="formatters">
            	<set>
                	<bean class="com.itheima.convert.DateFormatter" />
            	</set>
        	</property>
    	</bean>
    

    13.3 复杂数据绑定

    可能遇到一些比较复杂的数据绑定问题,比如数组的绑定、集合的绑定

    在实际开发时,可能会遇到前端请求需要传递到后台一个或相同名称参数的情况(如批量删除),此种情况采用前面讲解的简单数据绑定的方式显然是不合适的。
    针对上述这种情况,如果将所有同种类型的请求参数封装到一个数组中,后台就可以进行绑定接收了。

    13.3.1 绑定数组

    前端
    在这里插入图片描述
    在这里插入图片描述
    后端
    在这里插入图片描述
    在批量删除用户的操作中,前端请求传递的都是同名参数的用户id,只要在后台使用同一种数组类型的参数绑定接收,就可以在方法中通过循环数组参数的方式来完成删除操作。

    13.3.2 绑定集合

    如果是批量修改用户操作的话,前端请求传递过来的数据可能就会批量包含各种类型的数据,如Integer,String等。
    针对上述这种情况,就可以使用集合数据绑定。即在包装类中定义一个包含用户信息类的集合,然后在接收方法中将参数类型定义为该包装类的集合
    包装类
    在这里插入图片描述
    前端
    在这里插入图片描述
    在这里插入图片描述

    后端
    在这里插入图片描述

    思考

    • 请简述简单数据类型中的@RequestParam注解及其属性作用。
    • 请简述包装POJO类型绑定时的注意事项。

    14 JSON数据交互和RESTful支持

    目标:

    • Spring MVC中JSON数据交互的使用和Spring MVC中RESTful风格请求的使用(掌握)
    • RESTful风格的请求样式(熟悉)
    • JSON的数据结构(了解)

    14.1 JSON数据交互

    14.1.1 JSON概述

    JSON(JavaScript Object Notation,JS对象标记)是一种轻量级的数据交换格式。它是基于JavaScript的一个子集,使用了C、C++、C#、Java、JavaScript、Perl、Python等其他语言的约定,采用完全独立于编程语言的文本格式来存储和表示数据。

    JSON有什么特点

    JSON与XML非常相似,都是用来存储数据的,并且都是基于纯文本的数据格式。
    与XML相比,JSON解析速度更快占用空间更小,且易于阅读和编写,同时也易于机器解析和生成

    JSON有如下两种数据结构

    1. 对象结构
      在对象结构以“{”开始,以“}”结束。中间部分由0个或多个以英文“,”分隔的name:value对构成(注意name和value之间以英文“:”分隔),其存储形式如下图所示。
      在这里插入图片描述
    {"city":"Beijing","street":"Xisanqi","postcode":100096}
    
    1. 数组结构
      数组结构以“[”开始,以“]”结束。中间部分由0个或多个以英文“,”分隔的值的列表组成,其存储形式如下图所示。
      在这里插入图片描述
    ["abc",12345,false,null]
    

    14.1.2 JSON数据转换

    Spring提供了一个HttpMessageConverter< T >接口来实现浏览器与控制器类(Controller)之间的数据交互。该接口主要用于将请求信息中的数据转换为一个类型为T的对象,并将类型为T的对象绑定到请求方法的参数中,或者将对象转换为响应信息传递给浏览器显示。
    HttpMessageConverter< T >接口有很多实现类,这些实现类可以对不同类型的数据进行信息转换。其中MappingJackson2HttpMessageConverter是Spring MVC默认处理JSON格式请求响应的实现类。该实现类利用Jackson开源包读写JSON数据,将Java对象转换为JSON对象XML文档同时也可以将JSON对象和XML文档转换为Java对象。

    使用注解

    在使用注解式开发时,需要用到2个重要的JSON格式转换注解,分别为@RequestBody和@ResponseBody,关于这两个注解的说明如下表所示:
    在这里插入图片描述

    Json注解驱动配置

    在配置JSON转换器时,除了常用的< mvc:annotation-drivern />方式配置外,还可以使用< bean >标签的方式进行显示的配置。具体配置方式如下:

    	<!-- <bean>标签配置注解方式的处理器映射器和处理器适配器必须配对使用 -->
    	<!-- 使用<bean>标签配置注解方式的处理器映射器 -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
    		<!--配置处理器适配器-->
    	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    		<property name="messageConverters">
    			<list>
    				<!--在注解适配器中配置JSON转换器-->
    				<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
    			</list>
    		</property>
    	</bean> 
    	小提示:使用<bean>标签配置注解方式的处理器映射器和处理器适配器必须配对使用。
    

    配置静态资源的访问方式

    1. 在springmvc-config.xml文件中,使用< mvc:default-servlet-handler >标签
    <mvc:default-servlet-handler />
    
    1. 激活Tomcat默认的Servlet来处理静态文件访问
     <!--激活tomcat的静态资源拦截,需要哪些静态文件,再往下追加-->
    <servlet-mapping>
    	<servlet-name>default</servlet-name>
    	<url-pattern>*.js</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    	<servlet-name>default</servlet-name>
    	<url-pattern>*.css</url-pattern>
    </servlet-mapping>
    ...
    

    以上两种方式本质上是一样的,都是使用Web服务器默认的Servlet处理静态资源文件的访问。其中Servelt名称也是由使用的服务器来确定的,不同的服务器需要使用不同的名称,常用服务器及其Servlet名称如下:

    常用服务器及其Servlet名称如下:

    在这里插入图片描述

    14.2 RESTful支持

    RESTful也称之为REST,是英文“Representational State Transfer”的简称。可以将他理解为一种软件架构风格或设计风格,而不是一个标准。
    在这里插入图片描述

    思考

    • 请简述JSON数据交互两个注解的作用。
    • 请简述静态资源访问的几种配置方式。

    15 拦截器

    目标:

    • 拦截器的使用(掌握)
    • 拦截器的执行流程(熟悉)
    • 拦截器的定义和配置方式(了解)

    15.1 拦截器概述

    Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户 是否登录等。

    15.1.1 拦截器的定义

    • 通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义。
    • 通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义。

    以实现HandlerInterceptor接口方式为例,自定义拦截器类的代码如下:

         public class CustomInterceptor implements HandlerInterceptor{
         //该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;
         //当其返回值为false时,会中断后续的所有操作。
                public boolean preHandle(HttpServletRequest request, 
                HttpServletResponse response, Object handler)throws Exception {
    		return false;
    	}
    	//该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
    	public void postHandle(HttpServletRequest request, 
    		HttpServletResponse response, Object handler, 
    		ModelAndView modelAndView) throws Exception {
    	}
    	//该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。
    	public void afterCompletion(HttpServletRequest request, 
    			HttpServletResponse response, Object handler, 
    			Exception ex) throws Exception {		
              }
        }
    

    15.1.2 拦截器的配置

    要使自定义的拦截器类生效,还需要在Spring MVC的配置文件中进行配置。

        <mvc:interceptors>
        <!--全局拦截器,拦截所有请求-->
            <bean class="com.itheima.interceptor.CustomInterceptor"/>
           <mvc:interceptor>
                <mvc:mapping path="/**"/> <!--/**配置,表示拦截所有路径-->
                <mvc:exclude-mapping path=""/><!--配置不需要拦截的路径-->
                <bean class="com.itheima.interceptor.Interceptor1" /> 
           </mvc:interceptor>
           <mvc:interceptor>
                <mvc:mapping path="/hello"/><!--/hello表示拦截所有以“/hello”结尾的路径-->
                <bean class="com.itheima.interceptor.Interceptor2" />	   
            </mvc:interceptor>
            ...
         </mvc:interceptors>
    

    注意:< mvc:interceptor >中的子元素必须按照上述代码的配置顺序进行编写,否则文件会报错。

    15.2 拦截器的执行流程

    15.2.1 单个拦截器的执行流程

    在这里插入图片描述

    15.2.2 多个拦截器的执行流程

    在这里插入图片描述

    思考

    • 请简述Spring MVC拦截器的定义方式。
    • 请简述单个拦截器和多个拦截器的执行流程。

    16 文件上传和下载

    目标:

    • 文件下载程序的编写和文件上传案例的编写(掌握)
    • Spring MVC中文件上传的实现步骤(了解)

    16.1 文件上传

    16.1.1 文件上传概述

    多数文件上传都是通过表单形式提交给后台服务器的,因此,要实现文件上传功能,就需要提供一个文件上传的表单,而该表单必须满足以下3个条件:

    • form表单的method属性设置为post;
    • form表单的enctype属性设置为multipart/form-data;
    • 提供< input type=“file” name=“filename” />的文件上传输入框。

    1.表单配置

         <form action="uploadUrl" method="post" enctype="multipart/form-data">
         <!--multiple属性是HTML5中新属性,可实现多文件上传-->
              <input type="file" name="filename" multiple="multiple" />
              <input type="submit" value="文件上传" />
         </form>
    

    当form表单的enctype属性为multipart/form-data时,浏览器就会采用二进制流来处理表单数据,服务器端就会对文件上传的请求进行解析处理。Spring MVC通过MultipartResolver实现文件上传功能。MultipartResolver是一个接口对象,需要通过它的实现类CommonsMultipartResolver来完成文件上传工作。
    2.MultipartResolver配置示例如下

         <bean id="multipartResolver"          	     
                class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
          <!--设置请求编码格式,必须与JSP中的pageEncoding属性一致,默认为ISO-8859-1-->       
                 <property name="defaultEncoding" value="UTF-8" />
                 <!--设置允许上传文件的最大值(2M),单位为字节-->
                 <property name="maxUploadSize" value="2097152" />
                 ...
         </bean>
    

    在前面的配置代码中,除配置了CommonsMultipartResolver类外,还通过< property >元素配置了编码格式以及允许上传文件的大小。通过< property >元素可以对文件解析器类CommonsMultipartResolver的如下属性进行配置:

    • maxUploadSize:上传文件最大长度(以字节为单位);
    • maxInMemorySize:缓存中的最大尺寸;
    • defaultEncoding:默认编码格式;
    • resolveLazily:推迟文件解析,以便在Controller中捕获文件大小异常。
      注意:因为MultipartResolver接口的实现类CommonsMultipartResolver内部是引用multipartResolver字符串获取该实现类对象并完成文件解析的,所以在配置CommonsMultipartResolver时必须指定该Bean的id为multipartResolver

    3.当完成页面表单和文件上传解析器的配置后,在Controller中编写文件上传的方法即可实现文件上传,其代码如下所示:

         @Controller
         public class FileUploadController {
               @RequestMapping("/fileUpload ")
               //使用MultipartFile 绑定接收上传文件
               public String handleFormUpload(@RequestParam("name") String name,
                @RequestParam("filename") MultipartFile file,...) {
                //判断上传文件是否为空,然后进行解析存放处理
    	if (!file.isEmpty()) {
    		...
    		return "uploadSuccess";
    	}
    	return "uploadFailure";
                }
         }
    

    org.springframework.web.multipart.MultipartFile接口中提供了获取上传文件、文件名称等方法,如下表所示:
    在这里插入图片描述

    16.2 文件下载

    16.2.1 实现文件下载

    文件下载就是将文件服务器中的文件下载到本机上。在Spring MVC环境中,实现文件下载大致可分为如下两个步骤:

    • 在客户端页面使用一个文件下载的超链接,该链接的href属性要指定后台文件下载的方法以及文件名(需要先在文件下载目录中添加了一个名称为“1.jpg”的文件)。
         <a href="${pageContext.request.contextPath }/download?filename=1.jpg">
              文件下载 
         </a>
    
    • 在后台使用Spring MVC提供的ResponseEntity类型对象完成文件下载,使用它可以很方便的定义返回的HttpHeaders对象和HttpStatus对象,通过对这两个对象的设置,即可完成下载文件时所需的配置信息。
         @RequestMapping("/download")
         public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception{
         	//指定要下载的文件所在路径
              String path = request.getServletContext().getRealPath("/upload/");
              File file = new File(path+File.separator+filename);
              HttpHeaders headers = new HttpHeaders();
              //通知浏览器以下载的方式打开文件
              headers.setContentDispositionFormData("attachment", filename);
              //定义以流的形式下载返回文件数据
              headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
              //使用Sring MVC框架的ResponseEntity对象封装返回下载数据
        	return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.OK);
        }
    

    文件下载中的ResponseEntity对象有些类似前面章节中的@ResponseBody注解,它用于直接返回结果对象。
    响应头信息中的MediaType代表的是Interner Media Type(即互联网媒体类型),也叫做MIME类型,MediaType.APPLICATION_OCTET_STREAM的值为application/octet-stream,即表示以二进制流的形式下载数据
    HttpStatus类型代表的是Http协议中的状态,示例中的HttpStatus.OK表示200,即服务器已成功处理了请求。
    效果:
    在这里插入图片描述
    在这里插入图片描述

    16.2.2 中文名称的文件下载

    为了解决浏览器中文件下载时中文名称的乱码问题,可以在前端页面发送请求前先对中文名进行统一编码,然后在后台控制器类中对文件名称进行相应的转码
    前端:

      <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
      	##需要引入Encoder类
      <%@page import="java.net.URLEncoder"%>
      ...
      <body>
      ## 使用Encoder类的encoder()方法对中文名进行编码
          <a href="${pageContext.request.contextPath }/download?filename=<%=URLEncoder.encode(“ 
            壁纸.jpg", "UTF-8")%>">
    	中文名称文件下载 </a>
        </body>
    </html>
    

    后端:

        public String getFilename(HttpServletRequest request,String filename) throws Exception {
        //IE不同版本User-Agent中出现的关键词
              String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};  
              String userAgent = request.getHeader("User-Agent"); 
              //对不同的浏览器进行不同编码格式的转码
              for (String keyWord : IEBrowserKeyWords) { 
                    if (userAgent.contains(keyWord)) { 
                            return URLEncoder.encode(filename, "UTF-8");
                    }
              }  
              return new String(filename.getBytes("UTF-8"), "ISO-8859-1");  
        } 
    

    思考

    • 请简述上传表单需要满足的3个条件。
    • 请简述如何解决中文文件名称下载时的乱码问题。

    17 SSM框架整合

    目标:

    • SSM框架整合应用程序的编写(掌握)
    • SSM框架整合时的配置文件内容(熟悉)
    • SSM框架的整合思路(了解)

    17.1 整合环境搭建

    17.1.1 整合思路

    如何进行SSM框架整合
    由于Spring MVC是Spring框架中的一个模块,所以Spring MVC与Spring之间不存在整合的问题,只要引入相应JAR包就可以直接使用。因此SSM框架的整合就只涉及到了Spring与MyBatis的整合,以及Spring MVC与MyBatis的整合

    SSM框架整合图如下所示:
    在这里插入图片描述
    如何判断整合成功
    在第10章讲解Spring与MyBatis框架的整合时,我们是通过Spring实例化Bean,然后调用实例对象中的查询方法来执行MyBatis映射文件中的SQL语句的,如果能够正确查询出数据库中的数据,那么我们就认为Spring与MyBatis框架整合成功。同样,整合之后,如果我们可以通过前台页面来执行查询方法,并且查询出的数据能够在页面中正确显示,那么我们也可以认为三大框架整合成功。
    db.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
    jdbc.username=root
    jdbc.password=root
    jdbc.maxTotal=30
    jdbc.maxIdle=10
    jdbc.initialSize=5
    

    applicationContext.xml

     <context:property-placeholder location="classpath:db.properties"/>
     <!--数据源配置-->
     <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
                    <property name="driverClassName" value="${jdbc.driver}" />
     </bean>
     <!--配置事务管理器-->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                    <property name="dataSource" ref="dataSource" />
     </bean>	
     <!--开启事务注解-->             
      <tx:annotation-driven transaction-manager="transactionManager"/>
      <!--配置MyBatis工厂-->
      <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
                   <property name="dataSource" ref="dataSource" />
                   <property name="configLocation" value="classpath:mybatis-config.xml" />
      </bean>
       <!--配置mapper文件扫描器-->
      <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                   <property name="basePackage" value="com.itheima.dao"/>
      </bean>
      <!--Service层注解扫描-->
      <context:component-scan base-package="com.itheima.service" />
    

    mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    	<typeAliases>
    		<package name="com.itheima.po" />
    	</typeAliases>
    </configuration>
    

    springmvc-config.xml

    <!--Controller层注解扫描-->
    <context:component-scan base-package="com.itheima.controller" />
    <!--加载注解驱动-->
    <mvc:annotation-driven />
    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	<property name="prefix" value="/WEB-INF/jsp/" />
    	<property name="suffix" value=".jsp" />
    </bean>
    

    在web.xml中,配置Spring的文件监听器、编码过滤器以及Spring MVC的前端控制器等信息。
    web.xml

    <context-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--配置Spirng文件监听器-->
    <listener>
             <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
    <!--配置编码过滤器-->
             <filter-name>encoding</filter-name>
             <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
             <init-param>
                        <param-name>encoding</param-name>
                        <param-value>UTF-8</param-value>
              </init-param>
    </filter>
    <filter-mapping>
              <filter-name>encoding</filter-name>
              <url-pattern>*.action</url-pattern>
    </filter-mapping>
    <servlet>
    <!--配置Spirng MVC前端控制器-->
              <servlet-name>springmvc</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <init-param><param-name>contextConfigLocation</param-name>
              <param-value>classpath:springmvc-config.xml</param-value></init-param>
              <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
              <servlet-name>springmvc</servlet-name>
              <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    展开全文
  • 全国计算机四嵌入式系统开发工程师考试总结 1 考试题型和内容 一共考两门,操作系统原理和计算机组成与接口,每门50分,30道单项选择题,每题一分,10道多选题,每题2分。 2 考试实际情况 在网上买了全国计算机...

    全国计算机四级嵌入式系统开发工程师考试总结

    1 考试题型和内容

    一共考两门,操作系统原理和计算机组成与接口,每门50分,30道单项选择题,每题一分,10道多选题,每题2分。

    2 考试实际情况

    在网上买了全国计算机等级考试官方参考资料,两本书大概看了一遍,刷了十几套题。考试时有1/4的题没见过。下面就总结一下我考试时遇到的题型。

    2.1 操作系统原理

    操作系统的使用环境、实时操作系统的优点;中断源、中断点指什么;系统调用与一般过程调用的区别;独占设备;哪些会引起进程状态变化;PCB内容;管程、PV操作;哲学家就餐如何防止死锁;给出逻辑地址计算访问内存次数;下次适应算法;页表结构;使用快表与不使用快表的访问时间变化;Clock算法计算缺页率;给出物理块大小和地址计算访问磁盘次数;UNIX文件权限;SSTF算法;与设备无关的系统软件作用;银行家算法;资源分配图。

    2.2 计算机组成与接口

    BCD码;流水线排空;VIF标志;高位交叉编址多体存储器;DRAM刷新;存储器容量扩展;单标志条件转移指令;8259A引脚高低电平;特殊全嵌套优先级排列;8251A工作方式、引脚控制字;8255A的置位复位控制字、方式选择控制字;8253计数器个数、工作模式;AD7501引脚;总线层次特性。

    考试最大感受就是自己得理解原理,光靠刷题是不够的,计算机组成与接口各种芯片控制字、状态字、引脚等都得背,操作系统的各种页面置换算法、磁盘移臂调度算法都要知道原理,像这次我遇到了Clock算法,想不起来原理了。希望大家好好准备,考出好成绩!

    展开全文
  • 华为通过HMS Core全面开放“芯-端-云”的能力,帮助开发者实现高效开发、快速增长、商业变现,使能开发者创新,助力开发者高效构建精品的应用。 HMS Core从开发、增长和盈利三个环节为开发者提供支持。 ...

    HMS Core是华为面向开发者提供的开放能力合集,包括账号、支付、Push、地图等核心能力。华为通过HMS Core全面开放“芯-端-云”的能力,帮助开发者实现高效开发、快速增长、商业变现,使能开发者创新,助力开发者高效构建精品的应用。

     

     

    HMS Core从开发、增长和盈利三个环节为开发者提供支持。

     

    • 开发环节,提供账号、定位、机器学习等基础能力,帮助开发者快速构建高质量的移动应用;
    • 增长环节,提供Push、分析等能力,协助开发者精细化运营;
    • 盈利环节,提供应用内支付、广告等能力,助力开发者实现商业变现。


    图2-1展示了HMS Core开放能力框架。

    ▲图2-1 HMS Core视图

    HMS Core不断开放出新的能力,建议读者从开发者联盟官网选择需要的各类开放能力。下面通过实例来了解框架中的一些常用开放能力。

    01 开发:低成本快速构建优质应用
    本节介绍在App开发阶段常用的一些HMS开放能力,帮助开发者了解如何快速低成本地构建App,打造一款高质量的产品。
    1. Account Kit
    当用户开始体验一个移动App时,往往会因为烦琐的注册流程而中途退出,但通过了解用户的身份进而为其提供个性化体验,对于App而言又是十分必要的。如何平衡用户体验与获取用户之间的这种矛盾?Account Kit(华为账号服务)能帮你解决这个问题,其应用场景如图2-2所示。
    Account Kit在遵循OAuth 2.0(Open Authorization,开放式授权)和OpenID Connect(OIDC)等国际标准协议的基础上,为用户提供了简单、安全的登录授权功能,用户只需一键点击授权,就能通过华为账号快速登录应用,避免了烦琐的注册登录操作。

    1. 当用户重启应用时,华为账号默认是自动登录的状态,无须再次授权,这能帮开发者大大降低应用注册和登录环节的用户流失率。
    2. 在账号安全方面,Account Kit采用双因素身份验证的方式,对数据进行全流程加密,保障了全球范围内账号登录安全和隐私合规。
    3. Account Kit拥有覆盖全球的海量活跃用户,帮助开发者充分利用华为全场景生态平台的优势,在手机、平板、大屏、车机等各种华为终端设备上进行应用登录。

     

    ▲图2-2 Account Kit应用场景

    2. FIDO
    有了账号后,很多App在登录或者遇到支付场景时,往往需要进行身份验证,以确保账户或资金的安全。传统方式是通过输入密码来进行身份验证,但是使用密码存在一定的安全风险,并且对于不少用户来说,要牢牢记住密码也是一件困难的事情。
    那么,有没有一种既安全又便捷的身份验证方式呢?华为FIDO服务可以解决这个问题。
    FIDO为开发者提供了两个主要特性:线上快速身份验证(FIDO2)和本地生物特征认证(BioAuthn),可以支撑“在线用户身份验证”和“本地身份验证”两类场景(见图2-3)。

    ▲图2-3 FIDO应用场景

    3. Map、Site和Location
    在电商、快递物流、旅游和社交等场景中,地图服务、位置服务和定位服务是App不可缺少的功能。如电商App,通过定位和地图,用户可快速定位位置、添加地址信息。对于旅游类App,搜索地点,了解详情,寻找周边的酒店、美食等是用户常用的功能。
    华为Map Kit(地图服务)、Site Kit(位置服务)和Location Kit(定位服务)为这些App提供了基础软件能力。Map Kit和Site Kit都是基于地图的数据为开发者提供服务。

    • Map Kit提供地图呈现、地图绘制、地图交互、自定义地图样式和路径规划。
    • Site Kit提供丰富的地点数据,通过周边搜索、关键字搜索、地点详情查询和地理编码等查询能力帮助用户探索世界。
    • Location Kit采用GPS、Wi-Fi、基站等多途径的混合定位模式进行定位,精准地获取用户位置信息,提供融合定位、活动识别和地理围栏等功能。


    以3个场景来举例说明上述Kit的组合使用(见图2-4)。

    • 场景1:基于Location的定位数据,结合Site Kit能力可以进行附近地址的搜索。
    • 场景2:基于Location的定位数据,结合Map Kit能力可以进行路径规划。
    • 场景3:基于Site Kit的PoI(Point of Information,关注点)数据,结合Map Kit能力进行地图的绘制。

     

    ▲图2-4 Map、Site和Location应用场景

    除了这几个场景外,开发者可以基于实际的业务需要来对这些能力进行个性化的组合使用,全面提升应用的服务体验。
    4. Safety Detect
    今天,用户不仅关注App的功能体验,还关注App的使用安全。App所运行的设备是否安全,App是否会感染病毒,App是否会被攻击而泄露隐私,这些关注点已变成开发者必须考虑的因素。
    如何才能做好安全防护,保护用户的数据安全呢?
    Safety Detect覆盖多维度安全检测开放服务,包括系统完整性检测、应用安全检测、恶意URL检测和虚假用户检测,助力快速构建应用安全,保护用户数据安全。图2-5所示为Safety Detect应用场景。

    ▲图2-5 Safety Detect应用场景


    02 增长:持续提升用户量和活跃度
    通常开发者在运营一款App时,需要通过实时消息推送来保持与用户的黏性,进而提升用户的留存率和活跃度,持续做大用户流量。而实际情况下,针对海量用户群体的消息触达,往往面临两个比较突出的问题:

    • 一是如何在较短的时间内触达海量目标用户,实现“推得到”“推得快”和“推得准”;

    • 二是如何根据用户的标签、分组等维度向特定的人群进行消息推送,并准确获得用户使用效果反馈。


    针对以上问题,让我们来看下华为Push服务是如何解决的。

    1. 依托华为全球化的数据中心部署,华为Push服务覆盖多达200多个国家和地区,推送容量单日百亿级,推送速度达千万级/秒。
    2. 基于华为终端EMUI提供系统级的消息通道,即使在应用未启动的情况下,消息也可以正常接收并在设备上显示。同时,设备会以实时消息回执的方式来反馈发送状态,实现了对消息发送状态的全掌握。
    3. 华为Push服务支持按标签、主题、情景智能、地理围栏等方式对特定的受众发送消息,并支持多维度的数据统计分析。图2-6所示为华为Push服务推送的文本消息和图文消息。

     

    ▲图2-6 文本消息和图文消息


    03 盈利:利用多渠道实现开发者变现
    开发者开发一款App所追求的商业目标是盈利,通常需要通过广告或付费模式进行变现。在付费模式下,App需要提供购买支付能力,对接支付系统。
    而实际情况下,开发者面临很多支付通道选择,包括支付宝、微信、银联和运营商支付等。与多个支付系统实现对接,存在开发成本高、对接联调的时间周期很长的问题。华为支付可以帮你简化这些工作。
    1)华为IAP(In App Purchase)覆盖全球主流支付方式,聚合多条支付通道,提供全球化的支付服务。主要支付方式包括银行卡支付、DCB(Direct Carrier Billing)、花币支付和第三方支付(见图2-7)。
    其中,银行卡支付覆盖170多个国家,DCB支付覆盖超过47家运营商,花币支付覆盖全球70多个国家,第三方支付支持微信、支付宝、Sofort和iDeal等支付方式。

    ▲图2-7 全球主流支付方式
    2)IAP提供多种支付配套能力(见图2-8),包括商品管理、订单管理和订阅管理。商品管理支持超过62种语言、195个商品价格档位,支持170多个国家的本地货币自动定价,可根据国家或区域来调整定价策略。
    订单管理提供了丰富的订单管理开放接口,能够记录完整的订单信息,主动查询异常订单并及时补发,实现“零掉单”。订阅服务提供多样化的订阅策略,包括促销折扣、免费试用和延迟结算,支持订阅周期可配置。

    ▲图2-8 支付配套能力

    关于作者:王希海,华为终端云服务开发者联盟产品部部长,具有15年以上丰富的软件领域从业经验,华为终端HDD、HSD、HDG、HDE等生态项目创始人,消费者云服务DigiX系列赛首席评委,曾获深圳市科技进步奖。目前专注华为终端HMS开放能力的推广与布道,与全球开发者共同打造全场景智慧化终端生态。

    望岳,华为终端云服务HMS Core平台部部长,快应用联盟的发起和倡导者之一,20余年电信领域大型管理软件、分布式中间件与平台的研发和全球交付经验。曾发表多篇电信领域专利文章并取得国际专利。目前专注于华为终端HMS Core开放能力构建,助力全球开发者的商业成功。

    吴海亮,华为终端云服务开发者联盟首席技术专家,华为HDD和HMS开放能力首席课程讲师,10余年软件开发与架构设计经验,曾主导多个开放能力的开发项目。目前致力于HMS开放能力推广与全球开发者技术支持工作,亦作为布道师活跃于全球HMS生态发展项目。
     

                                                                                            扫描二维码加入华为了解更多

     

     

    展开全文
  • 开发一款Android App,从零开始详细讲解

    万次阅读 多人点赞 2021-03-04 17:16:38
    入门篇:第篇:开发环境篇第二篇:材料设计篇第三篇:规范开发篇第四篇:从项目开发到上架篇(篇章调整,最后更新) 进阶篇:第五篇:设计模式篇第六篇:网络请求篇(上)     网络请求篇(下)第七篇:图片...
  • 计算机一级考试中wps office和ms office这两个科目,总是让报考者傻傻分不清楚,报考时不知道该如何选择,不知道哪个更简单更容易考。一、计算机wps和ms哪个简单?答案当然是:wps因为wps是是国产软件,专门为中国人...
  • 作者:Michael Thiessen 译者:前端小智 来源:dev 有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。 ... 学习成为个更好的Vue开发者并不...在用 Vue 开发的这几年里,我学到了很多有用的技.
  • 得物(毒 app) 国际技术的内推来了,简历直呈 leader,加快面试流程,有反馈立即回复。...2.编写代码实现产品功能,完成项目开发,撰写相关文档,参与需求分析;3.负责技术问题的攻关、系统优化,协助...
  • web开发流程

    千次阅读 2021-03-02 18:36:58
    、需求分析阶段 在需求分析阶段,即上图所述 ”需求明确“之前的阶段 产品经理PM召集需要项目相关人员,开需求讨论会、讲解原型 相关人员需要以此了理解产品的需求,提出质疑:这是什么功能,怎么做,为啥这么做,大概...
  • Android AR开发实践之:AR介绍

    千次阅读 2021-01-15 11:06:18
    ARCore系统文章之------ AR介绍 、什么是AR 二、AR的发展历程 三、AR的应用场景 四、AR技术面临的主要问题 五、AR平台简介 、什么是AR AR(Augmented Reality增强现实的简称),也有对应VR虚拟实境词的翻译...
  • 浅谈软件开发的四大要素

    千次阅读 2021-11-04 18:49:21
    对于软件开发的过程,不可谓不熟悉,真的是爱恨交织,第次自己头铁当队长做服创,也没有学长学姐带着,没啥经验,就是乱搞,然后交接和收尾的时候,我真的是快哭了; 在做的时候,每次看要求,就又感觉不对,又...
  • 就目前国内的面试模式来讲,在面试前积极的准备面试,复习整个 Android 知识体系将变得非常重要,可以很负责任的说句,复习准备的是否充分,将直接影响你入职的成功。 但很多小伙伴却苦于没有合适的资料来回顾...
  • 滴滴开源轻量跨端开发框架:Hummer

    千次阅读 多人点赞 2021-01-07 21:09:28
    桔妹导读:Hummer 是滴滴普惠泛前端团队和滴滴R-Lab泛前端团队联合打造的超轻量级动态化跨端开发框架,目前已在滴滴内部多个业务线完成了大规模落地。本篇我们将从业务背景和技术优势对H...
  • 软件工程-软件开发

    千次阅读 2021-06-05 19:40:44
    、软件开发方法 结构化开发方法 用户至上,自顶向下,逐步分解(求解),严格区分工作阶段,每阶段有任务与成果,强调系统开发过程的整体性和全局性,系统开发过程工程化,文档资料标准化。 优点: 理论基础严密...
  • 安卓系统的开发

    千次阅读 2021-02-17 11:05:43
    、Android开发概述 1.1 Android简介 Android是由Google公司和开放手机联盟领导并开发种基于Linux的自由且开放源代码的操作系统,主要使用于移动设备。 其最初由Andy Rubin开发,后被Google于2005年8月收购。...
  • 从参加工作到现在,短短的几年内,我投资在自己身上的钱已超过三十多万,光买书籍的钱就已超过总投资的三分之,买了不少于上千本书,有实体书,也有电子书。这些书不仅提升了我的技术能力,更提升了我的视野和认知...
  • 、树莓派介绍 树莓派作为款物美价廉的微型电脑,被广发应用于物联网、开源电子和机器人等领域。它的官方组织是Raspberry Pi foundation,并被Broadcom公司支持。树莓派版本从2012年开始至今发展了很多代,最新的...
  • 很多时候,开发写了单元测试,但是我们并不知道当前的单元测试覆盖是怎么样的,所以我们需要有技术手段来分析我们的单元测试覆盖情况。那么,jacoco来了...jacoco介绍:jacoco 是个开源的覆盖工具。Jacoco ...
  • 文章目录)信息安全概述(了解即可,考察较少)1.1 信息与信息安全1.1.1信息1.1.2 信息技术1.1.3 信息安全1.1.4 信息系统安全1.2 信息安全威胁1.3 信息安全发展阶段与形式1.4 信息安全保障1.4.1 信息安全保障含义...
  • 2021-3-18 V1.0:是10家左右一线和二线互联网...你直接回答个确定的薪资,或薪资范围,其实就是把自己能谈薪资的机会给封死了。正确的回答应该是:先反问对方,公司的薪资结构是怎样的?其中,薪资结构包括:1.五险
  • IPD产品开发流程详解

    千次阅读 2021-02-25 09:49:22
    IPD的思想来源于美国PRTM公司出版的《产品及生命周期优化法书,该书中详细描述了这种新的产品开发模式所包含的各个方面。 最先将IPD付诸实践的是IBM公司,IBM公司实施IPD的效果不管在财务指标还是质量指标上得到...
  • 如果觉得一直从事PCBLayout太乏味,不如通过个硬件项目搞明白后去应聘硬件工程师,如果有完整的硬件项目经验,应聘硬件工程师成功还是非常高。 本次更新内容主要讲述如何通过基于Zynq7045芯片开发的板电源...
  • 近期,数睿数据、艾瑞咨询联合发布《2021年中国企业无代码开发白皮书》(以下简称《白皮书》)。《白皮书》从企业无代码的定义出发,深度洞察中国企业软件开发的困境与变革,通过典型厂商实践分析未来发展趋势。...
  • 文章目录、服务器的定义二、服务器的分类1.外形2.CPU指令集3.用途1.web服务器WEB简介协议WWW简介发展和特点服务器特点工作原理2.应用服务器定义分类静态动态概括区别应用服务器和WEB服务器的区别Web型应用程序型3....
  • 可以使用addToBackStack()方法将该事务对象添加到backStack 中,然后当用户按下回退的时候,直接返回的是上个fragment的状态 实例:开发兼顾屏幕分辨率的应用 为了实现这个目的可以在res/目录下为大屏幕,600dpi的...
  • 【判断题】由运放组成的任何应用电路都可以采用 ...初沉池对悬浮物的去除按50%计,则该厂初沉池每天产生含水为97%(污泥密度按1000kg/m2计)的泥量约为多少?( )【单选题】牙膏中常用作洁净剂的是【多选题】汽车保险...
  • 它适合高吞吐的场景,就是在某时间内写入大量的数据。 无法高效的对大量小文件进行存储 存储大量小文件的话,它会占用 NameNode大量的内存来存储文件、目录和块信息。这样是不可取的,因为NameNode的内存总是...
  • 它们各自有功能侧重,也有功能重叠,但是合在一起,就提供给STM32开发者,个无缝的开发平台。前面三个,STM32CubeMX,STM32CubeIDE、STM32CubeProgrammer,更加偏向开发的通用性。即,无论你的应用使用哪颗STM32...
  • 高级开发运维从简单学:Redis哨兵和集群小贴士

    千次阅读 热门讨论 2021-05-24 00:07:59
    一起学习了解高级开发运维知识,Redis的高可用、高并发、分布式,或许你跟我一样刚刚入门,那就看完本篇,应该有所收获,其实这篇总结的知识点不难,是最基础的Redis多机数据库下的哨兵sentinel架构和集群架构。
  • 2021Java开发工程师必备知识,Java后端主流知识学习系列()(有用的客官建议三连!) 初 前言 、Java基础 二、操作系统 三、计算机网络 四、数据结构 五、算法 六、数据库 七、热门框架技术 八、微服务分布式...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 307,041
精华内容 122,816
关键字:

一般一级开发的出地率