【笔记】Spring MVC学习指南(二)MVC模式
2015-09-22 00:08
417 查看
这一章跟Spring基本没有关系,权当是简单地复习了一下servlet的知识点。
示例实现了一个输入表单和输出信息的小功能,具体如下:
访问product_input.action跳转ProductForm.jsp,填写相关信息后点击提交按钮,访问product_save.action,跳转ProductDetails.jsp。
![](http://img.blog.csdn.net/20150921235603385?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20150921235712556?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
目录结构:
![](http://img.blog.csdn.net/20150922001836751?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
先来看web.xml,其中配置了servlet
Servlet类ControllerServlet.java
再来看看两个类文件,先是ProductForm.java
Product.java
再来看看两个jsp文件,先是ProductForm.jsp
再是ProductDetails.jsp
没有涉及到Spring,纯粹复习servlet内容。
在2.4小节,介绍了“解耦控制器代码”的操作,主要就是修改了原ControllerServlet.java,将处理跳转的那部分由硬编码改为调用接口方法(新增Controller接口以及InputProductController和SaveProductController两个实现类)。目录结构变为:
![](http://img.blog.csdn.net/20150922211435920?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
ControllerServlet.java修改了部分代码,重命名为DispatcherServlet.java,具体见截图:
![](http://img.blog.csdn.net/20150922211714989?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20150922211516565?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
新增的Controller.java
InputProductController.java
SaveProductController.java
如果根据现有情况来看,2.4节的改动无疑是增加了工作量,但把业务逻辑代码提取到独立的类中可以避免Servlet控制器的不断膨胀,利大于弊。
2.5小节对“校验器”功能做了个小的开发,原理很简单,就是新建了一个ProductValidator.java,内含validate()方法(在新的SaveProductController.java中被调用)对ProductForm对象进行属性值的判断并得出结论。以下是新增的代码部分:
ProductValidator.java
新版SaveProductController.java
ProductForm.jsp也做了相应更改,添加了输出错误提示的部分
第二章的内容就是这些,算是简单的MVC实例,没有涉及Spring
示例实现了一个输入表单和输出信息的小功能,具体如下:
访问product_input.action跳转ProductForm.jsp,填写相关信息后点击提交按钮,访问product_save.action,跳转ProductDetails.jsp。
目录结构:
先来看web.xml,其中配置了servlet
<?xml version="1.0" encoding="utf-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <servlet-mapping> <servlet-name>ControllerServlet</servlet-name> <!-- 只匹配.action的请求,嗯... --> <url-pattern>*.action</url-pattern> </servlet-mapping> <servlet> <servlet-name>ControllerServlet</servlet-name> <servlet-class>app02a.servlet.ControllerServlet</servlet-class> </servlet> </web-app>
Servlet类ControllerServlet.java
package app02a.servlet; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import app02a.domain.Product; import app02a.form.ProductForm; public class ControllerServlet extends HttpServlet { private static final long serialVersionUID = 1579L; @Override // 养成添加Override注解的习惯,有利于避免重写失败 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { process(request, response); // 无论get还是post,最终都是调用process() } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { process(request, response); } private void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String uri = request.getRequestURI(); // eg: visit http://localhost:7676/product_input.action, uri: /product_input.action /* * uri is in this form: /contextName/resourceName, * for example: /app10a/product_input. * However, in the event of a default context, the * context name is empty, and uri has this form * /resourceName, e.g.: /product_input */ int lastIndex = uri.lastIndexOf("/"); // 获取最终action的名称,lastIndexOf(),避免/a/b/c.action有多个斜线造成的获取失败。 String action = uri.substring(lastIndex + 1); // execute an action if (action.equals("product_input.action")) { // no action class, there is nothing to be done } else if (action.equals("product_save.action")) { // create form ProductForm productForm = new ProductForm(); // populate action properties productForm.setName(request.getParameter("name")); productForm.setDescription(request.getParameter("description")); productForm.setPrice(request.getParameter("price")); // create model Product product = new Product(); product.setName(productForm.getName()); product.setDescription(productForm.getDescription()); try { product.setPrice(Float.parseFloat(productForm.getPrice())); } catch (NumberFormatException e) { } // code to save product // store model in a scope variable for the view request.setAttribute("product", product); } // forward to a view String dispatchUrl = null; if (action.equals("product_input.action")) { dispatchUrl = "/WEB-INF/jsp/ProductForm.jsp"; } else if (action.equals("product_save.action")) { dispatchUrl = "/WEB-INF/jsp/ProductDetails.jsp"; } if (dispatchUrl != null) { RequestDispatcher rd = request.getRequestDispatcher(dispatchUrl); // 典型的servlet跳转方式 rd.forward(request, response); } } }
再来看看两个类文件,先是ProductForm.java
package app02a.form; public class ProductForm { private String name; private String description; private String price; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } }
Product.java
package app02a.domain; import java.io.Serializable; public class Product implements Serializable { private static final long serialVersionUID = 748392348L; private String name; private String description; private float price; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
再来看看两个jsp文件,先是ProductForm.jsp
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Add Product Form</title> <style type="text/css">@import url(/css/main.css);</style> <%-- /开头,根目录,另外 @import url()这个,没什么印象,需要注意--%> </head> <body> <div id="global"> <form action="product_save.action" method="post"> <fieldset> <%--这个标签还是挺实用的,记住吧--%> <legend>Add a product</legend> <p> <label for="name">Product Name: </label> <input type="text" id="name" name="name" tabindex="1"> <%--tabindex 属性规定元素的 tab 键控制次序(当 tab 键用于导航时,1 是第一个)。--%> </p> <p> <label for="description">Description: </label> <input type="text" id="description" name="description" tabindex="2"> </p> <p> <label for="price">Price: </label> <input type="text" id="price" name="price" tabindex="3"> </p> <p id="buttons"> <input id="reset" type="reset" tabindex="4"> <input id="submit" type="submit" tabindex="5" value="Add Product"> </p> </fieldset> </form> </div> </body> </html>
再是ProductDetails.jsp
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <%--依然是模板,粘贴复制的节奏--%> <title>Save Product</title> <style type="text/css">@import url(/css/main.css);</style> </head> <body> <div id="global"> <h4>The product has been saved.</h4> <p> <h5>Details:</h5> Product Name: ${product.name}<br/> <%--EL表达式,没啥好说的,不懂就看专门的章节去( ⊙ o ⊙ )啊!--%> Description: ${product.description}<br/> Price: $${product.price} </p> </div> </body> </html>
没有涉及到Spring,纯粹复习servlet内容。
在2.4小节,介绍了“解耦控制器代码”的操作,主要就是修改了原ControllerServlet.java,将处理跳转的那部分由硬编码改为调用接口方法(新增Controller接口以及InputProductController和SaveProductController两个实现类)。目录结构变为:
ControllerServlet.java修改了部分代码,重命名为DispatcherServlet.java,具体见截图:
新增的Controller.java
package app02a.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface Controller { String handleRequest(HttpServletRequest request, HttpServletResponse response); }
InputProductController.java
package app02a.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class InputProductController implements Controller { @Override public String handleRequest(HttpServletRequest request, HttpServletResponse response) { return "/WEB-INF/jsp/ProductForm.jsp"; } }
SaveProductController.java
package app02a.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import app02a.domain.Product; import app02a.form.ProductForm; public class SaveProductController implements Controller { @Override public String handleRequest(HttpServletRequest request, HttpServletResponse response) { ProductForm productForm = new ProductForm(); // populate form properties productForm.setName(request.getParameter("name")); productForm.setDescription(request.getParameter("description")); productForm.setPrice(request.getParameter("price")); // create model Product product = new Product(); product.setName(productForm.getName()); product.setDescription(productForm.getDescription()); try { product.setPrice(Float.parseFloat(productForm.getPrice())); } catch (NumberFormatException e) { } // insert code to add product to the database request.setAttribute("product", product); return "/WEB-INF/jsp/ProductDetails.jsp"; } }
如果根据现有情况来看,2.4节的改动无疑是增加了工作量,但把业务逻辑代码提取到独立的类中可以避免Servlet控制器的不断膨胀,利大于弊。
2.5小节对“校验器”功能做了个小的开发,原理很简单,就是新建了一个ProductValidator.java,内含validate()方法(在新的SaveProductController.java中被调用)对ProductForm对象进行属性值的判断并得出结论。以下是新增的代码部分:
ProductValidator.java
package app02a.validator; import java.util.ArrayList; import java.util.List; import app02a.form.ProductForm; public class ProductValidator { public List<String> validate(ProductForm productForm) { List<String> errors = new ArrayList<String>(); String name = productForm.getName(); if (name == null || name.trim().isEmpty()) { errors.add("Product must have a name"); } String price = productForm.getPrice(); if (price == null || price.trim().isEmpty()) { errors.add("Product must have a price"); } else { try { Float.parseFloat(price); } catch (NumberFormatException e) { errors.add("Invalid price value"); } } return errors; } }
新版SaveProductController.java
package app02a.controller; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import app02a.domain.Product; import app02a.form.ProductForm; import app02a.validator.ProductValidator; public class SaveProductController implements Controller { @Override public String handleRequest(HttpServletRequest request, HttpServletResponse response) { ProductForm productForm = new ProductForm(); // populate action properties productForm.setName(request.getParameter("name")); productForm.setDescription(request.getParameter("description")); productForm.setPrice(request.getParameter("price")); // validate ProductForm ProductValidator productValidator = new ProductValidator(); List<String> errors = productValidator.validate(productForm); if (errors.isEmpty()) { // create Product from ProductForm Product product = new Product(); product.setName(productForm.getName()); product.setDescription(productForm.getDescription()); product.setPrice(Float.parseFloat(productForm.getPrice())); // no validation error, execute action method // insert code to save product to the database // store product in a scope variable for the view request.setAttribute("product", product); return "/WEB-INF/jsp/ProductDetails.jsp"; } else { // store errors and form in a scope variable for the view request.setAttribute("errors", errors); request.setAttribute("form", productForm); return "/WEB-INF/jsp/ProductForm.jsp"; } } }
ProductForm.jsp也做了相应更改,添加了输出错误提示的部分
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE HTML> <html> <head> <title>Add Product Form</title> <style type="text/css">@import url(/css/main.css);</style> </head> <body> <div id="global"> <c:if test="${requestScope.errors != null}"> <p id="errors"> Error(s)! <ul> <c:forEach var="error" items="${requestScope.errors}"> <li>${error}</li> </c:forEach> </ul> </p> </c:if> <form action="product_save.action" method="post"> <fieldset> <legend>Add a product</legend> <p> <label for="name">Product Name: </label> <input type="text" id="name" name="name" tabindex="1"> </p> <p> <label for="description">Description: </label> <input type="text" id="description" name="description" tabindex="2"> </p> <p> <label for="price">Price: </label> <input type="text" id="price" name="price" tabindex="3"> </p> <p id="buttons"> <input id="reset" type="reset" tabindex="4"> <input id="submit" type="submit" tabindex="5" value="Add Product"> </p> </fieldset> </form> </div> </body> </html>
第二章的内容就是这些,算是简单的MVC实例,没有涉及Spring
相关文章推荐
- String.getBytes() 与编码格式
- JSP教程之使用JavaBean完成业务逻辑的方法
- spring framework最新发布压缩包
- Java NIO原理 图文分析及代码实现
- java读写excel之POI篇—003
- java读写excel之POI篇—004
- 《Java设计模式》七大原则
- Eclipse快捷键—几个常用最高效的快捷键
- SpringMVC学习篇—SpringMVC原理
- java synchronized详解
- kafka java示例
- ZeroMQ(java)之负载均衡
- Java基础之集合框架
- Unit Testing RxJava Observables and Subscriptions
- 使用java对文件中关键字进行统计,并作排序
- Java中Map转为List的方法
- kafka java示例
- ZeroMQ(java)之负载均衡
- Java 重写 equals 与 hashCode 的注意事项
- 利用java反射机制解析json