You are on page 1of 39

Java SE Application Design With MVC

By Robert Eckstein, March 2007

Articles Index Contents - What Is Model-View-Controller (MVC)? - Interaction Between MVC Components - Modifying the MVC Design - Using the Modified MVC - Issues With Application Design - Common Swing Component Listeners - Conclusion - For More Information What Is Model-View-Controller (MVC)? If you've programmed with graphical user interface (GUI) libraries in the past 10 years or so, you have likely come across the model-view-controller (MVC) design. MVC was first introduced by Trygve Reenskaug, a Smalltalk developer at the Xerox Palo Alto Research Center in 1979, and helps to decouple data access and business logic from the manner in which it is displayed to the user. More precisely, MVC can be broken down into three elements: Model - The model represents data and the rules that govern access to and updates of this data. In enterprise software, a model often serves as a software approximation of a real-world process. View - The view renders the contents of a model. It specifies exactly how the model data should be presented. If the model data changes, the view must update its presentation as needed. This can be achieved by using a push model, in which the view registers itself with the model for change notifications, or a pull model, in which the view is responsible for calling the model when it needs to retrieve the most current data. Controller - The controller translates the user's interactions with the view into actions that the model will perform. In a stand-alone GUI client, user interactions could be button clicks or menu selections, whereas in an enterprise web

application, they appear as GET and POST HTTP requests. Depending on the context, a controller may also select a new view -- for example, a web page of results -- to present back to the user. Sun BluePrints Catalog

Figure1. A Common MVC Implementation Interaction Between MVC Components This section will take a closer look at one way to implement Figure 1 in the context of an application in the Java Platform, Standard Edition 6 (Java SE 6). Once the model, view, and controller objects are instantiated, the following occurs: 1. The view registers as a listener on the model. Any changes to the underlying data of the model immediately result in a broadcast change notification, which the view receives. This is an example of the push model described earlier. Note that the model is not aware of the view or the controller -- it simply broadcasts change notifications to all interested listeners.

2. The controller is bound to the view. This typically means that any user actions that are performed on the view will invoke a registered listener method in the controller class. 3. The controller is given a reference to the underlying model. Once a user interacts with the view, the following actions occur: 1. The view recognizes that a GUI action -- for example, pushing a button or dragging a scroll bar -- has occurred, using a listener method that is registered to be called when such an action occurs. 2. The view calls the appropriate method on the controller. 3. The controller accesses the model, possibly updating it in a way appropriate to the user's action.

If the model has been altered, it notifies interested listeners, such as the view, of the change. In some architectures, the controller may also be responsible for updating the view. This is common in Java technology-based enterprise applications. Figure 2 shows this interaction in more detail.

Figure 2. A Java SE Application Using MVC As this article mentioned earlier, the model does not carry a reference to the view but instead uses an event-notification model to notify interested parties of a change. One of the consequences of this powerful design is that the many views can have the same underlying model. When a change in the data model occurs, each view is notified by a property change event and can update itself accordingly. For example, Figure 3 shows two views that use the same data model.

Figure 3. Multiple Views Using the Same Model Modifying the MVC Design A more recent implementation of the MVC design places the controller between the model and the view. This design, which is common in the Apple Cocoa framework, is shown in Figure 4.

Figure 4. An MVC Design Placing the Controller Between the Model and the View The primary difference between this design and the more traditional version of MVC is that the notifications of state changes in model objects are communicated to the view through the controller. Hence, the controller mediates the flow of data between model and view objects in both directions. View objects, as always, use the controller to translate user actions into property updates on the model. In addition, changes in model state are communicated to view objects through an application's controller objects. Thus, when all three components are instantiated, the view and the model will both register with the controller. Once a user interacts with the view, the events are nearly identical: 1. The view recognizes that a GUI action -- for example, pushing a button or dragging a scroll bar -- has occurred, using a listener method that is registered to be called when such an action occurs. 2. The view calls the appropriate method on the controller.

3. The controller accesses the model, possibly updating it in a way appropriate to the user's action. 4. If the model has been altered, it notifies interested listeners of the change. However, in this case, the change is sent to the controller. Why adopt this design? Using this modified MVC helps to more completely decouple the model from the view. In this case, the controller can dictate the model properties that it expects to find in one or more models registered with the controller. In addition, it can also provide the methods that effect the model's property changes for one or more views that are registered with it. Using the Modified MVC This section of the article shows you how to put this design into practice, starting with the model. Suppose that you want to paint some text using a simple display model with five properties. Code Sample 1 shows a simple component that you can use to create such a model. Code Sample 1 public class TextElementModel extends AbstractModel { private String text; private Font font; private Integer x; private Integer y; private Integer opacity; private Integer rotation; /** * Provides the means to set or reset the model to * a default state */ public void initDefault() { setOpacity(89); setRotation(0); setText("Sample Text"); setFont(new Font("Arial", Font.BOLD, 24)); setX(50);

setY(50); } // Accessors public String getText() { return text; } public void setText(String text) { String oldText = this.text; this.text = text; firePropertyChange( DefaultController.ELEMENT_TEXT_PROPERTY, oldText, text); } public Font getFont() { return font; } public void setFont(Font font) { Font oldFont = this.font; this.font = font; firePropertyChange( DefaultController.ELEMENT_FONT_PROPERTY, oldFont, font); } // The remaining accessors for properties are omitted. }

Note that the rest of the accessors follow the standard JavaBeans model, although they are omitted in Code Sample 1. For reference, Code Sample 2 shows the underlying AbstractModel class, which simply uses the javax.beans.PropertyChangeSupport class to register, deregister, and notify interested listeners of changes to the model. Code Sample 2 public abstract class AbstractModel { protected PropertyChangeSupport propertyChangeSupport; public AbstractModel() { propertyChangeSupport = new PropertyChangeSupport(this); } public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.removePropertyChangeListener(listener); } protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); } } The Controller Between the model and view lies the controller. First, take a look at the code for the abstract controller superclass, as shown in Code Sample 3. Code Sample 3 public abstract class AbstractController implements PropertyChangeListener {

private ArrayList<abstractviewpanel> registeredViews; private ArrayList<abstractmodel> registeredModels; public AbstractController() { registeredViews = new ArrayList<abstractviewpanel>(); registeredModels = new ArrayList<abstractmodel>(); } public void addModel(AbstractModel model) { registeredModels.add(model); model.addPropertyChangeListener(this); } public void removeModel(AbstractModel model) { registeredModels.remove(model); model.removePropertyChangeListener(this); } public void addView(AbstractViewPanel view) { registeredViews.add(view); } public void removeView(AbstractViewPanel view) { registeredViews.remove(view); } // Use this to observe property changes from registered models // and propagate them on to all the views. public void propertyChange(PropertyChangeEvent evt) { for (AbstractViewPanel view: registeredViews) { view.modelPropertyChange(evt); } } /**

* This is a convenience method that subclasses can call upon * to fire property changes back to the models. This method * uses reflection to inspect each of the model classes * to determine whether it is the owner of the property * in question. If it isn't, a NoSuchMethodException is thrown, * which the method ignores. * * @param propertyName = The name of the property. * @param newValue = An object that represents the new value * of the property. */ protected void setModelProperty(String propertyName, Object newValue) { for (AbstractModel model: registeredModels) { try { Method method = model.getClass(). getMethod("set"+propertyName, new Class[] { newValue.getClass() } ); method.invoke(model, newValue); } catch (Exception ex) { // Handle exception. } } } } The AbstractController class contains two ArrayList objects, which are used to keep track of the models and views that are registered. Note that whenever a model is registered, the controller also registers itself as a property change listener on the model. This way, whenever a model changes its state, the propertyChange() method is called and the controller will pass this event on to the appropriate views.

The final method, setModelProperty(), employs some magic to get its work done. In order to keep the models completely decoupled from the controller, the code samples in this article have employed the Java Reflection API. In this case, when this method is called with the desired property name, you hunt through the registered models to determine which one contains the appropriate method. Once you find it, you invoke the method using the new value. If the method is not called, thegetMethod() will throw a NoSuchMethodException, which the exception handler ignores, allowing the for- loop to continue. Code Sample 4 shows the source code for the default controller class. This class consists of only property constants and methods called by the GUI event listeners of the view. Code Sample 4 public class DefaultController extends AbstractController { public static final String ELEMENT_TEXT_PROPERTY = "Text"; public static final String ELEMENT_FONT_PROPERTY = "Font"; public static final String ELEMENT_X_PROPERTY = "X"; public static final String ELEMENT_Y_PROPERTY = "Y"; public static final String ELEMENT_OPACITY_PROPERTY = "Opacity"; public static final String ELEMENT_ROTATION_PROPERTY = "Rotation"; // Code omitted public void changeElementText(String newText) { setModelProperty(ELEMENT_TEXT_PROPERTY, newText); } public void changeElementFont(Font newFont) { setModelProperty(ELEMENT_FONT_PROPERTY, newFont); } public void changeElementXPosition(int newX) { setModelProperty(ELEMENT_X_PROPERTY, newX); } public void changeElementYPosition(int newY) { setModelProperty(ELEMENT_Y_PROPERTY, newY); }

public void changeElementOpacity(int newOpacity) { setModelProperty(ELEMENT_OPACITY_PROPERTY, newOpacity); } public void changeElementRotation(int newRotation) { setModelProperty(ELEMENT_ROTATION_PROPERTY, newRotation); } } The View This example will have two views displaying the data from the model: a propertyeditor view and a graphical page view. Both of these are implementations of a JPanel, inserted into either a JDialogor JFrame. The dialog box allows the user to update the values of the model, and the frame panel simply reflects the changes as the final textual display. The author of this article built this example using the NetBeans Swing GUI Builder, formerly referred to as Project Matisse, to design the GUI forms. Code Sample 5 shows the source code for the property-editor view, the more interesting of the two. The first section is simply devoted to initialization of the components, which for the most part was automatically generated by the NetBeans integrated development environment (IDE) in theinitComponents() method. All of this section is omitted but is present in the downloadable code. Any other initialization that you need to perform -- in this case, creating custom models for JSpinnerand JSlider objects or adding DocumentListeners to the JTextField components -- is handled in the localInitialization() method. Code Sample 5 public PropertiesViewPanel(DefaultController controller) { this.controller = controller; initComponents(); localInitialization(); } // editor-fold defaultstate="collapsed" desc=" Local Initialization " /**

* Used to provide local initialization of Swing components * outside of the NetBeans automatic code generator */ public void localInitialization() { opacitySpinner.setModel(new SpinnerNumberModel(100, 0, 100, 1)); opacitySlider.setModel(new DefaultBoundedRangeModel(100, 0, 0, 100)); rotationSpinner.setModel(new SpinnerNumberModel(0, -180, 180, 1)); rotationSlider.setModel(new DefaultBoundedRangeModel(0, 0, -180, 180)); text.getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { textDocumentChanged(e); } public void removeUpdate(DocumentEvent e) { textDocumentChanged(e); } public void changedUpdate(DocumentEvent e) { textDocumentChanged(e); } }); } // /editor-fold Note that the automatically generated NetBeans IDE code folds in the source code so that the developer can collapse each of these sections when it is not needed: // editor-fold defaultstate="collapsed" desc=" Local Initialization " // /editor-fold If you're using the NetBeans IDE, this practice is highly recommended.

The second section of the PropertiesViewPanel class deals exclusively with the model. In Code Sample 6, a modelPropertyChange() method is called by the controller whenever the model reports a state change. Code Sample 6 // editor-fold defaultstate="collapsed" desc=" Model Event Handling Code " public void modelPropertyChange(final PropertyChangeEvent evt) { if (evt.getPropertyName().equals( DefaultController.ELEMENT_X_PROPERTY)) { String newStringValue = evt.getNewValue().toString(); xPositionTextField.setText(newStringValue); } else if (evt.getPropertyName().equals( DefaultController.ELEMENT_Y_PROPERTY)) { String newStringValue = evt.getNewValue().toString(); yPositionTextField.setText(newStringValue); } else if (evt.getPropertyName().equals( DefaultController.ELEMENT_OPACITY_PROPERTY)) { int newIntegerValue = (Integer)evt.getNewValue(); opacitySpinner.setValue(newIntegerValue); opacitySlider.setValue(newIntegerValue); } else if (evt.getPropertyName().equals( DefaultController.ELEMENT_ROTATION_PROPERTY)) { int newIntegerValue = (Integer)evt.getNewValue(); rotationSpinner.setValue(newIntegerValue); rotationSlider.setValue(newIntegerValue); } else if (evt.getPropertyName().equals( DefaultController.ELEMENT_TEXT_PROPERTY)) { String newStringValue = evt.getNewValue().toString(); text.setText(newStringValue); } else if (evt.getPropertyName().equals( DefaultController.ELEMENT_FONT_PROPERTY)) { Font f = (Font)evt.getNewValue(); String fontString = f.getFontName() + " " + f.getSize(); font.setText(fontString); currentFont = f;

} // Remainder of the code omitted } // /editor-fold Again, this code sample omits portions of the code that are similar to the sections shown. The final portion consists of the GUI event listeners. Code Sample 7 contains listeners that are called whenever GUI events occur, such as pushing the Change Font button or the Opacityspinner buttons, or resetting the text in any of the text fields. These are largely event listeners that most Swing developers are already familiar with. If you're using the NetBeans IDE, you'll see that the IDE can automatically generate many of these using the GUI developer. Code Sample 7 // editor-fold defaultstate="collapsed" desc=" GUI Event Handling Code " // Code omitted private void yPositionTextFieldFocusLost(java.awt.event.FocusEvent evt) { try { controller.changeElementYPosition( Integer.parseInt(yPositionTextField.getText())); } catch (Exception e) { // Handle exception. } } private void yPositionTextFieldActionPerformed(java.awt.event.ActionEvent evt) { try { controller.changeElementYPosition( Integer.parseInt(yPositionTextField.getText())); } catch (Exception e) { // Handle exception. } }

// Code omitted -- code for xPosition // is nearly the same as for yPosition. private void changeFontButtonActionPerformed(java.awt.event.ActionEvent evt) { JFontChooserDialog fontChooser = new JFontChooserDialog((Dialog)this.getTopLevelAncestor()); fontChooser.setSelectedFont(currentFont); fontChooser.setVisible(true); Font returnedFont = fontChooser.getSelectedFont(); if (returnedFont != null) { controller.changeElementFont(returnedFont); } } private void opacitySliderStateChanged(javax.swing.event.ChangeEvent evt) { controller.changeElementOpacity((int)opacitySlider.getValue()); } private void rotationSliderStateChanged(javax.swing.event.ChangeEvent evt) { controller.changeElementRotation((int)rotationSlider.getValue()); } private void opacitySpinnerStateChanged(javax.swing.event.ChangeEvent evt) { controller.changeElementOpacity((Integer)opacitySpinner.getValue()); } private void rotationSpinnerStateChanged(javax.swing.event.ChangeEvent evt) { controller.changeElementRotation((Integer)rotationSpinner.getValue()); } private void textDocumentChanged(DocumentEvent evt) { Document document = evt.getDocument(); try { controller.changeElementText(document.getText(0, document.getLength()));

} catch (BadLocationException ex) { // Handle exception. } } // /editor-fold Issues With Application Design Once the application is up and running, you immediately run into a problem. Consider the following chain of events: 1. One of the Swing components in the view receives a change, presumably from the user action. 2. The appropriate controller method is called. 3. The model is updated. It notifies the controller of its property change. 4. The view receives a change event from the controller and attempts to reset the value of the appropriate Swing components. 5. The appropriate controller method is called, and the model is updated again. At this point, any of three different scenarios can occur, depending on what Swing component you use and how robust your model is. The Swing component that prompted the initial change refuses to update itself the second time, noting that its property state cannot be updated again while it is in the process of notifying listeners of the initial state change. This primarily occurs when you use Swing text components. The model notes that the value of the second update matches that of the first, its current value, and refuses to send a change notification. This is always a safe programming practice, and it automatically occurs if you use the PropertyChangeSupport class provided in the java.beanspackage. However, it does not keep the model from receiving a redundant update. No safeguards are in place on either the model or the Swing component, and the program enters an infinite loop. This issue occurs because the Swing components are autonomous. For example, what happens if the user presses the up arrow of the JSpinner component in PropertiesViewPanel, incrementing the spinner's value by one? After the value is updated, a GUI event listener method that is listening for value changes is

called, opacitySpinnerStateChanged(), which in turn calls the controller and then updates the appropriate property in the model. With a traditional MVC design, the view would still contain the previous value, and the change in the model would update the view to the current value. However, there is no need to update the Swing component because it has already reset itself to the correct value -- it did so before it even passed an event to the controller. How do you get around this? One way is to write a mechanism that tells the model or the controller not to propagate a change notification under these circumstances, but this is not a good idea. Remember that more than one view may be listening for changes on the model. If you shut down the change notification for the model, no other listeners, including other views, will be notified of the change. In addition, other components in the same view may rely on the property change notification, with a slider and spinner combination, for example. Ideally, each Swing component would be aware of its current value and the value that the view is trying to set it to. If they match, no change notifications will be sent. However, some Swing components include this logic, and others do not. One possible solution is to check the incoming changed value of the model against the current value stored in the Swing component. If they are identical, there is no need to reset the value of the Swing component. Code Sample 8 shows an update of the modelPropertyChange() method to demonstrate this approach. Code Sample 8 public void modelPropertyChange(final PropertyChangeEvent evt) { if (evt.getPropertyName().equals(DefaultController.ELEMENT_X_PROPERTY)) { String newStringValue = evt.getNewValue().toString(); if (!xPositionTextField.getText().equals(newStringValue)) xPositionTextField.setText(newStringValue); } // Remaining code omitted }

The final example, which uses two delegate views, is shown in Figure 5. The second delegate makes use of the Java 2D libraries to display the text, which is beyond the scope of this article. However, the source code is relatively easy to follow and is included in the downloadable source code.

Figure 5. Both Views Attached to a Single Model Common Swing Component Listeners As this article has shown throughout, part of the initialization of each delegate or controller requires you to subscribe to various Swing component events. However, individual Swing components can often generate multiple event types. Table 1 presents some common listener methods. Table 1. Common Swing Event Listener Methods Event to Monitor Swing Event Listener Method

JButton pressed;JCheckBox pressed;J JButton.addActionListener(java.awt.event.A RadioButton pressed;JToggleButtont ctionListener) oggled. JSpinner.addChangeListener(javax.swing.ev JSpinner value changed. ent.ChangeListener)

JTextField,JFormattedTextField,JPas JTextField.getDocument().addDocumentList swordField orJTextArea character(s) ener(javax.swing.event.DocumentListener) are added, changed, or deleted. JTextField return button is pressed, orJTextField.addActionListener(java.awt.event focus switches to another component. .ActionListener) JComboBox new entry is selected. JComboBox.addActionListener(java.awt.eve from list. nt.ActionListener) JTextField editor = JComboBox editor (typically a text ((JTextField)comboBox.getEditor().getEdito field) characters are added, changed, rComponent()); or deleted. editor.getDocument().addDocumentListener( javax.swing.event.DocumentListener) JComboBox.addActionListener(java.awt.eve JComboBox return button is pressed. nt.ActionListener) JComboBox pop-up menu is about to JComboBox.addPopupMenuListener(javax.s become visible, invisible, or be wing.event.PopupMenuListener) cancelled without a selection. JList.addListSelectionListener(javax.swing.e JList new entry is selected. vent.ListSelectionListener) JTabbedPane.addChangeListener(javax.swin JTabbedPane new tab is selected. g.event.ChangeListener) JScrollBar.addAdjustmentListener(java.awt. JScrollBar adjustment is made. event.AdjustmentListener) JScrollPane.getHorizontalScrollBar().addAd justmentListener(java.awt.event.Adjustment Listener) JScrollPaneadjustment is made. JScrollPane.getVerticalScrollBar().addAdjus tmentListener(java.awt.event.AdjustmentLis tener) JPopupMenu is about to become JPopupMenu.addPopupMenuListener(javax. visible, invisible, or be cancelled swing.event.PopupMenuListener) without a selection. JMenu is about to be become visible JMenu.addMenuListener(javax.swing.event. or invisible, or be cancelled without a MenuListener) selection. JMenuItem (in standard or pop-up JMenuItem.addActionListener(java.awt.even menu) is selected. t.ActionListener) JSlider.addChangeListener(javax.swing.even JSlider value is changed. t.ChangeListener)

Conclusion MVC is one of the staples of any GUI programmer's toolkit. This article has shown how to implement a variation of the MVC design using Java SE and the Swing libraries. In addition, it has demonstrated some common issues that programmers may face when using MVC, as well as listed common Swing component events that any Java platform programmer can use when creating a view.

MVC Design Pattern v Java Webmail

Written by Administrator Feb 02, 2007 at 03:58 PM Trong bi vit ny, ti s gii thiu tng quan v Phng php thit k MVC, v minh ha Cch s dng MVC trong Thit k hng i tng bng vic xy dng phn mm Java Web Mail.

Phng php thit k MVC bt u t vic pht trin giao din vi ngi s dng (user interface) trong ngn ng lp trnh Smalltalk, v l mt trong nhng phng php thit k thnh cng nht trong cc Phng php thit k hng i tng (Object Oriented Design Pattern). Hin nay, MVC c dng mt cch rng ri trong nhiu h thng phn mm hng i tng (OO Application), bt k c vit bng ngn ng hng i tng (OO Language) no. Trong bi vit ny, ti s gii thiu tng quan v Phng php thit k MVC, v minh ha Cch s dng MVC trong Thit k hng i tng bng vic xy dng phn mm Java Web Mail. nhn r c ngha ca vic ng dng MVC trong Java Web Mail, bn c phi quen thuc vi ngn ng lp trnh Java, cc khi nim v JSP, Servlet, Java Mail API. Tuy nhin, bn c cng c th tham kho m

ngun ca chng trnh, dch, chy th v tm hiu dn dn. MVC l 3 ch vit tt ca Model-ViewController. Phng php thit k MVC (MVC Design Pattern)[1] l mt phng php chia nh Presentation tier ca mt ng dng nhiu lp (multi-tier application) hoc chia nh phn giao din vi ngi dng (user interface)[2] ca mt ng dng bt k thnh ba thnh phn chnh l Model, View v Controller. Model (Tm dch l phn M hnh [3]) : ng nh tn gi ca n, Model l mt i tng hoc mt tp hp cc i tng biu din cho phn d liu ca chng trnh, v d nh cc d liu c lu trong database, d liu t mt h thng cc ng dng khc nh legacy system, file system, mail system View (Tm dch l phn Hin th) : y l phn giao din vi ngi dng, bao gm vic hin d liu ra mn hnh, cung cp cc menu, nt bm, hp i thoi, chn la , ngi dng c th thm, xa. sa, tm kim v lm cc thao tc khc i vi d liu trong h thng. Controller (Tm dch l phn iu khin) : y l phn iu khin ton b logic v hot ng ca giao din, tng tc vi thao tc ca ngi dng (t chut, bn phm v cc thit b ngoi vi khc) v cp nht, thao tc trn d liu theo input nhn c v iu khin vic chn phn Hin th thch hp truyn d liu ti ngi dng.

Di y l s ca Phng php thit k MVC :

Khi ngi s dng ra mt lnh (g cu lnh, bm nt chut, bm phm, chn menu ), lnh ny s c gi ti phn iu khin. Phn iu khin s khi to phn M hnh (nu cn thit), gi cc yu cu ti phn M hnh thc hin. Cn c trn cc lnh v thng tin nhn c t lnh, phn M hnh s m nhn vic ly thng tin v cp nht thng tin trong cc h thng khc, v d trong cc Enterprise Server nh Aplication Server, Mail Server, Database Server, t File System, Network File System, Legacy System Sau khi hon thnh vic thu thp, cp nht thng tin, M hnh s truyn nhng thng tin cn thit v phn iu khin. Lc ny, phn iu khin s quyt nh chn thnh phn no trong phn Hin th hin d liu ra cho ngi dng. Phn Hin th khi lm nhim v hin thng tin cho ngi dng cng c th truy cp cc thng tin hin th t M

hnh, hoc gi thng tin hin th ti M hnh. Trng hp ny xy ra khi M hnh cha cc thng tin c th dng hin trc tip, v d mt danh sch khch hng, hoc mt danh sch cc email trong mailbox. Khi phn Hin th hin thng tin, n c th bo cho phn M hnh bit n ang hin phn no ca thng tin, v d nh ang hin thng tin khch hng t 20 n 40. Nhng thng tin loi ny khng cn thit phi gi qua trung gian iu khin. Vi phng php thit k ny, cc chc nng hin th, chc nng logic iu khin v chc nng truy cp d liu ca chng trnh c chia lm cc phn tch bit. Khi cu trc hoc cch ci t ca mt phn c thay i, cc phn kia hu nh khng cn thay i, hoc thay i rt t v API (Application Programming Interface). Khi phn Hin th cn thay i hnh thc trnh by, phn iu khin v phn M hnh hon ton c th gi nguyn. Java l mt ngn ng lp trnh hng i tng thun ty (pure OOP Language), nn vic p dng Phng php thit k MVC vo cc phn mm vit bng Java rt d dng v hin nhin. MVC khng phi l phng php duy nht dng thit k giao din vi ngi s dng trong Java, nhng cho n nay, n vn l phng php tt nht cho vic ny, nht l trong cc ng dng Web. K t khi ra i cng ngh JSP (Java Server Page) v Servlet, c hai hnh mu (model) [4] chnh ca Phng php thit k MVC trong Java l MVC model 1 v MVC model 2.

Di y l s ca MVC model 1:

Trong MVC model 1, cc trang JSP ng vai tr Hin th (View) v iu khin (Controller). C th c nhiu trang JSP khc nhau ng cc vai tr khc nhau. Khi ngi s dng dng cc nt bm, menu hoc link trn trnh duyt Web (Web browser) thc hin mt thao tc, mt lnh (c th km theo cc tham s) c gi ti mt trang JSP tng ng. Trang JSP ny s khi to mt hoc nhiu Java Bean (nu cn thit), truyn cc lnh cn thi hnh ti Java Bean. Ch rng y l cc Java Bean thng thng, ch khng phi Enterprise Java Bean (EJB) Sau khi Java Bean thc hin xong vic truy xut hoc cp nht d liu, trang JSP ban u c th hin th d liu ly t Bean (JSP ban u ng lun vai tr View), hoc chn mt trang JSP khc hin d liu t Bean (JSP ban u ng lun vai tr Controller). Trong mt thit k tt, bo m vic tch ri phn

trnh by v logic ca chng trnh, trang JSP nhn request ch ng vai tr iu khin (Controller).

MVC model 1 c mt nhc im l phn logic iu khin c vit trong trang JSP, nh vy phn chng trnh Java phc tp dng iu khin s b ln vo trong m HTML dng trnh by. phc tp ca chng trnh cng cao, th trang JSP cng kh bo tr. Hn na trong cc d n phn mm phc tp, th phn hin th ca trang JSP thng c lm bi ngi thit k Web, gii v HTML v ha, cn phn chng trnh Java c vit bi lp trnh vin chuyn v lp trnh. Trong cc d n phc tp, dng JSP lm phn iu khin s lm ln ln vic phn chia ranh gii trch nhim gia nhm thit k ha v nhm lp trnh, i khi dn n vic bo tr v pht trin tr nn rt kh khn, gn nh khng th lm c. khc phc nhc im ny, MVC model 2 ra i. Di y l s ca MVC model 2:

Trong MVC model 2, mt hoc nhiu servlet (thng l mt) ng vai tr iu khin, cc Java Bean ng vai tr M hnh v cc trang

JSP ng vai tr hin th. Trong model 2, cc logic phc tp ca chng trnh c vit hon ton trong cc servlet, l cc chng trnh Java. Phn hin th ch gm cc trang JSP vi mt vi m n gin ly d liu c sn, khng c logic phc tp, v th hon ton c th c to ra bng nhng ngi thit k Web. Cc yu cu ca ngi dng c gi t trnh duyt Web ti servlet. Servlet s khi to Java Bean (nu cn thit), ra lnh thu thp, cp nht thng tin. Khi Java Bean hon thnh cng vic, servlet s chn trang JSP thch hp hin thng tin trong Java Bean cho ngi dng. y chnh l mt cch s dng MVC rt hiu qu trong Java. Tt nhin l s dng MVC model 2 mt cch hon ton cng nhc, phn iu khin ch dng servlet, phn Hin th ch dng JSP s dn n mt vi trng hp km hiu qu, nht l khi c cc request t trnh duyt Web ch i hi vic hin th thng tin. V d: mt trang Web ang hin cc mail trong mail box t mail th 20 n mail th 40. Danh sch cc mail ny c sn phn M hnh khi ngi dng login v phn iu khin ra lnh cho phn M hnh ly danh sch cc mail c trong mail box trong POP server. T trang Web ny, ngi dng pht ra mt yu cu Next xem tip danh sch cc mail t mail th 40 n mail th 60. y n thun ch l i hi thng tin hin th, do , nu gi qua servlet iu khin , servlet s khng lm g c, m ch gi yu cu hin th ti trang JSP hin th danh sch mail. Trong trng hp ny, gi thng yu cu hin th t trnh duyt Web ti trang JSP s hiu qu hn.

S cho cch p dng MVC ni trn nh sau:

Trong cch p dng MVC ny, cc yu cu c lin quan n logic chng trnh hoc truy cp d liu s c gi ti servlet controller, cn cc yu cu ch lin quan ti hin th s c gi ti JSP controller. y chnh l cch ti chn ci t chng trnh Java Web Mail. Chng trnh Java Web Mail bao gm cc thnh phn sau : Mt servlet controller MailUtilServlet, dng nhn cc yu cu: login, logout, gi mail, hin attachment. Nhng yu cu ny s c x l v mt logic ri gi ti Java Bean thc s lm cng vic truy cp mail server. Sau khi Java Bean thc hin vic truy cp di liu xong, MailUtilServlet s chn trang JSP thch hp hin d liu. Mt Java Bean MailUserBean dng truy cp mail server, ly danh sch v mi dung mail trong mail box, xa mail trong server. Trang JSP index.jsp ng vai tr JSP

controller, dng nhn cc yu cu: hin danh sch cc mail trong mail box, hin ni dung ca mt mail c chn trong danh sch, hin trang son tho mail ngi dng son tho v gi mail. Nhng thng tin cn hin th c sn trong MailUserBean, v MailUserBean ly nhng thng tin ny khi nhn c yu cu login t MailUtilServlet. V th, nhng loi yu cu ny thuc v loi yu cu hin th, khng c logic phc tp, nn khng cn phi gi qua MailUtilServlet. Mt tp hp cc trang JSP: menu.jsp dng hin menu lnh bao gm Log in, Inbox, Compose v Exit first.jsp l trang nhp username, password, mailserver cho vic login messageheaders.jsp l trang hin danh sch cc mail c trong mail box ngi dng chn xem v xa mail trong mail box. messagecontent.jsp l trang hin ni dung ca mt mail c chn t danh sch. compose.jsp l trang son tho mail cn gi. status.jsp l trang dng bo v li khi log in, log out khng thnh cng, v thng bo v kt qu gi mail thnh cng hay khng. errordetails.jsp l trang dng cung cp thng tin chi tit mi khi c li log in, log out, gi mail khng thnh cng. Thng tin

trong trang ny bao gm c Stack Trace ca exception khi sinh ra li, ch yu dnh cho lp trnh vin dng xem chi tit v vn xy ra. logout.jsp l trang hin ra khi ngi dng login ra khi h thng mail. Mt vi trang JSP v text file khc dng trang tr. Mt CSS (Cascade Style Sheet) tn l styleSheet.txt, dng nh dng v font v mu sc cho tt c cc file JSP. Trong h thng ny, khng c database sever. MailUserBean ly v cp nht d liu t POP mail server, gi mail t SMTP server, s dng Java Mail API. Chng trnh gm c cc chc nng sau: S dng HTTP c v gi mail t bt k mt mail server no dng POP3 Protocol trn Internet hoc trong Intranet. C th truy cp mail qua bt k mt proxy server no c chc nng HTTP proxy. Chc nng ny rt c ch khi ngi dng kt ni vo Internet t mt mng Intranet pha sau mt firewall, v firewall ny ngn chn cc my tnh trong Intranet truy cp POP server bn ngoi, trong khi , ngi s dng mun gi v nhn mail t mt POP server trn Internet. S dng kh nng x l cc loi d liu (content handling) ca trnh duyt Web hin Attachment.

Bn c c th lin h vi tp ch PC World nhn file Zip cha ton b cc file Java, JSP ca bi vit, hoc download t Internet. y l mt ng dng Web s dng JSP/Servlet, nn phi c ci t nh mt Chng trnh Web (Web application) ca mt Web Server c h tr servlet engine (v d nh BEA WebLogic, IBM Web Sphere, Sun One, JBoss, Tomcat, Alaire JRun )hoc mt Web server kt ni vi servlet engine (v d nh IIS + Tomcat, Apache + Tomcat, IIS + JRun, Apache + JRun ). C hai phng php trin khai mt Chng trnh Web: Trin khai chng trnh trong th mc cha cc ng dng Web ca servlet engine, v d trong <TOMCAT>/webapps hoc trong <BEA>/ user_projects/ domains/ mydomain/ <DOMAIN NAME> ca BEA WebLogic. y l cch lm d nht. Trin khai chng trnh trong mt th mc bt k trn a cng ca server, ri chnh li server descriptor ch ti th mc ny. y khng phi l bi vit v ng dng Web v Cch trin khai ng dng Web, nn ti khng i su vo chi tit ca cch ci t Java Web Mail vo trong mt servlet engine. tin cho cc bn cha quen vi vic vit, dch v trin khai ng dng Web, ti xin trnh

by mt (trong s vi cch) d nht l trin khai Java Web Mail vo th mc webapps/examples ca Tomcat. Bn c th download Tomcat t v ci t ln my tnh ca bn. Khi bung nn file ra mt th mc no trn a cng, v d th mc D:\java\webmail, bn s c mt cu trc th mc nh sau Th mc D:\java\webmail\jspmail cha ton b cc trang JSP ca chng trnh, mt CSS dng nh dng mu sc v font ch cho tt c cc trang Web v mt vi file TXT cha thng tin v header, gooter ca trang Web. Th mc D:\java\webmail\jspmail\images cha cc nh dng trang tr giao din Web cha ton b cc trang JSP ca chng trnh. Th mc D:\java\webmail\src\com\hanoian\mail cha hai Java file l m ngun chng trnh ca MailUtilServlet v MailUserBean. Hai lp i tng ny thuc v gi (package) com.hanoian.mail, nn chng nm trong th mc com/hanoian/mail dc th mc src (source). Trong th mc D:\java\webmail, c file compile_sample.bat dng dch thng Java Web Mail vo th mc <TOMCAT>webapps/examples. Cc bn ch cc im sau trong file

compile_sample.bat : JAVA_HOME l th mc m bn ci J2SE (Java 2 Standard Edition), v d C:\j2sdk1.4.1_02. Bn c th t gi tr ny trong bin mi trng (environment variable), c gi tr trong tt c cc ln chy, hoc t gi tr ny bng lnh set trc khi chy compile_sample, hoc thay lun a tn th mc vo ch ca %JAVA_HOME% trong file compile_sample.bat. TOMCAT_HOME l th mc bn ci Tomcat, v d nh C:\Tomcat4. Bn c th lm tng t nh i vi JAVA_HOME trn thit lp gi tr cho TOMCAT_HOME Cc bc dch v trin khai chng trnh nh sau: Vo th mc <TOMCAT>/webapps/examples (v d C:\Tomcat4\examples), to th mc jspmail. Trong th mc jspmail to th mc images. M mt du nhc DOS, chuyn n th mc m bn gii nn file vo , v d D:\java/webmail. Chy file compile_sample.bat trong , Ch phi thit lp cc gi tr JAVA_HOME v TOMCAT_HOME trc khi chy. Vo th mc <TOMCAT>/webapps/examples/ WEBINF (v d C:\ Tomcat4\ examples\ WEB-INF), m file web.xml ra. C th dng Notepad, Wordpad hay bt k mt chng trnh son tho text no. Nu c XML Spy l tt nht.

Trong file web.xml tm phn nh ngha cc servlet, l phn bao gm rt nhiu cc XML element c tag l <servlet>, v d: <servlet> <servlet-name> CompressionFilterTestServlet </servlet-name> <servlet-class> compressionFilters.Compressio nFilterTestServlet </servlet-class> </servlet> vit thm khai bo servlet sau y vo phn di ca cc nh ngha <servlet> (tc l phn trng gia cc XML element <servlet> v <servletmapping>) : <servlet> <servletname>MailUtilServlet</servletname> <servlet-class> com.hanoian.mail.MailUtilServlet </servlet-class> </servlet> Ghi li file web.xml, sau khi ng li Tomcat. Nh vy l chng trnh c trin khai xong. Chy chng trnh bng cch m mt trnh duyt Web, g mt trong cc lin kt sau vo

phn a ch Web: http://localhost:8080/examples/servlet/MailUtil Servlet hoc http://localhost:8080/examples/jspmail/index.js p V yu cu u tin ca chng trnh ch l hin mn hnh nhp username v password, khng c logic, nn n c th c gi thng qua servlet controller hoc JSP controller ------------------------------------Ch thch [1] Trong phn tch/ thit k hng i tng (OOA/OOD), khi ni n MVC, ngi ta thng dng cc thut ng MVC Design Pattern, MVC Framework, MVC Paradigm. Theo kin ca ti, khi ni v thit k chng trnh, v diagram v cu trc ca chng trnh, MVC l mt phng php thit k (Design Pattern). Khi c mt b cng c tin ch lp trnh h tr cho lp trnh vin vit chng trnh theo phng php MVC (v d nh Jakarta Struts ), th b cng c tin ch lp trnh gi l MVC Framework implementation. Cn t Paradigm dng cho MVC mang tnh cht ch chung chung. Hin nay, ti M, cc thut ng trn thng c dng ln, ty theo tc gi v hon cnh. [2] Trong ngnh Khoa hc v my tnh (Computer Science), c rt nhiu khi nim v giao din (interface) khc nhau. V d: User interface l giao din gia my tnh v ngi dng, ch yu chia lm 2

loi chnh l Command line (Console) Interface, l giao din theo dng lnh v Graphical User Interface (GUI), l giao din ha vi ngi s dng. API (Application Programming Interface) l mt tp hp cc hm (funtion) hoc phng thc (method) c quy c sn ca cc software component m cc software component khc c th gi thc hin mt s chc nng xc nh trc. Mt v d v API l Window API, gm mt tp cc hm API dng gi thc hin cc chc nng h thng trn Window. Cc lp trnh vin vit chng trnh gi cc API ny tng tc vi Window v cung cp cc thao tc trong chng trnh. Object Interface : Trong mt h thng hng i tng, cc i tng (object) thng c thit k cung cp mt tp hp cc phng thc (method) m cc i tc khc c th s dng lm mt s nhim v nht nh. Tp cc method chung ca mt i tng thng c ci t thng qua mt giao din gi l Object Interface. Network Interface : y l card mng (network card ) ca my tnh hoc cc thit b mng. Ngoi ra, cn nhiu loi interface khc. V th, khi ni v giao din (interface), ti s dng thm b ng ch r l loi interface no. [3] Thc ra t Model trong trng hp ny (Data Model) dch ra ting Vit l M hnh

khng c chnh xc lm, v n khng phn nh ht chc nng ca Model trong mt h thng MVC. Dch ra l Mu hoc Hnh mu cng khng chnh xc. Chng ta cha c t ting Vit tng ng, nn ti tm gi l M hnh. [4] T model trong cm t MVC model 1 v MVC model 2 l dng ch cc hnh mu khc nhau ca cch p dng MVC vo thc t, ch khng phi l Data Model ca MVC. Bottom of Form