‘壹’ 如何学习MVC
最早开始接触MVC的时候是因为学struts,那时候不懂,开始看了N本的有关MVC的书籍读完了两本关于struts的书,对spring,hibnerate也有了初步的了解,也可以写出一些小的struts程序了,MVC的概念也非常熟悉,感觉很良好,以为对mvc有了很深入的认识了呢,后来用cakephp(MVC)写一个商业的东西,才发现自己居然对MVC一点不了解,以前掌握的实在是有限后来就一直是边写程序边学习了,这才使得我对MVC有了更深入的理解 对待这些新技术学着去做那才是正确的,书在某些层面会限制了人的进步速度,但是我不是说不看书,有许多书都是经典之作,书中总结了很多前人的经验,书要看但是只能看好书下面来说说MVC的概念:[转的] MVC模式是"Model-View-Controller"的缩写,中文翻译为"模式-视图-控制器"。MVC应用程序总是由这三个部分组成。 Event(事件)导致Controller改变Model或View,或者同时改变两者。只要Controller改变了Models的数据或者属性,所有依赖的View都会自动更新。类似的,只要Controller改变了View,View会从潜在的Model中获取数据来刷新自己。MVC模式最早是smalltalk语言研究团提出的,应用于用户交互应用程序中。smalltalk语言和java语言有很多相似性,都是面向对象语言,很自然的 SUN在petstore(宠物店)事例应用程序中就推荐MVC模式作为开发Web应用的架构模式。MVC模式是一种架构模式,其实需要其他模式协作完成。在J2EE模式目录中,通常采用service to worker模式实现,而service to worker模式可由集中控制器模式,派遣器模式和Page Helper模式组成。而Struts只实现了MVC的View和Controller两个部分,Model部分需要开发者自己来实现,Struts提供了抽象类Action使开发者能将Model应用于Struts框架中。 MVC模式是一个复杂的架构模式,其实现也显得非常复杂。但是,我们已经终结出了很多可靠的设计模式,多种设计模式结合在一起,使MVC模式的实现变得相对简单易行。Views可以看作一棵树,显然可以用Composite Pattern来实现。Views和Models之间的关系可以用Observer Pattern体现。Controller控制Views的显示,可以用Strategy Pattern实现。Model通常是一个调停者,可采用Mediator Pattern来实现。MVC简介设计思想 MVC英文即Model-View-Controller,即把一个应用的输入、处理、输出流程按照Model、View、Controller的方式进行分离,这样一个应用被分成三个层——模型层、视图层、控制层。 视图(View)代表用户交互界面,对于Web应用来说,可以概括为HTML界面,但有可能为XHTML、XML和Applet。随着应用的复杂性和规模性,界面的处理也变得具有挑战性。一个应用可能有很多不同的视图,MVC设计模式对于视图的处理仅限于视图上数据的采集和处理,以及用户的请求,而不包括在视图上的业务流程的处理。业务流程的处理交予模型(Model)处理。比如一个订单的视图只接受来自模型的数据并显示给用户,以及将用户界面的输入数据和请求传递给控制和模型。 模型(Model):就是业务流程/状态的处理以及业务规则的制定。业务流程的处理过程对其它层来说是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的核心。目前流行的EJB模型就是一个典型的应用例子,它从应用技术实现的角度对模型做了进一步的划分,以便充分利用现有的组件,但它不能作为应用设计模型的框架。它仅仅告诉你按这种模型设计就可以利用某些技术组件,从而减少了技术上的困难。对一个开发者来说,就可以专注于业务模型的设计。MVC设计模式告诉我们,把应用的模型按一定的规则抽取出来,抽取的层次很重要,这也是判断开发人员是否优秀的设计依据。抽象与具体不能隔得太远,也不能太近。MVC并没有提供模型的设计方法,而只告诉你应该组织管理这些模型,以便于模型的重构和提高重用性。我们可以用对象编程来做比喻,MVC定义了一个顶级类,告诉它的子类你只能做这些,但没法限制你能做这些。这点对编程的开发人员非常重要。 业务模型还有一个很重要的模型那就是数据模型。数据模型主要指实体对象的数据 保存(持续化)。比如将一张订单保存到数据库,从数据库获取订单。我们可以将这个模型单独列出,所有有关数据库的操作只限制在该模型中。 控制(Controller)可以理解为从用户接收请求, 将模型与视图匹配在一起,共同完成用户的请求。划分控制层的作用也很明显,它清楚地告诉你,它就是一个分发器,选择什么样的模型,选择什么样的视图,可以完成什么样的用户请求。控制层并不做任何的数据处理。例如,用户点击一个连接,控制层接受请求后, 并不处理业务信息,它只把用户的信息传递给模型,告诉模型做什么,选择符合要求的视图返回给用户。因此,一个模型可能对应多个视图,一个视图可能对应多个模型。
‘贰’ 西方经济学中厂商要素的使用选择一种是w=vmp=mp*p,还有一种是mfc=mr*mp,怎么...
MFC定义是边际要素成本
W是劳动的价格 完全竞争市场下 W=MFC
和MR=MC的道理一样,厂商出于利润最大化的目的会使最后增加使用的那单位生产要素所带来的收益等于为使用他所支付的成本,既MRP=MFC
其实通过数学方法可以推导出W=VMP=MFC=MRP (完全竞争市场条件下) 他们与需求曲线重合 是一条线
‘叁’ TP AP MP,TC AC MC,TFC TVC,AVC AFC,MFC MVC,STC SAC SMC,LTC LAC SMC在西方经济学中分别代表些
一、T-total总的;A-average平均;M-margin边际;P-proction产量;C-cost成本;F-fixed固定;V-variable可变;S-short短期;L-long长期;
TP为总产量,AP为平均产量,MP为边际产量;TC表示总成本,AC表示平均成本,MC表示边际成本;TFC表示总固定成本,TVC表示总可变成本;AVC表示平均可变成本,AFC表示平均固定成本;MFC表示边际固定成本,MVC表示边际可变成本;STC为短期总成本,SAC为短期平均成本,SMC为短期边际成本;LTC为长期总成本,LAC表示长期平均成本,LMC为长期边际成本
二、涉及短期成本、短期产量的一部分知识:
1、短期成本曲线:
(1)各短期成本曲线的形状不变成本TFC曲线是一条水平线。它表示在短期内无论产量如何变化,总不变成本是固定的。可变成本TVC曲线是一条由原点出发的向右上方倾斜的曲线。在一定的产量水平上,总可变成本TVC存在着一个拐点(C点)。在拐点之前,TVC曲线的斜率是递减的,在拐点之后,TVC曲线的斜率是递增的。这一特征来源于边际报酬递减规律。总成本TC曲线是一条由水平的TFC曲线与纵轴的交点出发的向右上方倾斜的曲线。在每一个产量点上,不仅TC曲线的斜率和TVC曲线的斜率相等,而且,TC曲线和TVC曲线之间的垂直距离都等于固定的总不变成本TFC。平均不变成本AFC曲线是一条向两轴渐近的双曲线,它表示平均不变成本随产量的增加而减少。平均可变成本AVC曲线、平均总成本AC曲线和边际成本MC曲线都呈U形,即它们都表现出随着产量的增加而先降后升的特征。他们的这一特征也来源于边际报酬递减规律。边际报酬递减规律是说在其他条件不变的情况下,随着一种可变要素投入量的连续增加,它所带来的边际产量先是递增的,达到最大值后再递减。从成本的角度来看,当产量由零开始不断增加时,起初由于可变要素投入量相对于不变要素投入量是较少的,增加可变要素的投入量会提高生产率,这样边际成本是递减的。但当可变要素投入量增加到最佳的比例以后再继续增加可变要素的投入量,生产效率会降低,这样边际成本是递增的。这说明短期生产函数和短期成本函数之间存在着某种对应关系。边际报酬的递增阶段对应的是边际成本的递减阶段,边际报酬的递减阶段对应的是边际成本的递增阶段,与边际报酬的极大值相对应的是边际成本的极小值
2、各成本之间的关系:
短期成本曲线相互之间的关系利用边际报酬递减规律所决定的MC曲线的U形特征可以得到短期成本曲线的一些关系:①TC曲线、TVC曲线和MC曲线之间的关系。由于每一产量点上的TC曲线和TVC曲线的斜率是相等的,所以,每一产量点上的MC值就是相应的TC曲线和TVC曲线的斜率。边际报酬递减规律的作用下,当MC曲线逐渐地由下降变为上升时,相应地,TC曲线和TVC曲线的斜率也由递减变为递增。当MC曲线在A点达极小值时,TC曲线和TVC曲线相应地各自存在一个拐点B和C。②AC曲线、AVC曲线和MC曲线之间的关系。先分析AC曲线和MC曲线之间的关系。U形的AC曲线与U形的MC曲线相交于AC曲线的最低点D。在AC曲线的下降阶段,即在D点以前,MC曲线在AC曲线的下方,在AC曲线的上升阶段,即在D点以后,MC曲线在AC曲线的上方。之所以有这个特征其原因在于:对于任何两个相应的边际量和平均量而言,只要边际量小于平均量,边际量就把平均量拉下,只要边际量大于平均量,边际量就把平均量拉上,所以当边际量等于平均量时,平均量必然达到其本身的极值点。还有一个重要的特点就是:不管是下降还是上升,MC曲线的变动都快于AC曲线的变动。这是因为对于产量变化的反应来说,边际成本MC要比平均成本AC敏感得多,因此不管是减少还是增加,MC曲线的变动都快于AC曲线的变动。再分析AVC曲线和MC曲线的关系。U形AVC曲线与U形的MC曲线相交于AVC曲线的最低点F。在AVC曲线的下降阶段,即在F点以前,MC曲线在AVC曲线之下,在AVC曲线的上升阶段,即在F点以后,MC曲线在AVC曲线之上。而且,不管是下降还是上升,MC曲线的变动都快于AVC曲线的变动。
‘肆’ 经济学中MU怎么求Mrs是什么怎么求
MU是边际效用,对TU(Q)求Q的导数,含义是多一单位商品所能得到的效用。
MRS是边际替代率。公式:MRSxy= - △y/△x=MUx/MUy=px/py
MRS是消费者,无差异曲线的斜率,MRT是生产者,投入不变时,无差异曲线的斜率,MRTS是生产者,生产要素的替代率。
MRS:MRS12=-△X2/△X1。
MRTS:MRTSLK=-dK/dL。MRS=MRT
MRTS:当等产量曲线的斜率为负值时,表明两种生产要素可以互相替代,一种生产要素增加,另一种生产要素必须减少方能使产量维持在同一个水平上。只有具有负斜率的等产量曲线,才表示这两种要素的替换时有效率的。
无差异
MRS递减的无差异曲线形状如图3—45所示。MRS递减,无差异曲线凸向原点。MRS递减是因为X和Y之间存在一定替代关系,但又不能完全替代,当X增多,Y减少时,MUX递减,而MUY递增,因而要用越来越多的X替代Y,即MRSXY递减。
这时无差异曲线之所以凸向原点,是因为MRS是无差异曲线上每一点的斜率。例如,在图3—45中,无差异曲线上a,b,c点的斜率,分别是递减,即b点上斜率小于a点上斜率,c点上斜率小于b点上斜率。
以上内容参考:网络-边际替代率
‘伍’ MVC的使用方法!
javaMVC模式是将servlet和jsp结合起来的技术。servlet适合数据处理,而jsp适合显示。这个模式充分发挥了每项技术的优点。
一、MVC 需求
如果需要大量的数据处理servlet很合适,但是servlet对html的处理很冗长难以修改,这就是使用jsp的原因。将视图从复杂的数据和逻辑处理中解放出来。
但是当jsp显示内容需要根据不同的需求生成差异较大的页面的时候我们就需要将jsp显示和servlet的逻辑处理结合起来。通常使用的模式是MVC模式。可以
使每项技术发挥它最大的功效。初始请求由servlet来处理,调用逻辑和数据处理代码,并穿件bean来表示响应的结果(即模型)。然后servlet确定由哪个jsp页面显示比较合适并将请求转发到jsp(即视图)。servlet就是控制器。
使用MVC的目的就是将逻辑操作和数据操作和显示代码分离。在相对较复杂的项目中使用框架是更好的更方便的选择。(Apache struts2)。但是相对于使用框架来说
从头开始自己创建MVC的实现(使用RequestDispatcher请求转发)更直观更灵活。
二、使用RequestDispatcher来手动创建MVC。
1.定义bean来表示数据
2.使用servlet来处理请求
3.填写bean
4.将bean存储到请求,会话或者servletcontext中
5.将请求转发给jsp
这里要说的是当一个请求转发的时候是将HttpServletRequest对象转发到jsp页面,而重定向(sendRedirect)是重新创建一个请求。(这里要注意的是如果jsp页面的显示只有在servlet上下文中才有意义的话可以讲页面放在WEB-INF目录中,因为这个目录用户是不能直接访问的,但是服务器可以访问)
如果是将bean存储在会话或者servletcontext 中时有的情况下使用重定向要比请求转发更有效
6.从bean中读取数据并显示
读取的时候jsp页面是使用的jsp:useBean标签及子标签来显示的,但是需要注意的是在这不能重新创建bean使用的标签应该这样:
<jsp:useBean ... type="package.class" />来代替创建新bean 的<jsp:useBean ... class="package.class" />
还有一点要注意的是jsp页面不能用来设置bean只能读取即<jsp:getProperty />标签。还要注意读取bean是基于那种共享(Request,session,application)
三、目的页面中相对URL的解释
使用RequestDispatcher来转发请求时最终URL是最初的servlet请求维持最初的请求不变,使用sendRedirect重定向的时候是重新创建请求并且URL是最终显示页面的URL
还有一个需要注意的是如果jsp页面使用图像和导入js或者css的时候,RequestDispatcher的相对路径应该是相对于初始servlet的相对路径,而sendRedirect 的文件相对路径是相对于最终请求的页面的相对路径
四、三种数据共享方式的对比
当数据在每个请求不同的时候使用请求共享,
当数据在会话的时候不变的情况下使用会话共享,
如果在整个程序运行的状态下数据都不需要重新定义的话使用应用程序共享。
五、在jsp中使用转发
在jsp中使用转发的方式可以是<jsp:forward page="relative URL">和scriptlet中,但是使用xml标签显然要比封装到RequestDispatcher中要方便许多,还有一个原因是效率要高。jsp:forward标签可以使用jsp:param作为子标签,为转到的页面提供额外的参数。在servlet中的后台实现就是RequestDispatcher类的forward方法。
六、包含页面
使用jsp转发是利用servlet产生数据用jsp输出servlet不产生输出。还有一种方法是使用页面包含,可以讲servlet自身的输出及一个或多个jsp页面的输出组合到一起。RequestDispatcher的include方法就是jsp标签<jsp:include>的后台实现。如:
import javax.servlet.*;
//doSomething
RequestDispatcher rd=request.getRequestDispatcher("jsp路径");
rd.include(当前servlet的Request对象,当前servlet的response对象);
//doSomething
这端代码就是jsp:include的实现方法只包含页面的输出内容而不是如<%@ include%>命令那样讲整个文件的内容包含进去。
七、EL表达式
EL(表达式语言)是为了计算和输出存储在标准位置的java对象的值。另一个特性是用jsp语法(而非Java语法)定义定制标签的能力。
优点:1.精确访问存储对象。输出用setAttribute存储的对象。
2.bean属性的简略记法。使用bean(name).attribute(name)访问bean属性。
3.对集合元素的简单访问。使用${variable[index or key]}
4.请求参数、cookie和其他请求数据的简单访问。
5.实现一些简单的运算。
6.选择性输出。(${test?option1:option2})
7.自动类型转换。
8.空值取代错误消息。
停用EL表达式
1.停用整个WEB应用中的表达式语言。
修改web.xml文件的兼容版本
2.停用多个jsp页面中的表达式语言。
修改web.xml文件,在其中添加如下标签:
<jsp-property-group>
<url-pattern>jsp Path</url-pattern>
<el-ignored>true or false</el-ignored>
</jsp-property-group>
true为停用false为启用
3.停用个别页面中的表达式语言。
在需要停用EL表达式的页面加入如下语句:
<%@ page ignored="false"%>
true为启用false为停用
4.停用表达式语言的个别语句。
将$符号用$替换,这个表达式就失效了
需要注意的是在jsp2.0的jsp页面上如果想要输出${}这个符号需要使用转意字符\${}表示这个和将$用$是一样的效果
下面是一个例子
package mvcTest2;
public class Data
{
public int value; // 学生年龄值
public String name; // 学生名
}
import java.util.*;
import java.util.Observable;
public class Model extends Observable
{
protected ArrayList data = new ArrayList();
public Model()
{
super();
}
public Model(int[] value, String[] name)
{
for ( int i = 0; i< value.length; i++ )
{
addData(value[i],name[i]);
}
}
public Model(Data[] data)
{
for ( int i = 0; i< data.length; i++ )
{
addData(data[i]);
}
}
public void addData(int value, String name)
{
Data data = new Data();
data.value = value;
data.name = name;
this.data.add(data);
setChanged(); // Indicates that the model has changed
notifyObservers(this);
}
public void addData(Data data)
{
this.data.add(data);
setChanged(); // Indicates that the model has changed
notifyObservers(this);
}
public Data getData(int idx)
{
return (Data)(data.get(idx));
}
public int size()
{
return data.size();
}
// 当数据改变时,由Controller调用此方法,通知各个Observer,刷新视图.
public void changeModel(Model model)
{
data.clear();
for (int i=0; i {
this.addData(model.getData(i));
}
setChanged(); // Indicates that the model has changed
notifyObservers(this);
}
}
import java.awt.*;
import javax.swing.*;
//import javax.swing.border.*;
import java.awt.event.*;
public class Controller extends JFrame
{
Model model = new Model();
TextView txtView = new TextView(model);
GraphicsView graphView = new GraphicsView(model);
JScrollPane jScrollPane1 = new JScrollPane();
JButton jButton1 = new JButton();
JTextField jTextField1 = new JTextField();
JTextField jTextField2 = new JTextField();
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
public Controller()
{
try
{
super.setTitle("MVC parrten test");
jbInit();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
Data[] data = new Data[4];
data[0] = new Data();
data[1] = new Data();
data[2] = new Data();
data[3] = new Data();
data[0].name = "Ted";
data[0].value = 20;
data[1].name = "Joy";
data[1].value = 14;
data[2].name = "Mars";
data[2].value = 23;
data[3].name = "Martian";
data[3].value = 25;
model.addData(data[0]);
model.addData(data[1]);
model.addData(data[2]);
model.addData(data[3]);
// 注意下面两行:向模型中登记它的观察者View1和View2.
model.addObserver(txtView);
model.addObserver(graphView);
this.getContentPane().setLayout(null);
jScrollPane1.setBounds(new Rectangle(0, 0, 3, 3));
jButton1.setBounds(new Rectangle(309, 259, 101, 27));
jButton1.setText("Update");
jButton1.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jButton1_actionPerformed(e);
}
});
jTextField1.setText("20");
jTextField1.setBounds(new Rectangle(80, 254, 52, 30));
jTextField2.setText("14");
jTextField2.setBounds(new Rectangle(178, 255, 50, 31));
jLabel1.setText("Age:");
jLabel1.setBounds(new Rectangle(41, 226, 47, 23));
jLabel2.setText("Ted");
jLabel2.setBounds(new Rectangle(42, 252, 35, 33));
jLabel3.setText("Joy");
jLabel3.setBounds(new Rectangle(144, 255, 31, 31));
txtView.setBounds(new Rectangle(7, 5, 225, 208));
graphView.setBounds(new Rectangle(234, 4, 219, 209));
this.getContentPane().add(jScrollPane1, null);
this.getContentPane().add(jTextField2, null);
this.getContentPane().add(jTextField1, null);
this.getContentPane().add(jLabel2, null);
this.getContentPane().add(jLabel3, null);
this.getContentPane().add(jLabel1, null);
this.getContentPane().add(jButton1, null);
this.getContentPane().add(txtView, null);
this.getContentPane().add(graphView, null);
}
// 按下Update按钮,通知Model数据发生改变.
void jButton1_actionPerformed(ActionEvent e)
{
Data[] data = new Data[2];
data[0] = new Data();
data[1] = new Data();
data[0].name = jLabel2.getText();
data[0].value = Integer.parseInt(jTextField1.getText());
data[1].name = jLabel3.getText();
data[1].value = Integer.parseInt(jTextField2.getText());
Model m = new Model(data);
this.model.changeModel(m);
}
public static void main(String[] args)
{
Controller c = new Controller();
c.setSize(475, 350);
c.setVisible(true);
}
}
package mvcTest2;
import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import java.util.Observer;
import java.util.Observable;
public class GraphicsView extends JPanel implements Observer
{
Model model;
public GraphicsView()
{
}
public GraphicsView(Model model)
{
try
{
this.model = model;
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
this.setBackground(Color.white);
this.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.black,1),"GraphicsView"));
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if ( model == null ) return;
int x = 10,y = 30;
int h = g.getFontMetrics().getHeight();
int width = this.getWidth();
int height = this.getHeight();
int sy = height / (model.size() +1);
int sx = width/ 2 -40;
for ( int i=0; i< model.size(); i++ )
{
Data data = model.getData(i);
int value = data.value;
int dx = 3;
int r = 3;
Color c = new Color((int)(255*Math.random()),(int)(255*Math.random()),(int)(255*Math.random()));
int cx = sx;
int cy = y+i * sy;
for ( int j=0;j {
g.setColor(c);
g.drawOval(cx,cy,r,r);
r+=dx;
}
//*/
g.draw3DRect( cx,cy,value*2,15,true);
g.setColor(c);
g.fill3DRect(cx,cy,value*2,15,true );
g.drawString(data.name,25,cy+15);
}
}
// 当模型数据发生改变时,会自动调用此方法来刷新图形
public void update(Observable o, Object arg)
{
this.model =(Model) o;
repaint();
}
package mvcTest2;
import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import java.util.Observer;
import java.util.Observable;
public class TextView extends JPanel implements Observer
{
Model model;
public TextView()
{
}
public TextView(Model model)
{
try
{
this.model = model;
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
this.setBackground(Color.white);
this.setBorder(new TitledBorder(BorderFactory.createLineBorder(Color.black,1),"TextView"));
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if ( model == null ) return;
int x = 20,y = 50;
int h = g.getFontMetrics().getHeight();
for ( int i=0; i< model.size(); i++ )
{
Data data = model.getData(i);
g.drawString(data.name + ":",x,y);
x+= g.getFontMetrics().stringWidth(data.name) + 20;
g.drawString(String.valueOf(data.value),x,y);
y+=h;
x = 20;
}
}
// 当模型数据发生改变时,会自动调用此方法来刷新图形
public void update(Observable o, Object arg)
{
this.model =(Model) o;
repaint();
}
}
会用吗 ??