简介
MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:
·Model(模型)表示应用程序核心(比如数据库记录列表)。
·View(视图)显示数据(数据库记录)。
·Controller(控制器)处理输入(写入数据库记录)。
MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。
通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。
MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。
框架内容
MVC指MVC模式的某种框架,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。
视图
视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Adobe Flash和像XHTML,XML/XSL,WML等一些标识语言和Web services.
MVC好处是它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
模型
模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用像EJBs和ColdFusion Components这样的构件对象来处理数据库,被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求,所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
区别
框架和设计模式的区别
有很多往往把框架模式和设计模式混淆,认为MVC是一种设计模式。实际上它们完全是不同的概念。
框架、设计模式这两个概念总容易被混淆,其实它们之间还是有区别的。框架通常是代码重用,而设计模式是设计重用,架构则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。在软件生产中有三种级别的重用:内部重用,即在同一应用中能公共使用的抽象块;代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。
框架与设计模式虽然相似,但却有着根本的不同。设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。
框架模式有哪些?
MVC、MTV、MVP、CBD、ORM等等;
框架有哪些?
C++语言的QT、MFC、gtk,Java语言的SSH 、SSI,php语言的 smarty(MVC模式),python语言的django(MTV模式)等等
设计模式有哪些?
工厂模式、适配器模式、策略模式等等
简而言之:框架是大智慧,用来对软件设计进行分工;设计模式是小技巧,对具体问题提出解决方案,以提高代码复用率,降低耦合度。
常见框架
Struts
Struts是Apache软件基金下Jakarta项目的一部分。Struts框架的主要架构设计和开发者是Craig R.McClanahan。Struts 是Java Web MVC框架中不争的王者。经过长达九年的发展,Struts已经逐渐成长为一个稳定、成熟的框架,并且占有了MVC框架中最大的市场份额。但是Struts某些技术特性上已经落后于新兴的MVC框架。面对Spring MVC、Webwork2这些设计更精密,扩展性更强的框架,Struts受到了前所未有的挑战。但站在产品开发的角度而言,Struts仍然是最稳妥的选择。
Struts有一组相互协作的类(组件)、Servlet以及jsp tag lib组成。基于struts构架的web应用程序基本上符合JSP Model2的设计标准,可以说是MVC设计模式的一种变化类型。根据上面对framework的描述,很容易理解为什么说Struts是一个web framework,而不仅仅是一些标记库的组合。但 Struts 也包含了丰富的标记库和独立于该框架工作的实用程序类。Struts有其自己的控制器(Controller),同时整合了其他的一些技术去实现模型层(Model)和视图层(View)。在模型层,Struts可以很容易的与数据访问技术相结合,包括EJB,JDBC和Object Relation Bridge。在视图层,Struts能够与JSP, Velocity Templates,XSL等等这些表示层组件相结合。
Spring
Spring实际上是Expert One-on-One J2EE Design and Development 一书中所阐述的设计思想的具体实现。在One-on-One 一书中,Rod Johnson倡导J2EE实用主义的设计思想,并随书提供了一个初步的开发框架实现(interface21 开发包)。而Spring 正是这一思想的更全面和具体的体现。Rod Johnson 在interface21 开发包的基础之上,进行了进一步的改造和扩充,使其发展为一个更加开放、清晰、全面、高效的开发框架。
Spring是一个开源框架,由Rod Johnson创建并且在他的著作《J2EE设计开发编程指南》里进行了描述。它是为了解决企业应用开发的复杂性而创建的。Spring使使用基本的JavaBeans来完成以前只可能由EJB完成的事情变得可能了。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
简单来说,Spring是一个轻量的控制反转和面向切面的容
框架。当然,这个描述有点过于简单。但它的确概括出了Spring是做什么的。
ZF
Zend Framework(简写ZF)是由 Zend 公司支持开发的完全基于 PHP5 的开源PHP开发框架,可用于开发 Web 程序和服务,ZF采用 MVC(Model–View-Controller) 架构模式来分离应用程序中不同的部分方便程序的开发和维护。
.NET
.NET MVC 是微软官方提供的以MVC模式为基础的 .NET Web应用程序(Web Application)框架,它由Castle的MonoRail而来(Castle的MonoRail是由java而来),目前最新版本是.N 4.5。
MVC特点
耦合性低
重用性高
生命周期成本低
部署快
可维护性高
有利软件工程化管理
缺点
没有明确的定义
不适合小型,中等规模的应用程序
增加系统结构和实现的复杂性
视图与控制器间的过于紧密的连接
视图对模型数据的低效率访问
一般高级的界面工具或构造器不支持模式
上传下载代码(hfs做服务器)
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下载"
android:id="@+id/download_btn"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/download_ProgressBar"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上传"
android:id="@+id/upload_btn"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/upload_ProgressBar"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="断点续传开始"
android:id="@+id/breakpoint_resume_start"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="断点续传暂停"
android:id="@+id/breakpoint_resume_stop"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/breakpoint_resume_ProgressBar"/>
</LinearLayout>
Activity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button download,upload,breakpoint_resume_start,breakpoint_resume_stop;
ProgressBar download_ProgressBar,upload_ProgressBar,breakpoint_resume_ProgressBar;
FileNetModel fileNetModel = new FileNetModel();
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == Constant.DOWNLOAD_MAX){
download_ProgressBar.setMax((Integer) msg.obj);
}else if (msg.what == Constant.DOWNLOAD_CURRENT){
download_ProgressBar.setProgress(download_ProgressBar.getProgress()+(Integer)msg.obj);
}else if (msg.what == Constant.DOWNLOAD_FINISH){
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}else if (msg.what == Constant.UPLOAD_MAX){
upload_ProgressBar.setMax((Integer) msg.obj);
}else if (msg.what == Constant.UPLOAD_CURRENT){
upload_ProgressBar.setProgress(upload_ProgressBar.getProgress()+(Integer) msg.obj);
}else if (msg.what == Constant.UPLOAD_FINISH){
Toast.makeText(MainActivity.this, "上传成功", Toast.LENGTH_SHORT).show();
}else if (msg.what == Constant.BREAKPOINT_RESUME_MAX){
breakpoint_resume_ProgressBar.setMax((Integer) msg.obj);
}else if (msg.what == Constant.BREAKPOINT_RESUME_CURRENT){
breakpoint_resume_ProgressBar.setProgress((Integer) msg.obj);
}else if (msg.what == Constant.BREAKPOINT_RESUME_FINISH){
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initComponent();
}
private void initComponent() {
download = findViewById(R.id.download_btn);
upload = findViewById(R.id.upload_btn);
breakpoint_resume_start = findViewById(R.id.breakpoint_resume_start);
breakpoint_resume_stop = findViewById(R.id.breakpoint_resume_stop);
download_ProgressBar = findViewById(R.id.download_ProgressBar);
upload_ProgressBar = findViewById(R.id.upload_ProgressBar);
breakpoint_resume_ProgressBar = findViewById(R.id.breakpoint_resume_ProgressBar);
download.setOnClickListener(this);
upload.setOnClickListener(this);
breakpoint_resume_start.setOnClickListener(this);
breakpoint_resume_stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.download_btn:
fileNetModel.download("http://10.211.55.4/hfs_demo/i.png","/sdcard/Pictures/ninga.png",handler);
break;
case R.id.upload_btn:
fileNetModel.upload("http://10.211.55.4/hfs_demo/","/sdcard/Movies/刀郎 - 西海情歌.mp4",handler);
break;
case R.id.breakpoint_resume_start:
fileNetModel.breakpoint_resume("http://uvideo.spriteapp.cn/video/2019/0512/56488d0a-7465-11e9-b91b-1866daeb0df1_wpd.mp4","/sdcard/Movies/duandian.mp4",handler);
fileNetModel.handler.sendEmptyMessage(Constant.start);
break;
case R.id.breakpoint_resume_stop:
fileNetModel.handler.sendEmptyMessage(Constant.end);
break;
}
}
}
Thread 包
常量
public class Constant {
public static final int DOWNLOAD_MAX = 1001;
public static final int DOWNLOAD_CURRENT = 1002;
public static final int DOWNLOAD_FINISH = 1003;
public static final int UPLOAD_MAX = 2001;
public static final int UPLOAD_CURRENT = 2002;
public static final int UPLOAD_FINISH = 2003;
public static final int BREAKPOINT_RESUME_MAX = 3001;
public static final int BREAKPOINT_RESUME_CURRENT = 3002;
public static final int BREAKPOINT_RESUME_FINISH = 3003;
public static final int start = 101;
public static final int end = 102;
}
线程
下载
public class DownloadThread extends Thread {
private String strUrl;
private String path;
private Handler handler;
public DownloadThread(String strUrl, String path, Handler handler) {
this.strUrl = strUrl;
this.path = path;
this.handler = handler;
}
@Override
public void run() {
super.run();
InputStream inputStream = null;
FileOutputStream fos = null;
try {
URL url = new URL(strUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(5000);
connection.setConnectTimeout(5000);
if (connection.getResponseCode() == 200){
inputStream = connection.getInputStream();
Message obtain = Message.obtain();
obtain.what = Constant.DOWNLOAD_MAX;
obtain.obj = connection.getContentLength();
handler.sendMessage(obtain);
fos = new FileOutputStream(path);
byte[] b = new byte[1024*8];
int len = 0;
while ((len = inputStream.read(b)) != -1){
fos.write(b,0,len);
Message obtain1 = Message.obtain();
obtain1.what = Constant.DOWNLOAD_CURRENT;
obtain1.obj = len;
handler.sendMessage(obtain1);
}
handler.sendEmptyMessage(Constant.DOWNLOAD_FINISH);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (inputStream != null){
inputStream.close();
}
if (fos != null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
上传
public class UploadThread extends Thread {
private String strUrl;
private String path;
private Handler handler;
public UploadThread(String strUrl, String path, Handler handler) {
this.strUrl = strUrl;
this.path = path;
this.handler = handler;
}
/**
* 上传文件:post请求
* 1.设置请求头信息:
* Content-Length:请求体的长度
* Content-Type:multipart/form-data; boundary=7e324741816d4
* 2.请求体:2部分
* 第一部分:要有换行
* -----------------------------7e324741816d4
* Content-Disposition: form-data; name="file"; filename="上传到服务器的名字"
* Content-Type: media/mp4或者media/mp3或者image/jpeg或者image/png
* 空行
*/
@Override
public void run() {
super.run();
OutputStream outputStream = null;
FileInputStream fis = null;
try {
File file = new File(path);
String fileName = URLEncoder.encode(file.getName());
StringBuffer sb = new StringBuffer();
sb.append("-----------------------------8xp45657"+"\r\n");
sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""+fileName+"\""+"\r\n");
sb.append("Content-Type: media/mp4"+"\r\n");
sb.append("\r\n");
byte[] bytes = sb.toString().getBytes("UTF-8");
Message obtain = Message.obtain();
obtain.what = Constant.UPLOAD_MAX;
obtain.obj = (int)file.length()+bytes.length;
handler.sendMessage(obtain);
URL url = new URL(strUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length",bytes.length+file.length()+"");
connection.setRequestProperty("Content-Type","multipart/form-data; boundary="+"8xp45657");
connection.setDoOutput(true);
outputStream = connection.getOutputStream();
fis = new FileInputStream(path);
byte[] b = new byte[1024*8];
int len = 0;
outputStream.write(bytes);
Message obtain2 = Message.obtain();
obtain2.what = Constant.UPLOAD_CURRENT;
obtain2.obj = bytes.length;
handler.sendMessage(obtain2);
while ((len = fis.read(b)) != -1){
outputStream.write(b,0,len);
Message obtain1 = Message.obtain();
obtain1.what = Constant.UPLOAD_CURRENT;
obtain1.obj = len;
handler.sendMessage(obtain1);
}
if (connection.getResponseCode() == 200){
handler.sendEmptyMessage(Constant.UPLOAD_FINISH);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (outputStream != null){
outputStream.close();
}
if (fis != null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
断点续传
public class Breakpoint_Resume extends Thread {
private String strUrl;
private String path;
private Handler handler;
private int start;
private int end;
private int max;
public Breakpoint_Resume(String strUrl, String path, Handler handler) {
this.strUrl = strUrl;
this.path = path;
this.handler = handler;
}
@Override
public void run() {
super.run();
InputStream inputStream = null;
RandomAccessFile randomAccessFile = null;
try {
URL url = new URL(strUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
Message obtain = Message.obtain();
max = connection.getContentLength();
obtain.what = Constant.BREAKPOINT_RESUME_MAX;
obtain.obj = max;
handler.sendMessage(obtain);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
File file = new File(path);
if(file.exists()){
start= (int) file.length();
}
end = max;
URL url = new URL(strUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestProperty("Range","bytes="+start+"-"+end);
if (connection.getResponseCode() == 206){
inputStream = connection.getInputStream();
randomAccessFile = new RandomAccessFile(path, "rw");
randomAccessFile.seek(start);
byte[] b=new byte[1024];
int len=0;
int count=start;
while ((len = inputStream.read(b)) != -1){
randomAccessFile.write(b,0,len);
Message obtain = Message.obtain();
obtain.what = Constant.BREAKPOINT_RESUME_CURRENT;
count+=len;
obtain.obj = count;
handler.sendMessage(obtain);
synchronized (StringBuffer.class){
if(FileNetModel.flag){
StringBuffer.class.wait();
}
}
}
handler.sendEmptyMessage(Constant.BREAKPOINT_RESUME_FINISH);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null){
inputStream.close();
}
if (randomAccessFile != null){
randomAccessFile.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Model 包
接口
public interface FileNetInterface {
void download(String strUrl, String path, Handler handler);
void upload(String strUrl, String path, Handler handler);
void breakpoint_resume(String strUrl, String path, Handler handler);
}
具体实现
public class FileNetModel implements FileNetInterface {
Breakpoint_Resume breakpoint_resume;
public static boolean flag = false;
int flag2;
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == Constant.start){
if (flag2==0){
breakpoint_resume.start();
flag2++;
}else {
flag=false;
synchronized (StringBuffer.class){
StringBuffer.class.notify();
}
}
}else if (msg.what == Constant.end){
flag = true;
}
}
};
@Override
public void download(String strUrl, String path, Handler handler) {
new DownloadThread(strUrl, path, handler).start();
}
@Override
public void upload(String strUrl, String path, Handler handler) {
new UploadThread(strUrl, path, handler).start();
}
@Override
public void breakpoint_resume(String strUrl, String path, Handler handler) {
breakpoint_resume = new Breakpoint_Resume(strUrl, path, handler);
}
}