【python3的进阶之路二】因特网客户端编程

一、文件传输

1.1 文件传输因特网协议

最流行的协议包括文件传输协议(FTP)、UNIX到UNIX复制协议(UUCP)、用于Web的超文本传输协议(HTTP)。另外,还有(UNIX下的)远程文件复制命令rcp(以及更安全、灵活的scp和rsync)。

HTTP主要用于基于Web的文件下载以及访问Web服务,一般客户端无须登录就可以访问服务器上的文件和服务。大部分HTTP文件传输请求都用于获取网页(即将网页文件下载到本地)。

而scp和rsync需要用户登录到服务器主机。在传输文件之前必须验证客户端的身份,否则不能上传或下载文件。FTP与scp/rsync相同,它也可以上传或下载文件,并采用了UNIX的多用户概念,用户需要输入有效的用户名和密码。但FTP也允许匿名登录。

1.2 文件传输协议

文件传输协议(File Transfer Protocol,FTP)主要用于匿名下载公共文件,也可以用于在两台计算机之间传输文件,特别实在使用Windows进行工作,而文件存储系统使用UNIX的情况下。

FTP要求输入用户名和密码才能访问远程FTP服务器,但也允许没有账号的用户匿名登录。不过管理员要先设置FTP服务器以允许匿名用户登录。这时,匿名用户的用户名是“anonymous”,密码一般是用户的电子邮件地址。与向特定的登录用户传输文件不通过,这相当于公开某些目录让大家访问。但与登录用户相比,匿名用户只能使用有限的几个FTP明令。

由上图展示的这个协议,其工作流程如下:

1、客户端连接远程主机上的FTP服务器

2、客户端输入用户名和密码(或“anonymous”和电子邮件地址)

3、客户端进行各种文件传输和信息查询操作

4、客户端从远程FTP服务器退出,结束传输

有时,由于网络两边计算机的崩溃或网络的问题,会导致整个传输在完成之前中断。如果客户端超过15分钟(900秒)还没有响应,FTP连接就会超时并中断。

在底层,FTP只使用TCP,而不是UDP。另外,可以将FTP看作客户端/服务器编程中的特殊情况。因为这里的客户端和服务器都使用俩个套接字来通信:一个是控制和命令端口(21号端口),另一个是数据端口(有时是20号端口)。

这里说的“有时”是因为FTP由俩种模式:主动和被动。只有主动模式下服务器才使用数据端口。在服务器把20号端口设置为数据端口后,它“主动”连接客户端的数据端口。而在被动模式下,服务器只是告诉客户端随机的数据端口号,客户端必须主动建立数据连接。在这种模式下,FTP服务器在建立数据连接时是“被动”的。最后,现在已经有了一种扩展的被动模式来支持第6版本的因特网协议(IPv6)地址——详见RFC 2428

1.3 Python和FTP

回顾流程:

1、连接到服务器

2、登录

3、发出服务请求(希望得到响应)

4、退出

在使用Python的FTP支持时,所需要做的只是导入ftplib模块,并实例化一个ftplib.FTP类对象。所有的FTP操作(如登录、传输文件和注销等)都要使用这个对象完成。

from ftplib import FTP

f = FTP(‘some.ftp.server‘)
f.login(‘anonymous‘, ‘[email protected]‘)
.
.
.
f.quit()

1.4 ftplib.FTP类的方法

方法 描述
login(self, user, password, acct) 登录到FTP服务器,所有参数都是可选的
pwd(self) 获取当前工作目录
cwd(self, dirname) 在服务器上设置当前目录
dir(self, args) 生成LIST命令返回的目录列表,将其打印到标准输出。可选参数是要列出的目录(默认为当前服务器目录)。可以使用多个参数将非标准选项传递给LIST命令。如果最后一个参数是一个函数,它将被用作回调函数retrlines(); 默认打印到 sys.stdout。此方法返回None。
nlst(self, args) 与dir()类似,但返回一个文件名列表,而不是显示这些文件名
retrlines(self, cmd, callback) 给定FTP命令(如“RETR filename”),用于下载文件。可选的回调函数cb用于处理文件的每一行
retribinary(self, cmd, fp, blocksize, callback, rest) 与retrlines类似,只是这个指令处理二进制文件。回调函数用于处理每一块(块大小默认8KB)
storlines(self, cmd, fp, callback) 给定FTP命令(如“STOR filename”),用来上传文本文件。要给定一个文件对象f
storbinary(self, cmd, fp, blocksize, callback, rest) 与storlines()类似,只是这个指令处理二进制文件。要给定一个文件对象f,上传块大小bs默认为8KB
rename(self, fromname, toname) 文件重命名
delete(self, filename) 删除名为dirname的远程文件。如果成功,则返回响应的文本,否则会引发error_perm权限错误或 error_reply其他错误。
mkd(self, dirname) 在服务器上创建一个新目录
rmd(self, dirname) 删除服务器上名为dirname的目录
quit(self) 关闭连接并退出
close(self) 单方面关闭连接

FTP对象更多信息:https://docs.python.org/3/library/ftplib.html

1.5 客户端FTP程序示例

import ftplib
import os
import socket

HOST = ‘ftp.sjtu.edu.cn‘   # 不可用ftp://ftp.sjtu.edu.cn/
DIRN = ‘logs/rsync‘
FILE = ‘fedora-epel.trace‘

def main():
    try:
        f = ftplib.FTP(HOST)
    except (socket.error, socket.gaierror) as e:
        print(‘ERROR:cannot reach %s‘ % HOST)
        return
    print(‘*** Connected to host %s‘ % HOST)

    try:
        f.login()
    except ftplib.error_perm:
        print(‘ERROR: cannot login anoymously‘)
        f.quit()
        return
    print("*** Logged in as ‘anonymous‘")

    try:
        f.cwd(DIRN)
    except ftplib.error_perm:
        print(‘ERROR: cannot CD to %s‘ % DIRN)
        f.quit()
        return
    print(‘*** Changed to %s folder‘ % f.pwd())

    try:
        f.retrbinary(‘RETR %s‘ % FILE, open(FILE, ‘r‘))
    except ftplib.error_perm:
        print(‘ERROR: cannot read file %s‘ % FILE)
        os.unlink(FILE)
    else:
        print(‘*** Downloaded %s to CWD‘ % FILE)
    f.quit()

if __name__ == ‘__main__‘:
    main()

说明:

第一到七行

代码前几行导入要用的模块(主要用于抓取异常对象),并设置一些常量

第九行到四十一行

创建一个FTP对象,尝试连接到FTP服务器(第十到十五行),然后返回。如果发生任何错误九退出。接着尝试用“anonymous”登录,如果不行九结束(第十七到二十三行)。下一步就是转到发布目录(第二十五到三十一行),最后下载文件(第三十三扫四十一行)。

在第三十四行,向retrbinary()传递一个回调函数,没接收到一块二进制数据的时候都会调用这个回调函数。这个函数就是船舰文件的本地版本时需要用到的文件对象的write()方法。传输结束时,python解释器会自动关闭这个文件对象,因此不会丢失数据。虽然方便,但要尽量做到在资源不再被使用的时候九立即释放,而不是依赖其他代码来完成释放操作。这里应该把开放的文件对象保存到一个变量(如变量loc),然后把loc.write传给ftp.retrbinary()。

完成传输后,调用loc.close()。如果由于某些原因无法保存文件,则移除空的文件夹来避免弄乱文件系统(第三十七行)。在os.unlink(FILE)俩侧添加一些错误检查代码,以应对文件不存在的情况。

第四十二到四十三行

运行独立脚本的惯用方法

1.6 FTP的其他内容

Python同时支持主动和被动模式。注意,在Python2.0及以前版本中,被动模式默认时关闭的;在Python2.1及以后版本中,默认时打开的。

以下是一些典型的FTP客户端类型:

  • 命令行客户端程序: 使用一些FTP客户端程序(如/bin/ftp或NcFTP)进行FTP传输,用户可以在命令中交互式执行FTP传输
  • GUI客户端程序: 与命令客户端程序相似,但它是一个GUI程序,如WS_FTP、Filezilla、CuteFTP、Fetch、SmartFTP
  • Web浏览器:
    除了使用HTTP之外,大多数Web浏览器(也称为客户端)可以进行FTP传输。URL/URI的第一部分就用来表示所使用的协议,如“http://blahblah”。这就告诉浏览器要使用HTTP作为指定网站传输数据的协议。通过修改协议部分,就可以发送使用FTP的请求,如“ftp://blahblah”,这与使用HTTP的网页URL很像(“blahblah”可以展开为“host/path?attributes”)。如果要登录,用户可以把登录信息(以明文方式)放在URL里,如“ftp://user:[email protected]/path?attr1=vall&attr2=val2…”
  • 自定义应用程序: 自己编写的用于FTP文件传输的程序。这些式用于特殊目的的应用程序,一般这种程序不允许用户与服务器交互

二、网络新闻

2.1 Usenet与新闻组

Usenet新闻系统式一个全球存档的“电子公告板”。各个主题的新闻组一应俱全,新闻组可以面向全球,也可以只面向某个特定区域。老的Usenet使用UUCP作为其网络传输机制,在20世纪80年代中期出现了另一个网络协议TCP/IP,之后大部分网络流量转向使用TCP/IP。

2.2 网络新闻传输协议

作为客户端/服务器架构的另一个例子,NNTP与FTP的操作方式相似,但更简单。FTP中,登录、传输数据和控制需要使用不同的端口,而NNTP只使用一个标准端口119来通信。用户向服务器发送一个请求,服务器就做出相应的响应。

2.3 Python和NNTP

NNTP协议流程:

1、连接到服务器

2、登录(根据需要)

3、发出服务请求

4、退出

from nntplib import NNTP

n = NNTP(‘your.nntp.server‘)
r,c,f,l,g = n.group(‘comp.lang.python‘)
.
n.quit()

登录后需要调用group()方法来选择一个感兴趣的新闻组。该方法返回服务器的回复、文章的数量、第一篇和最后一篇文章的ID、新闻组的名称。

2.4 nntplib.NNTP类方法

方法 描述
group(self, name) 选择一个组的名字,返回一个元组(rsp,ct,fst,lst,group),分别表示服务器响应信息、文章数量、第一个和最后一个文章的编号、组名,所有数据都是字符串。(返回的group与传进去的name应该式相同的)
xhdr(self, hdr, str, file) 发送XHDR命令。该命令没有在RFC中定义,但是是一个常见的扩展。的报头参数是一个报头的关键字,例如‘subject‘。该字符串参数应具有的形式‘first-last‘,其中第一和最后一个是第一个和最后的文章编号,以搜索。返回一对(response, list),其中list是对的列表(id, text),其中id是商品编号(作为字符串),text是该文章请求的标题的文本。如果提供了文件参数,则XHDR命令的输出将存储在文件中。如果文件是一个字符串,然后该方法将打开一个名称为文件对象,写入并关闭它。如果file是一个文件对象,那么它将开始调用write()它来存储命令输出的行。如果提供了文件,则返回的列表是一个空列表。
body(self,message_spec, file) 发送一个BODY命令,其中id的含义与以前相同stat()。如果提供了文件参数,则主体存储在文件中。如果file是一个字符串,那么该方法将打开一个具有该名称的文件对象,写入并关闭它。如果文件是一个文件对象,那么它将开始调用write()它来存储正文的行。返回head()。如果提供了文件,则返回的列表是一个空列表。
head(self,message_spec, file) 发送一个HEAD命令,其中id的含义与以前相同stat()。返回一个元组(response, number, id, list),其中前三个元素与for相同stat(),list是文章标题列表(一个没有解释的行列表,没有尾随换行符)。
article(self,message_spec, file) 发送一个ARTICLE命令,其中id的含义与以前相同stat()。返回head()。
stat(self,message_spec) 发送一个STAT命令,其中id是消息ID(用‘<‘and 括起来‘>‘)或商品编号(作为字符串)。返回一个triple (response, number, id),其中number是商品编号(作为字符串),id是消息ID(用‘<‘和括起来‘>‘)。
next(self) 把文章指针移到下一篇文章,返回与stat()相似的元组
last(self) 把文章指针移到最后一篇文章,返回与stat()相似的元组
post(self,data) 使用该POST命令发布文章。的文件参数是其使用其读直至EOF一个打开的文件对象readline()的方法。它应该是一篇格式良好的新闻文章,包括必需的标题。该post()方法自动转义以.。开头的行。
quit(self) 关闭连接并退出

2.5 客户端程序NNTP示例

import nntplib
import socket

HOST = ‘your.nntp.server‘
GRNM = ‘comp.lang.python‘
USER = ‘wesley‘
PASS = ‘youllNeverGuess‘

def main():
    try:
        n = nntplib.NNTP(HOST)
        #, user = USER, password = PASS)
    except socket.gaierror as e:
        print(‘ERROR: cannot reach host %s‘ % HOST)
        print(‘%s‘ % eval(str(e))[1])
        return
    except nntplib.NNTPermanentError as e:
        print(‘ERROR:access denied on %s‘ % HOST)
        print(‘%s‘ % str(e))
        return
    print(‘*** Connected to host %s‘ % HOST)

    try:
        rsp, ct, fst, lst, grp = n.group(GRNM)
    except nntplib.NNTPTemporaryError as ee:
        print(‘ERROR: cannot load group %s‘ % GRNM)
        print(‘%s‘ % str(e))
        print(‘Server may require authentication‘)
        print(‘Uncomment/edit login line above‘)
        n.quit()
        return
    except nntplib.NNTPTemporaryError as ee:
        print(‘ERROR: group %s unavailable‘ % GRNM)
        print(‘%s‘ % str(e))
        n.quit()
        return
    print(‘*** Found newsgroup %s‘ % GRNM)

    rng = ‘%s-%s‘ % (lst, lst)
    rsp, frm = n.xhdr(‘from‘, rng)
    rsp, sub = n.xhdr(‘subject‘,rng)
    rsp, dat = n.xhdr(‘date‘, rng)
    print(‘‘‘*** Found last article (#%s)
    From:%s
    Subject:%s
    Date:%s
    ‘‘‘ % (lst, frm[0][1], sub[0][1], dat[0][1]))

    rsp, anum, mid, data = n.body(lst)
    displayFirst20(data)
    n.quit()

def displayFirst20(data):
    print(‘*** First (<=20) meaningful lines:\n‘)
    count = 0
    lines = (line.rstrip() for line in data)
    lastBlank = True
    for line in lines:
        if line:
            lower = line.lower()
            if(lower.startswith(‘>‘) and not             lower.startswith(‘>>>‘)) or             lower.startswith(‘|‘) or             lower.startswith(‘in article‘) or             lower.endswith(‘writes:‘) or             lower.endswith(‘wrote:‘):
                continue
        if not lastBlank or (lastBlank and line):
            print(‘%s‘ % line)
            if line:
                count += 1
                lastBlank = False
            else:
                lastBlank = True
        if count == 20:
            break

if __name__ == ‘__main__‘:
    main()

说明:

第九行到三十七行:

尝试连接NNTP主机服务器,如果失败就退出。接着尝试读取指定的新闻组。同样,如果新闻组不存在,或服务器没有保存这个新闻组,或需要身份验证,就退出

第三十九到五十一行:

这一部分读取并显示一些头消息(第三十九到第四十七行)。程序会读取作者、主题、日期这些数据并显示给用户。每次调用xhdr()方法时,都要给定想要提取消息头的文章的范围。因为这里只想获取一条消息,所以范围就是“X-X”,其中X是最新一条消息的号码。xhdr()方法返回一个长度为2的元组,其中包含了服务器的响应(rsp)和指定范围的消息头的列表。

最后一部分是下载文章的内容(第四十九到五十一行)。先调用body()方法,然后至多显示前20个有意义的行,最后从服务器注销,完成处理。

第五十三到七十六行:

该函数接受文章的一些内容,并做一些预处理,如把计数器清0,创建一个生成器表达式对文章内容的所有行做一些处理,然后“假装”刚碰到并显示了一行空行(第五十五到五十七行)。

由于不想显示引用的文本和引用文本指示行,而在第六十到六十七使用了一个大if语句。只有在当前行不是空行时,才做这个检查。检查的时候,会把字符串转成小写,这样就能做到比较的时候不区分大小写。

第六十八行的if语句表示只有在上一行不为空,或者上一行为空但当前不为空的时候才显示。

三、电子邮件

3.1 电子邮件电子组件和协议

电子邮件系统的重要组件是消息传输代理(MTA).这是在邮件交换主机上运行的服务进程,它负责邮件的路由、队列处理和发送工作。MTA就是邮件从发送主机到接收主机所要经过的主机和“跳板”,也称为“消息传输”的“代理”。MTA要知道的俩件事:

1、如何找到消息应该到达的下一个MTA

2、如何与另一台MTA通信

3.2 Python和SMTP

需要一个smtplib模块和一个需要实例化的smtplib.SMTP类。流程:

1、连接到服务器

2、登录(根据需要)

3、发出服务请求

4、退出

from smtplib import SMTP

n = SMTP(‘smtp.yourdomain.com‘)
.
.
.
n.quit()

3.4 smtplib.SMTP类方法

方法 描述
sendmail(self, from_addr, to_addr, msg, mail_options, rcpt_options) 将msg从from_addr发送至to_addr,还可以选择性地设置ESMTP邮件(mail_options)和收件人(rcpt_options)选项
ehlo(self, name)或helo(self, name) 使用ehlo指令像ESMTP(SMTP扩展)确认你的身份/使用helo指令向SMTP服务器确认你的身份
starttls(self, keyfile, certfile, context) 让服务器启用TLS模式。如果给定了keyfile或certfile,则它们用来创建安全套接字
set_debuglevel(self,debuglevel) 为服务器通信设置调试级别
quit(self) 关闭连接并退出
login(self, user, password, initial_response_ok) 使用用户名和密码登录SMTP服务器

3.5 Python和POP3

需要一个poplib模块和一个需要实例化的poplib.POP3类。流程:

1、连接到服务器

2、登录(根据需要)

3、发出服务请求

4、退出

from poplib import POP3

p = POP3(‘pop.python.is.cool‘)
p.user(...)
p.pass_(...)
...
p.quit()

3.6 poplib.POP3类方法

方法 描述
user(self, user) 向服务器发送登录名,并显示服务器的响应,表示服务器正在等待输入该用户的密码
pass_(self, pswd) 在用户使用user()登录后,发送password。如果登录失败,则抛出异常
stat(self) 返回邮件的状态,即一个长度为2的元组,分别表示消息的数量和消息的总大小
list(self, which) stat()的扩展,从服务器返回以三元组表示的整个消息列表,分别表示为服务器的响应、消息列表、返回消息的大小。
retr(self, which) 从服务器中得到消息的邮件,并设置其“已读”标志。返回一个长度为3的元组,分别为服务器的响应、消息的邮件的所有行、消息的字节数
dele(self, which) 将标记的消息删除,大多数服务器在调用quit()后执行删除操作
quit(self) 注销、提交修改(如处理“已读”和“删除”标记等)、解锁邮箱、终止连接,然后退出

3.7 客户端程序SMTP和POP3示例

from smtplib import SMTP
from poplib import POP3
from time import sleep
from email.parser import Parser
from email.mime.text import MIMEText

SMTPSVR = ‘smtp.exmail.qq.com‘   # SMTP服务器
POPSVR = ‘pop.exmail.qq.com‘     # POP服务器
mail_user = "username"  # 用户名
mail_pass = "password"  # 密码

sender = ‘sender mail‘       # 发件人邮箱
receivers = [‘receiver mail‘]    # 接收人邮箱

content = ‘Hello World!‘
title = ‘test msg‘  # 邮件主题
message = MIMEText(content, ‘plain‘, ‘utf-8‘)  # 内容, 格式, 编码
message[‘From‘] = "{}".format(sender)
message[‘To‘] = ",".join(receivers)
message[‘Subject‘] = title

sendSvr = SMTP(SMTPSVR)
sendSvr.login(mail_user, mail_pass)
errs = sendSvr.sendmail(sender, receivers, message.as_string()) # 发送邮件,sendmail()的第三个参数是电子邮件消息本身
sendSvr.quit()
assert len(errs) == 0, errs
sleep(10)

recvSvr = POP3(POPSVR)
recvSvr.user(mail_user)
recvSvr.pass_(mail_pass)
rsp, msg, siz = recvSvr.retr(recvSvr.stat()[0])  # stat()方法得到可用消息列表,通过[0]符号选中第一条消息;retr()下载这条消息
msg_content = b‘\r\n‘.join(msg).decode(‘utf-8‘)
recvBody = Parser().parsestr(msg_content)

3.8 Python和IMAP4

from imaplib import IMAP4

s = IMAP4(‘imap.python.is.cool‘)
s.login(...)
...
s.close()
s.logout()

3.9 imaplib.IMAP4类的常用方法

方法 描述
close(self) 关闭当前邮箱。如果访问权限不是只读,则本地删除大的邮件在服务器端也会被丢弃
login(self, user, password) 使用指定的用户名和密码登录
logout(self) 从服务器注销
fetch(self, message_set, message_parts) 获取之前由message_set设置的电子邮件消息状态(或使用message_parts获取部分状态信息)
noop(self) ping服务器,但不产生任行为
search(self, charset, *criteria) 查询邮箱中至少匹配一块criteria的消息。如果charset为False,则默认使用US-ASCII
select(self, mailbox, readonly) 选择一个文件夹(默认是INBOX),如果是只读,则不允许用户修改其中的内容

原文地址:https://www.cnblogs.com/CSgarcia/p/9883011.html

时间: 2024-10-10 15:51:53

【python3的进阶之路二】因特网客户端编程的相关文章

【python3的学习之路二】数据类型和变量

整数 python可以处理任意大小的整数(包括负整数),如100,0,-8080等. 浮点数 浮点数也就是小数,如1.23,-9.01等.但对于很大或很小的浮点数,就必须用科学计数法表示,把10用e代替,1.23*109就是1.23e9,0.000012可以写成1.2e-5. 字符串 字符串是以单引号或双引号括起来的任意文本.如果字符串内部既包含'又包含"怎么办?可以用转义字符\来标识,如果你不想让反斜杠发生转义,可以在字符串前面添加一个 r,表示原始字符串. print('I\'m \&quo

JavaScript进阶之路(二)——变量与基本数据类型

前言 JavaScript中的变量为松散类型,所谓松散类型就是指当一个变量被申明出来就可以保存任意类型的值,就是不像SQL一样申明某个键值为int就只能保存整型数值,申明varchar只能保存字符串.一个变量所保存值的类型也可以改变,这在JavaScript中是完全有效的,只是不推荐.相比较于将变量理解为“盒子“,<JavaScript编程精解>中提到应该将变量理解为“触手”,它不保存值,而是抓取值.这一点在当变量保存引用类型值时更加明显. JavaScript中变量可能包含两种不同的数据类型

【python3的学习之路九】函数式编程

变量作用域 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python的作用域一共有4种,分别是: L (Local) 局部作用域 E (Enclosing) 闭包函数外的函数中 G (Global) 全局作用域 B (Built-in) 内建作用域 以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找. x = int(2.9) # 内建作用域 g_count = 0 # 全局作用域 de

【SSH进阶之路】Hiberante3搭建开发环境+简单实例(二)

Hibernate是非常典型的持久层框架,持久化的思想是非常值得我们学习和研究的.这篇博文,我们主要以实例的形式学习Hibernate,不深究Hibernate的思想和原理,否则,一味追求,苦学思想和原理,到最后可能什么也学不会,从实践入手,熟能生巧,思想和原理自然而然领悟. 上篇博文:[SSH进阶之路]Hibernate基本原理,我们介绍了Hibernate的基本概念.Hibernate的核心以及Hibernate的执行原理,可以很好帮助我们认识Hibernate,再看这篇博客之前,请先回顾上

【SSH进阶之路】Spring的IOC逐层深入——为什么要使用IOC[实例讲解](二)

上篇博客[SSH进阶之路]Spring简介,搭建Spring环境--轻量级容器框架(一),我们简单的介绍了Spring的基本概念,并且搭建了两个版本的Spring开发环境,但是我们剩下了Spring最核心的两大技术:IoC和AOP,没有深入介绍.从这篇博文开始,我们开始一一的深入学习Spring的两个核心.Spring目前最引人注目的地方,就是IOC=Inversion  Of Control(控制反转)或者DI=Dependence  Injection(依赖注入)的设计思想. 这篇博客我们使

【SSH进阶之路】深入源码,详解Struts基本实现流程

通过一步步的封装我们实现了Struts的基本雏形,我们解决了Struts怎么实现MVC的问题,我们现在仅仅有了Struts的基础,对Struts的学习才刚刚开始,这篇我们要通过对比MVC来理解Struts的执行流程,最后深入Struts的源码,一看究竟. MVC M:业务逻辑,业务数据可以重复使用,我们经常说的javabean(其实struts没有实现业务层,也无法实现) V:显示逻辑,同一份数据,对应多中显示方法,JSP代码实现 C:控制流程器,Servlet代码实现. 我们通过时序图看一下M

【SSH进阶之路】Hibernate基本映射(三)

[SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心,采用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例(二),小编搭建了基本Hibernate的开发环境,并做了一个简单实例,对它的基本原理有了一个理性的认识. 这篇博客小编介绍Hibernate的经典内容:对象关系映射.主要介绍映射的基本概念,映射的分类,映射文件. 概念 ORM(Object Relational Mapping),即对象关系映射.

【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)

目录: [SSH进阶之路]Struts基本原理 + 实现简单登录(二) [SSH进阶之路]一步步重构MVC实现Struts框架--从一个简单MVC开始(三) [SSH进阶之路]一步步重构MVC实现Struts框架--封装业务逻辑和跳转路径(四) [SSH进阶之路]一步步重构MVC实现Struts框架--彻底去掉逻辑判断(五) [SSH进阶之路]一步步重构MVC实现Struts框架--完善转向页面,大功告成(六) 上篇[SSH进阶之路]Struts基本原理 + 实现简单登录(二),我们介绍MVC和

【SSH进阶之路】Spring的AOP逐层深入——采用注解完成AOP(七)

上篇博文[SSH进阶之路]Spring的AOP逐层深入--AOP的基本原理(六),我们介绍了AOP的基本原理,以及5种通知的类型, AOP的两种配置方式:XML配置和Aspectj注解方式. 这篇我们使用注解方式来实现一个AOP,我们先看一下项目的目录. 我们采用的是JDK代理,所以首先将接口和实现类代码附上: package com.tgb.spring; public interface UserManager { public void addUser(String userName,St