`
xiaoqzai414
  • 浏览: 15853 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

用Servlet实现MVC模式

阅读更多
MVC模式的学习

今天的内容:理解MVC的原理方法,以及看代码熟悉MVC的建议框架的实现
1. 看程序使用mvc实现helloworld的输出;
2. 看程序使用mvc实现猜数字游戏;


今天阅读的程序清单:
DispaterFilter.java
package com.yuqiaotech.simplejee.mvc;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* 本过滤器是作为mvc的前端控制器。
* 用来根据请求路径和配置文件的内容,触发相应的处理类(我们称为handler)的handler方法,
* 然后获取该方法返回的对象,调用其display方法进行显示。
*
*/
public class DispatcherFilter implements Filter {
private String contextPath;
public String configFile = "/mvc.xml";
public Map<String,HandlerConfig> handlerMapping = new HashMap<String,HandlerConfig>();
/**
* 初始化。
* 读取配置文件的位置,分析配置文件的内容。
* 并将配置内容转化为HandlerConfig对象,
* 然后以contextPath+path为key,放到一个map里,方便后续使用。
*/
public void init(FilterConfig cfg) throws ServletException {
System.out.println("DispatcherFilter init.");
String configFile = cfg.getInitParameter("configFile");
if(configFile != null)this.configFile = configFile;
contextPath = cfg.getServletContext().getContextPath();
parseConfigFile();

}
private void parseConfigFile(){
        InputStream in = DispatcherFilter.class.getResourceAsStream(configFile);
        DocumentBuilderFactory factory = DocumentBuilderFactory 
                .newInstance();
        DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
Document doc = builder.parse(in);
NodeList nodes = doc.getElementsByTagName("handler");
for (int i = 0; i < nodes.getLength(); i++) {
Element ele = (Element)nodes.item(i);
//现在很简单只有几个属性
String path = ele.getAttribute("path");
String clazz = ele.getAttribute("class");
String method = ele.getAttribute("method");
HandlerConfig handlerConfig = new HandlerConfig();
handlerConfig.setClazz(clazz);
handlerConfig.setPath(path);
handlerConfig.setMethod(method);

NodeList views = ele.getElementsByTagName("view");//注意与ele.getChildNodes()的区别
if(views != null){
for (int j = 0; j < views.getLength(); j++) {
Element viewEle = (Element) views.item(j);
View v = new View();
v.setName(viewEle.getAttribute("name"));
v.setType(viewEle.getAttribute("type"));
v.setValue(viewEle.getFirstChild().getNodeValue());//注意这里
handlerConfig.putView(v.getName(), v);
}
}

handlerMapping.put(contextPath+path, handlerConfig);
}
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);

}
public void destroy() {
System.out.println("DispatcherFilter: bye.");
}
/**
* 拦截请求。
*
* 从handlerMapping查找是否有对应当前请求路径的handler,
* 如果没有的话,继续chain.doFilter(request, response);
* 如果有的话,就实例化handler类,然后调用其handler方法,
* 然后处理返回的对象,如果返回的是String,那么包装成一个ForwardView对象,
* 否则调用返回对象的display方法。
*/
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)res;
       
        String url = request.getRequestURI();
        HandlerConfig handlerConfig = handlerMapping.get(url);
        if(handlerConfig != null){
        MvcServletContext context = new MvcServletContext();
        context.setRequest(request);
        context.setResponse(response);
        MvcContext.context.set(context);
       
        Object handler = newInstance(handlerConfig);
       
        //获取需要执行的方法名
String methodName = "handler";
String methodNameCfg = handlerConfig.getMethod();
if( methodNameCfg != null && !"".equals(methodNameCfg)){
methodName = handlerConfig.getMethod();
}else{
Enumeration<String> enuma = request.getParameterNames();
while(enuma.hasMoreElements()){
String pName = enuma.nextElement();
if(pName.startsWith("method:")){
methodName = pName.substring("method:".length());
break;
}
}
}//struts2还支持actionName!methodName的方式。
//执行方法并得到view对象
        Object view = invokeHandler(handlerConfig,handler,methodName);
        if(view != null){
        //获取如果返回的是字符串,
        //那么就使用该字符串从配置中找到相应的view
        if(view instanceof String){
        View v = handlerConfig.getView((String)view);
        if(v == null)throw new RuntimeException("no such view with name ["+view+"]");
        //这里显然太不灵活,不具备可扩展性。
        String type = v.getType();
        String viewValue = v.getValue();
        if("redirect".equals(type)){
        view = new RedirectView(viewValue);
        }else{
        view = new ForwardView(viewValue);
        }
        }
        invokeDisplay(handlerConfig,view);
        }
        //如果view为null,说明handler已经处理了显示问题
        }else{
        chain.doFilter(request, response);
        }
}
/**
* 实例化Handler类。
* @param handlerConfig
* @return
*/
private Object newInstance(HandlerConfig handlerConfig){
try {
return Class.forName(handlerConfig.getClazz()).newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
/**
* 触发Handler类的handler方法。
* 本mvc框架处于演示反射的目的,以及为struts2做准备的目的,
* 没有规定handler类必须实现特定接口,而只是规定需要有个方法名叫handler。
* @param handlerConfig
* @param o
* @return
*/
private Object invokeHandler(HandlerConfig handlerConfig,Object o,String methodName){
try {

Method m = o.getClass().getMethod(methodName, null);
return m.invoke(o, null);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* 触发handler方法返回的对象的display方法。
* @param handlerConfig
* @param view
*/
private void invokeDisplay(HandlerConfig handlerConfig,Object view){
try {
Method m = view.getClass().getMethod("display", null);
m.invoke(view, null);
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
*
*/
class HandlerConfig{
private String path;
private String clazz;
private String method;
private Map<String, View> views = new HashMap<String, View>();
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}

public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public void putView(String name,View v){
views.put(name, v);
}
public View getView(String name){
return this.views.get(name);
}

};
class View{
private String name;
private String type;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String toString(){
return name+"_"+type+"_"+value;
}
}


}


ForwardView.java

package com.yuqiaotech.simplejee.mvc;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ForwardView {

private String forwardTo;
public ForwardView(String forwardTo) {
this.forwardTo = forwardTo;
}
public void display(){
HttpServletRequest request = MvcContext.getRequest();
HttpServletResponse response = MvcContext.getResponse();
try {
request.getRequestDispatcher(forwardTo).forward(request, response);
} catch (ServletException e) {
throw new RuntimeException(e.getMessage(),e);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
}


MvcContext.java
package com.yuqiaotech.simplejee.mvc;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
* 这里主要是通过ThreadLocal技术,使得在一个线程之内,可以方便的
* 访问request,response等对象,而不是通过一层层的传输传递。
*
*/
public class MvcContext {
    public static final ThreadLocal <MvcServletContext> context =
        new ThreadLocal <MvcServletContext> ();
    public static HttpServletRequest getRequest(){
    return context.get().getRequest();
    }
    public static HttpSession getSession(){
    return context.get().getRequest().getSession();
    }
    public static ServletContext getApplication(){
    return context.get().getRequest().getSession().getServletContext();
    }
    public static HttpServletResponse getResponse(){
    return context.get().getResponse();
    }
}

MvcServletContext.java

package com.yuqiaotech.simplejee.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 为方便存取request和response写的一个简单的类。
*
*/
public class MvcServletContext {
private HttpServletRequest request;
private HttpServletResponse response;
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public HttpServletResponse getResponse() {
return response;
}
public void setResponse(HttpServletResponse response) {
this.response = response;
}
}

RedirectView.java

package com.yuqiaotech.simplejee.mvc;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;
/**
* 发送Location头信息的转向方式。
*
*/
public class RedirectView {

private String redirect;
public RedirectView(String redirect) {
this.redirect = redirect;
}
public void display(){
HttpServletResponse response = MvcContext.getResponse();
try {
response.sendRedirect(redirect);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
}

自己写的MVC猜数字程序清单:
NumberGuessServlet1.java
package com.yuqiao.qiu;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class NumberGuessServlet1 extends HttpServlet {

public  NumberGuessServlet1(){

}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}



public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{


// request.getSession().removeAttribute("randomNo");

String act=request.getParameter("act");
// Integer randomNo1=(Integer)request.getSession().getAttribute("randomNo");

if(null==request.getSession().getAttribute("randomNo")||"NewGuess".equals(act))
{
Random random=new Random();
Integer randomNo=random.nextInt(101);
System.out.print(randomNo);
request.getSession().removeAttribute("GuessTimes");
request.getSession().setAttribute("randomNo", randomNo);

if(null==this.getServletContext().getAttribute("times")){

this.getServletContext().setAttribute("times", 0);
}
else{
Integer times=(Integer)this.getServletContext().getAttribute("times");
++times;
this.getServletContext().setAttribute("times",times);
}
if("NewGuess".equals(act))
{
// this.getServletContext().setAttribute("times",times);
request.getRequestDispatcher("/list.jsp").forward(request, response);
}
}

if("guess".equals(act))
{
Integer number=Integer.parseInt(request.getParameter("number").trim());
request.getSession().setAttribute("number", number);
Integer GuessTimes=(Integer)request.getSession().getAttribute("GuessTimes");
if(GuessTimes == null)GuessTimes = 0;
GuessTimes+=1;
request.getSession().setAttribute("GuessTimes", GuessTimes);

if(number<(Integer)request.getSession().getAttribute("randomNo")){
request.setAttribute("content", "对不起你猜的数字小了");
}
if(number>(Integer)request.getSession().getAttribute("randomNo")){
request.setAttribute("content", "对不起你猜的数字大了");
}
if(number==(Integer)request.getSession().getAttribute("randomNo")){
// request.getSession().setAttribute("number", number);
request.getSession().removeAttribute("randomNo");
request.setAttribute("content", "恭喜你,你猜对了");
}
//
request.getRequestDispatcher("/result.jsp").forward(request, response);
}
if("new".equals(act))
{
request.getRequestDispatcher("/list.jsp").forward(request, response);
}

}


@Override
// protected void service(HttpServletRequest request, HttpServletResponse response)
// throws ServletException, IOException {
//
// }
//
// public Integer StringToInt(String number)
// {
// return Integer.parseInt(number);
// }

public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
public void init() throws ServletException {
// Put your code here
}


}


Web.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app>

    <welcome-file-list>
    <welcome-file>/list.jsp</welcome-file>
    </welcome-file-list>

<servlet>
    <servlet-name>NumberGuessServlet</servlet-name>
    <servlet-class>com.yuqiao.qiu.NumberGuessServlet1</servlet-class>
  </servlet>
 
 
  <servlet-mapping>
    <servlet-name>NumberGuessServlet</servlet-name>
    <url-pattern>/NumberGuessServlet</url-pattern>
  </servlet-mapping>
 

</web-app>

 




List.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
   
    <title>欢迎进入猜数字游戏</title>
   
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">   
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

  </head>
 
  <body>
   <div align=center><h1>NumberGuess</h1></div>
   <p></p>
   <p></p>
    <hr width=80%>
    <div align="center"><a href="<%=request.getContextPath() %>/NumberGuessServlet?act=NewGuess">新游戏</a></div>
    <div align=center>
       <form name=f action="<%=request.getContextPath() %>/NumberGuessServlet?act=guess" method="post">
          <input type="text" size=8  name="number">
          <input type="submit" value="guess">
       </form>
    </div>
  </body>
</html>



Result.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
   
    <title>My JSP 'result.jsp' starting page</title>
   
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">   
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

  </head>
 
  <body>
  <div align=center><P>结果显示</P></div>
  <p></p>
  <p></p>
  <hr width="80%"></hr>
  <div align=center>${content}</div>
  <div align=center> 你总共猜了${GuessTimes }次</div>
  <div align=center>总共有${times}人玩过此游戏</div>
  <div align=center><a href='<%=request.getContextPath()%>/NumberGuessServlet?act=new'>返回重新猜</a></div>
 
 
 
  </body>
</html>


今天学到的方法:
1. getContextPath() 获取的路径到底是哪边!
2. org.w3c.com.Node
NodeList getChildNodes()
包含此节点的所有子节点的 NodeList。如果不存在子节点,则这是不包含节点的 NodeList
   Org.w3c.com.Element NodeList getElementsByTagName(String name)
以文档顺序返回具有给定标记名称的所有后代 Elements 的 NodeList。



分享到:
评论
3 楼 spe294096580 2012-06-11  
[size=medium]zxX
[/align][align=left]
[flash=200,200][/flash]
[url][/url]

    [*]

    [*]
引用
[/i][i]
引用
引用
引用
引用
引用
引用
引用
引用
引用
引用
引用
引用
引用
引用
引用
[/size]
2 楼 spe294096580 2012-06-11  
zczxzdcx
1 楼 spe294096580 2012-06-11  
xs[b][/b][i][/i][u][/u]

相关推荐

    Jsp+JavaBean+Servlet(MVC设计模式)的寝室管理系统

    Jsp+JavaBean+Servlet(MVC设计模式)的寝室管理系统 Jsp+JavaBean+Servlet(MVC设计模式)的寝室管理系统 Jsp+JavaBean+Servlet(MVC设计模式)的寝室管理系统

    采用Servlet+Mvc模式实现学生管理系统

    在IT行业中,构建Web应用程序是常见的任务之一,而"Servlet+Mvc模式实现学生管理系统"是一个典型的案例,它展示了如何利用Java技术栈来设计一个简单的管理应用。在这个项目中,我们主要涉及了三个核心技术:Servlet...

    一个学生信息管理系统,使用jsp+Servlet的MVC模式,mysql数据库,适合初学者

    本篇文章将深入探讨一个使用jsp+Servlet实现的MVC模式学生信息管理系统,帮助读者理解这一经典架构。 首先,我们来了解一下MVC模式。MVC是一种软件设计模式,用于将业务逻辑(Model)、用户界面(View)和数据处理...

    JSP-Servlet 简单mvc模式

    总结来说,“JSP-Servlet 简单mvc模式”项目提供了一个基础的Web应用示例,通过JSP和Servlet实现MVC设计模式,展示了如何处理用户请求,管理业务逻辑,以及生成动态网页。这样的架构有助于提高代码的可读性和可维护...

    Java Web实验六 采用 DAO 模式实现对数据库的访问方法, 利用 Servlet 实现 MVC 模式

    Servlet在MVC模式中通常扮演控制器的角色,它接收HTTP请求,处理数据,然后将控制权传递给模型或视图。在实验中,你需要创建一个Servlet,比如UserController,用于处理用户的注册、登录等操作。 为了实现这个实验...

    基于JSP+Java+Servlet采用MVC模式开发的购物网站源码+项目说明.zip

    基于JSP+Java+Servlet采用MVC模式开发的购物网站源码+项目说明.zip基于JSP+Java+Servlet采用MVC模式开发的购物网站源码+项目说明.zip基于JSP+Java+Servlet采用MVC模式开发的购物网站源码+项目说明.zip基于JSP...

    Servlet的应用,使用MVC模式实现如下功能

    1、login.jsp:登录页面,登录表单提交到名为LoginServlet的Servlet。... 3、messageBoard.jsp:留言板页面,留言表单提交到名为MessageServlet的 Servlet。4、在MessageServlet中,...添加超链接(继续留言)实现再次留言。

    基于Jsp+JavaBean+Servlet实现MVC模式的分页模板

    基于Jsp+JavaBean+Servlet实现MVC模式的分页模板 分页没有css,但分页功能齐全 对初学者应该有帮助 分三层编写dao层 service层 web层 数据库可以用ms server2005 或者 mysql5.0 脚本为ms2005.sql 、mysql.sql 切换...

    基于Servlet实现的MVC项目demo

    使用Servlet实现MVC架构的优势在于其灵活性和可控性,但同时也存在一些挑战,比如代码组织复杂度增加,以及对于大型应用,手动管理请求转发和视图渲染可能会变得困难。 7. **其他MVC框架** 虽然Servlet能实现MVC...

    购物车jsp+servlet+MVC模式

    【标题】:“购物车jsp+servlet+MVC模式”实现详解 在Web开发中,创建一个功能完善的购物车系统是常见的需求。本项目采用经典的Java Web技术栈:JSP(JavaServer Pages)、Servlet以及MVC(Model-View-Controller)...

    Jsp+Servlet+JavaBean 实现MVC模式的留言本

    Jsp+Servlet+JavaBean 实现MVC模式的留言本 声明:本留言本所有源代码开源,使用者可以自由修改和传播,但仅限于非商业用途。 作者:梁龙 博客:http://www.lianglong.net.cn 由于这是本人学习JAVA的第一个项目,...

    一个学生信息管理系统,使用jsp+Servlet的MVC模式,mysql数据库

    《基于jsp+Servlet的MVC模式学生信息管理系统与MySQL数据库集成详解》 在现代教育管理中,信息系统的应用已经成为不可或缺的一部分。本系统——一个学生信息管理系统,采用的是经典的MVC(Model-View-Controller,...

    Servlet使用MVC模式(Dao\Service\Servlet)增删查改

    在这个名为"Servlet使用MVC模式(Dao\Service\Servlet)增删查改"的小程序中,我们将深入探讨如何利用这些组件来实现对MySQL数据库的操作。 **模型(Model)** 模型层是应用程序的核心,负责处理业务逻辑和数据访问...

    网上论坛基于MVC模式,用servlet技术实现(可以运行)

    在这个论坛项目中,Servlet可能被用来接收用户的登录、发帖、回帖等操作,并通过MVC模式将这些请求转发给相应的组件处理。 为了使这个论坛应用能够运行,你需要确保正确配置了数据库连接信息。通常,这包括数据库...

    基于jsp+servlet的mvc模式下的校园BBS论坛

    本项目以校园BBS论坛为例,探讨如何使用Java的JSP和Servlet技术实现一个基于MVC模式的Web应用。 **1. MVC模式介绍** MVC模式由三个核心组件组成: - **Model(模型)**:负责处理业务逻辑和数据管理,与数据库交互...

    jsp+dao+bean+servlet(MVC模式)实现简单用户登录和注册页面.docx

    jsp+dao+bean+servlet(MVC模式)是实现简单用户登录和注册页面的经典解决方案,该方案采用了MVC(Model-View-Controller)架构模式,具有良好的灵活性和可维护性。 在该解决方案中,jsp负责视图层的呈现,dao(Data ...

    JSP+Servlet的mvc模式的选课系统

    在这个"JSP+Servlet的mvc模式的选课系统"中,我们将深入探讨如何利用这两种技术实现这一模式。 1. **Model(模型)**:模型层主要负责处理业务逻辑和数据操作。在Java中,通常使用DAO(Data Access Object)模式来...

    servlet的mvc小练习

    本项目是一个关于Servlet的MVC小练习,旨在帮助学习者掌握如何使用Servlet实现基本的CRUD(创建、读取、更新和删除)操作,以及分页和模糊查询功能。同时,它还涉及到了一些请求跳转之间的实用技巧。以下是对这些...

    JavaServlet与MVC模式.doc

    在这个实验中,我们看到了如何使用JavaServlet和MVC模式来实现一个简单的Web应用,该应用计算两个正数的代数平均值和几何平均值: 1. **视图(View)**: 视图由两个JSP页面构成,`inputData.jsp`和`showResult.jsp`。...

    servlet简单实现的MVC框架

    在Servlet实现的MVC中,视图通常通过设置HttpServletResponse的相应头来决定输出的内容格式,比如重定向或转发到特定的JSP页面。 3. **Controller(控制器)**:控制器接收到请求后,根据请求参数和路由规则,调用...

Global site tag (gtag.js) - Google Analytics