Java Web MVC 一个实例的手动实现

平台:

tomcat7.0    Servlet3.0    Windows命令行编译

实现的功能:

在网页上可以进行对Product类的三个属性的输入,点击保存之后跳转到另一个显示输入内容的界面

文件结构:

  • SpringDemo02
    • index.html
    • WEB-INF
      • web.xml
      • classes
      • jsp
      • lib

说明:

  • index.html是欢迎界面,当没有指定到具体的servlet(为 /SpringDemo02/)时显示
  • WEB-INF中的文件将被确保不会被URL直接访问到
  • web.xml进行servlet和欢迎文件的配置
  • classes放置Java文件(Controller和Model)
  • jsp防止不想被URL直接访问的页面文件(View)
  • lib放置引用的文件

index.html

随便写一个欢迎内容

web.xml

用于配置servlet/Listener/filter/welcome file等。这里只配置servlet和welcome file

<?xml version="1.0" encoding="ISO-8859-1"?>
<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>
        <servlet-name>ControllerServlet</servlet-name>
        <servlet-class>ControllerServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ControllerServlet</servlet-name>
        <url-pattern>/product_input</url-pattern>
        <url-pattern>/product_save</url-pattern>
    </servlet-mapping>
    
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>

前面的web-app的配置基本是固定的,和web的版本有关

配置ControllerServlet的<servlet-class>将到WEB-INF文件夹下的classes文件夹找对应的类文件

将这个servlet映射到/product_input和/product_save的URL模式

lib

放置会使用到的javax.servlet-api-3.0.1.jar

jsp

product_input.jsp:有表单和一个按钮,点击按钮后将向product_save方法通过POST方法发送表单中的内容

效果:

代码如下:

<!DOCTYPE HTML>
<html>
    <head>
        <title>input product</title>
    </head>
    <body>
        <form id="input_form" action="product_save" method="post">
            <label>
                <span>Name</span>
                <input id="name" type="text" name="name"/>
            </label>
            <label>
                <span>Discription</span>
                <input id="discription" type="text" name="discription"/>
            </label>
            <label>
                <span>Price</span>
                <input id="price" type="number" name="price"/>
            </label>         
            <label>
                <span>&nbsp: </span>
                <input type="submit"/>
            </label>               
        </form>
    </body>
</html>

form的action属性表示有提交按钮的时候向product_save方法提交数据,用post方法

product_save.jsp:显示传入的数据的内容

效果如下:

代码如下:

<!DOCTYPE HTML>
<html>
    <head>
        <title>save product</title>
    </head>
    <body>
        <p>
            Product Name: ${product.name}<br/>
            Discription:  ${product.discription}<br/>
            Price: ${product.price}
        </p>
    </body>
</html>

在控制器中将会向响应数据写入product对象,并将该对象命名为"product",所以在这个jsp文件中可以通过${product.XXX}访问到对应的属性数据

classes

有五个类:

  • ControllerServlet:主要的控制逻辑的servlet
  • Product:实体类
  • ProductForm:提交的表单数据对应的类
  • SaveProductAction:数据库操作(但实际上方法是空的)
  • DefaultServlet:用以演示默认servlet的servlet类

Product:

代码如下:

public class Product
{
    private String name ;
    private String discription ;
    private float  price;
    
    public String getName()
    {
        return this.name;
    }
    
    public void setName(String name)
    {
        this.name = name;
    }
    
    public String getDiscription()
    {
        return this.discription;
    }
    
    public void setDiscription(String discription)
    {
        this.discription = discription;
    }
    
    public float getPrice()
    {
        return this.price;
    }
    
    public void setPrice(float price)
    {
        this.price = price;
    }    
}

ProductForm:

代码如下

public class ProductForm
{
    private String name ;
    private String discription ;
    private float  price;
    
    public String getName()
    {
        return this.name;
    }
    
    public void setName(String name)
    {
        this.name = name;
    }
    
    public String getDiscription()
    {
        return this.discription;
    }
    
    public void setDiscription(String discription)
    {
        this.discription = discription;
    }
    
    public float getPrice()
    {
        return this.price;
    }
    
    public void setPrice(float price)
    {
        this.price = price;
    }    
}

虽然在这个简单的demo中Product类和ProductForm类是一样的,看起来没有必要分开实现,但是实际上提交的数据和表示数据库的实体类可能有不一致等情况,而且为了降低耦合,还是将这两种分为两个类

DefaultServlet:

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DefaultServlet extends HttpServlet
{
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws IOException, ServletException
    {
        PrintWriter out = resp.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
        out.println("  <BODY>");
        out.print("    This is ");
        out.print(this.getClass());
        out.println(", using the GET method");
        out.println("  </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();
    }
    
    public void doPost(HttpServletRequest req, HttpServletResponse resp) 
    throws IOException, ServletException
    {
        PrintWriter out = resp.getWriter();
        out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
        out.println("<HTML>");
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
        out.println("  <BODY>");
        out.print("    This is ");
        out.print(this.getClass());
        out.println(", using the POST method");
        out.println("  </BODY>");
        out.println("</HTML>");
        out.flush();
        out.close();
    }
}

这个类实现了HttpServlet接口,重写了doGet和doPost方法,随便输出了一些和当前对象有关的信息

ServletResponse中内置了一个PrintWriter,客户端接收到数据后会写为页面

ControllerServlet:

import java.io.IOException;
import java.io.*;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 通过注解注册servlet而不用在xml中注册
@WebServlet(name = "ControllerServlet", urlPatterns = {"/product_input","/product_save"})
public class ControllerServlet extends HttpServlet
{
    @override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws IOException, ServletException
    {
        process(req,resp);
    }
    
    @override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) 
    throws IOException, ServletException
    {
        process(req,resp);
    }
    
    // 
    private void process(HttpServletRequest req, HttpServletResponse resp)
    throws IOException, ServletException
    {
        // 解析URL
        String uri = req.getRequestURI();
        
        int lastIndex = uri.lastIndexOf("/");
        String action = uri.substring(lastIndex+1);
        
        // 根据URL解析出来的action进行相应的操作
        if(action.equals("product_input"))
        {
            
        }
        else if(action.equals("product_save"))
        {
            // 从HttpServletRequest获取数据到表单
            ProductForm pf = new ProductForm();
            pf.setName(req.getParameter("name"));
            pf.setDiscription(req.getParameter("discription"));
            pf.setPrice(Float.valueOf(req.getParameter("price")));
            
            // 根据表单设置实体类
            Product p = new Product();
            p.setName(pf.getName());
            p.setDiscription(pf.getDiscription());
            p.setPrice(pf.getPrice());
            
            // 写回数据库
            SaveProductAction spa = new SaveProductAction();
            spa.save(p);
            
            // 将获取到的实体对象写回到响应以便显示
            req.setAttribute("product",p);
        }
            
        // 调用View
        String requestDispatcher = null;
        if(action.equals("product_input"))
        {
            requestDispatcher = "WEB-INF/jsp/product_input.jsp";
        }
        else if(action.equals("product_save"))
        {
            requestDispatcher = "WEB-INF/jsp/product_save.jsp";
        }
        if(requestDispatcher!=null)
        {
            RequestDispatcher rd = req.getRequestDispatcher(requestDispatcher);        
            rd.forward(req,resp);            
        }
    }// process
}// class

这个类能获得的只有HttpServletRequest和HttpServletResponse,要从里面获取URL并解析

无论获取到的是POST方法还是GET方法都执行process方法

根据解析出来的action进行相应的操作之后需要跳转到相应的View中,即jsp文件。需要从HttpServletRequest中获取RequestDispatcher对象,以此进行跳转

SaveProductAction:

这是模拟数据库操作的

public class SaveProductAction
{
    public void save(Product p)
    {
        // save to database
    }
}

编译

在命令行编译的时候需要加上使用到的jar文件,方式是javac -cp jar文件路径 源文件.java,-cp也可以替换为-classpath

需要注意的是当使用-cp的时候会取消默认使用当前文件夹中的class文件,所以要在 .jar文件路径后面加上 ";."表示还有当前路径下的class文件

部署

编译之后,将SpringDemo02文件夹拷贝到Tomcat中的Webapps文件夹下,运行tomcat文件夹中bin文件夹下的startup.bat运行tomcat,启动时tomcat将自动部署webapps文件夹中的应用程序

tomcat的安装:下载tomcat压缩包解压,并将这个文件夹配置到环境变量的CATALINE_HOME下,将bin文件夹配置到环境变量的PATH中

运行

tomcat会默认使用本地的8080端口

localhost:8080/SpringDemo02/product_input

点击提交之后:

猜你喜欢

转载自blog.csdn.net/qq_40711741/article/details/81189578