一或裂亏、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 = 0i<value.lengthi++ )
{
addData(value[i],name[i])
}
}
public Model(Data[] data)
{
for ( int i = 0i<data.lengthi++ )
{
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=0i {
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=0i<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=0j {
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=0i<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()
}
}
会用吗 ??
MVC (Model View Controller)本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。 模型-视图-控制器(MVC)是Xerox PARC在八十年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式,并且受到越来越多的使用 ColdFusion 和 PHP 的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。MVC是一个框架模式,它强制性的使应用程序的输谨毁入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自旦大处理自己的任务。
视图
视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和像XHTML,XML/XSL,WML等一些标识语言和Web services. 如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户 *** 纵的方式。
模型
模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用像EJBs和ColdFusion Components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后确定用哪个视图来显示模型处理返回的数据。 现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。编辑本段框架模式和设计模式的区别有很多程序员往往把框架模式和设计模式混淆,认为MVC是一种设计模式。实际上它们完全是不同的概念。[1] 框架、设计模式这两个概念总容易被混淆,其实它们之间还是有区别的。构件通常是代码重用,而设计模式是设计重用,框架则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。在软件生产中有三种级别的重用:内部重用,即在同一应用中能公共使用的抽象块代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。 框架与设计模式虽然相似,但却有着根本的不同。设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架祥迟备总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。 框架模式有哪些?MVC、MTV、MVP等等; 框架有哪些?C++语言的QT、MFC、gtk,Java语言的SSH,php语言的 smarty(MVC模式),python语言的django(MTV模式)等等 设计模式有哪些?工厂模式、适配器模式、策略模式等等 简而言之:框架模式是大智慧,用来对软件设计进行分工;设计模式是小技巧,对具体问题提出解决方案,以提高代码复用率、降低耦合度。编辑本段MVC框架模式的优点大部分Web应用程序都是用像ASP,PHP,或者CFML这样的过程化语言来创建的。它们将像数据库查询语句这样的数据层代码和像HTML这样的表示层代码混在一起。经验比较丰富的开发者会将数据从表示层分离开来,但这通常不是很容易做到的,它需要精心的计划和不断的尝试。MVC从根本上强制性的将它们分开。尽管构造MVC应用程序需要一些额外的工作,但是它给我们带来的好处是无庸质疑的。 首先,最重要的一点是多个视图能共享一个模型,正如我所提及的,现在需要用越来越多的方式来访问你的应用程序。对此,其中一个解决之道是使用MVC,无论你的用户想要Flash界面或是 WAP 界面;用一个模型就能处理它们。由于你已经将数据和业务规则从表示层分开,所以你可以最大化的重用你的代码了。 由于模型返回的数据没有进行格式化,所以同样的构件能被不同界面使用。例如,很多数据可能用HTML来表示,但是它们也有可能要用Macromedia Flash和WAP来表示。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。 因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变你的应用程序的数据层和业务规则。如果你想把你的数据库从MySQL移植到Oracle,或者改变你的基于RDBMS数据源到LDAP,只需改变你的模型即可。一旦你正确的实现了模型,不管你的数据来自数据库或是LDAP服务器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互对立,改变其中一个不会影响其它两个,所以依据这种设计思想你能构造良好的松耦合的构件。 对我来说,控制器的也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。编辑本段MVC框架模式的缺点MVC模式的缺点是由于它没有明确的定义,所以完全理解MVC模式并不是很容易。使用MVC模式需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。开发一个MVC模式架构的工程,将不得不花费相当可观的时间去考虑如何将MVC模式运用到应用程序中,同时由于模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。另外由于MVC模式将一个应用程序分成了三个部件,所以这意味着同一个工程将包含比以前更多的文件。 过去MVC模式并不适合小型甚至中等规模的应用程序,这样会带来额外的工作量,增加应用的复杂性。但现在多数软件设计框架,能直接快速提供MVC骨架,供中小型应用程序开发,此问题不再存在。对于开发存在大量用户界面,并且逻辑复杂的大型应用程序,JAVA将会使软件在健壮性、代码重用和结构方面上一个新的台阶。尽管在最初构建MVC模式框架时会花费一定的工作量,但从长远的角度来看,它会大大提高后期软件开发的效率
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)