第五章 Servlet与MVC

5.1MVC设计模式简介

1.什么是MVC模式

  MVC模式(Model-View-Controller)是软件工程中常见的一种软件架构模式,该模式把软件系统(项目)分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。

2.MVC模式的优势

①简化后期对项目的修改、扩展等维护操作;

②使项目的某一部分变得可以重复利用;

③使项目的结构更加直观。

3.每部分的功能

  MVC模式可以将项目划分为模型(M)、视图(V)和控制器(C)三个部分,并赋予各个部分不同的功能,方便开发人员进行分组:

a.视图(View):

负责界面的显示,以及与用户的交互功能。例如表单、网页等。

b.控制器(Controller):

可以理解为一个分发器,用来决定对于视图发来的请求,需要用哪一个模型来处理,以及处理完后需要跳回到哪一个视图。即用来连接视图和模型。

实际开发中,通常用控制器对客户端的请求数据进行封装(如将form表单发来的若干个表单字段值,封装到一个实体对象中),然后调用某一个模型来处理此请求,最后再转发请求(或重定向)到视图(或另一个控制器)。

c.模型(Model):

模型持有所有的数据、状态和程序逻辑。模型接受视图数据的请求,并返回最终的处理结果。

实际开发中,通常用封装数据的JavaBean和封装业务的JavaBean来实现模型层。

4.MVC模式的执行流程

浏览器通过视图向控制器发出请求–>
控制器接收到请求之后选择模型进行处理–>
模型处理完请求以后再转发到控制器–>
控制器再转发到视图界面的渲染并做出最终响应

在MVC模式中,视图View可以用JSP/HTML/CSS实现,模型model可以用Java Bean实现,而控制器Control就可以用Servlet来实现。

5.2 Servlet

  Servlet是基于Java技术的Web组件,运行在服务器端,由Servlet容器所管理,用于生成动态网页的内容。Servlet是一个符合特定规范的Java程序,编写一个Servlet,实际上就是按照Servlet的规范编写一个Java类,Servlet主要用于处理客户端请求并做出响应。

  在绝大多数的网络应用中,客户端都是通过HTTP协议来访问服务器端资源。这就要求我们编写的Servlet要适用于HTTP协议的请求和响应。我们本章讲解的Servlet,实际就是在讲解HttpServlet的相关类。

1.开发第一个Servlet程序

  如果要开发一个能够处理HTTP协议的控制器Servlet,就必须要继承javax.servlet.http.HttpServlet,并重写HttpServlet类里的doGet()方法或doPost()方法,用来处理客户端发来的get请求或post请求,方法简介如下,

方法简介
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException处理get方式的请求(如表单中,method=”get”;或超链接的请求方式)
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException处理post方式的请求(如表单中,method=”post”)

  doGet()和doPost()方法中的参数HttpServletRequest 对象req和HttpServletResponse 对象resp,就等价于JSP中的内置对象request和response。换句话说,JSP中的内置对象request,实际就是HttpServletRequest类型的对象;JSP内置对象response,实际就是HttpServletResponse类型的对象。因此,在doGet()和doPost()方法中,分别用req和resp处理请求和响应。

  接下来新建一个Web项目,用来开发第一个Servlet程序。先建一个名为ServletProject的Web Project,并将Dynamic web module version选择为4.0,如图
第一个servlet程序
之后再将该项目部署到eclipse中的tomcat里,并在WebContent下建index.jsp,代码如下:

<body>
<form action="WelcomeServlet" method="post">
	<input type="submit" value="提交">
</form>
</body>

  需要注意form表单的提交地址是WelcomeServlet,以及提交方式为post。

  接下来,再在src下新建一个WelcomeServlet类继承javax.servlet.http.HttpServlet,并重写HttpServlet的doGet()及doPost()方法,如下代码,

public class WelcomeServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		PrintWriter out = resp.getWriter();
		out.print("doGet()");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		PrintWriter out = resp.getWriter();
		out.print("doPost()");
	}
}

  如果现在就执行index.jsp中的submit按钮,是无法通过action跳转到WelcomeServlet的。因为,在Dynamic web module version选择为2.5的情况下,要想成功的实现从JSP(或其他Servlet)跳转到某一个特定的Servlet,必须要在web.xml中的标签里,加入一些servlet配置,具体如下:

<servlet>
	<!-- servlet名字和servlet-mapping名字要一致 -->
  	<servlet-name>welcome</servlet-name>
  	<!-- 全类名 -->
  	<servlet-class>com.lee.servlet.WelcomeServlet</servlet-class>
  </servlet>
  <servlet-mapping>
 	 <!-- servlet名字和servlet-mapping名字要一致 -->
 	<servlet-name>welcome</servlet-name>
 	<!-- 一定要加斜杠,否则服务起不来 -->
 	<url-pattern>/WelcomeServlet</url-pattern>
  </servlet-mapping>

  需要注意,每次修改web.xml后,都必须重新启动tomcat服务。

  具体的流程是:当用户点击index.jsp中的提交按钮后,程序发现action请求地址是“WelcomeServlet”,然后就会在web.xml中<servlet-mapping>内的<url-pattern>里寻找“WelcomeServlet”。如果匹配成功,就会根据<servlet-mapping>中的<servlet-name>值“welcome”,再去寻找<servlet>中的<servlet-name>值。如果仍然寻找成功,就会去执行<servlet>中的<servlet-class>里面的Servlet实现类(如com.lee.servlet.WelcomeServlet)。最后再根据请求方式,来决定执行Servlet实现类中的doGet()或doPost()方法。

运行index.jsp,并点击“提交”按钮,得到结果:
post方法执行结果
  以上就是用纯手写的方式开发的第一个Servlet程序,对于初学者来说可能稍微复杂一些,但上述的原理是必须要搞清楚的。此外,我们还可以借助于Eclipse来帮助我们快速的开发Servlet程序。

补充:解决在Eclipse 左键+Ctrl看不了HttpServlet源代码的方法

如果点Ctrl+鼠标左键,想看HTTPServlet源码,出现下图,说明没导源码包
没导源码包
导源码包方法:
Tomcat官方网站 中下载对应的Tomcat的源码,选择你对应的tomacat版本:
Tomcat版本
源码包
点击change attached source 导入即可:
导入zip包

2.使用Eclipse快速开发Servlet程序

用Eclipse开发Servlet,会比手工方式方便很多。我们接下来就用Eclipse来开发一个Servlet(需要确保项目的Dynamic web module version为2.5),步骤如下:

①新建一个index.jsp

Index.jsp

 <form action="WelcomeServlet" method="post" >
  <input type="submit" value="提交" /> 
 </form>

②再在src下,直接创建一个servlet(不再是创建class):鼠标右键src→new→Servlet→ 填入任意的Class name如图,
eclipse创建servlet
  点击Finish之后,我们就会得到一个已经继承了HttpServlet,并重写了doGet()和doPost()方法的类(即Servlet)。我们将注释等无关代码删除之后,得到如以下代码,

WelcomeServlet.java

public class WelcomeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public WelcomeServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

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

上面代码中的serialVersionUID,读者暂时不用理会,可以直接先将其删除。

再观察一下web.xml,会发现Eclipse也已经为我们自动生成了<servlet><servlet-mapping>的相关配置。

也就是说,如果用Eclipse创建一个servlet,就会得到一个已经继承了HttpServlet,并重写了doGet()和doPost()方法的类,并且自动完成了web.xml的配置。因此,使用Eclipose开发Servlet,可以提高我们的开发效率。

以上就是项目的Dynamic web module version为2.5时,开发servlet程序的方法及步骤。

3.Servlet3.0简介

接下来再重新创建一个Web项目,此次将Dynamic web module version选为3.0,如图,
servlet3.0
创建index.jsp,
index.jsp

  <form action="WelcomeServlet30" method="post" >
   <input type="submit" value="提交" /> 
  </form> 

这次再尝试通过Eclipse来创建一个名为WelcomeServlet30的servlet,会得到如下代码,

WelcomeServlet30.java

@WebServlet("/WelcomeServlet30")
public class WelcomeServlet30 extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public WelcomeServlet30() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

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

  仔细观察上面代码,会发现本次用Dynamic web module version3.0开发的servlet,比之前用Dynamic web module version为2.5开发的servlet多了一句@WebServlet(“/WelcomeServlet30WithEclipse”)再观察web.xml,会发现web.xml中,并没有像之前那样自动生成<servlet><servlet-mapping>的配置。

然后启动服务,直接运行index.jsp,点击提交后,也能得到正确的结果。

Servlet3.0和Servlet2.5的区别

(Dynamic web module version3.0与Dynamic web module version2.5的区别):
Servlet3.0及以上不用在web.xml中配置servlet,而是直接使用@WebServlet在创建的Servlet类名前加上映射路径(相当于之前web.xml中的<url-pattern>),如@WebServlet(“/WelcomeServlet30”)。

Servlet2.5需要配置web.xml中的servlet和servlet-mapping。

4.Servlet生命周期

Servlet是运行在服务器端的一段程序,所以Servlet的生命周期会受Servlet容器的控制。

Servlet生命周期包括加载、初始化、服务、销毁、卸载等5个部分。

  通常情况,加载和卸载阶段可以由Servlet容器来处理,我们只需要关注初始化、服务、销毁三个阶段。与Servlet生命周期相关的方法,如下表,

方法简介
public void init() throws ServletExceptionServlet初始化时调用
public void init(ServletConfig config) throws ServletExceptioninit() 的重载方法,Servlet初始化时调用,并可以通过config来读取配置信息
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;提供Servlet服务的方法。此方法是抽象方法,故实际使用的是此抽象方法的实现方法doGet()或doPost()来处理get或post请求
public void destroy()Servlet销毁时调用
①初始化

当一个Servlet被加载完毕并实例化以后,Servlet容器将调用init()方法初始化这个对象,执行一些初始化的工作,如读取资源配置信息等。如果初始化阶段发生错误,此Servlet实例将被容器直接卸载。

注意:
若init()和init(ServletConfig config)同时存在,则只加载init(ServletConfig
config)。

②服务

初始化完成以后,Servlet就会去调用service()的具体实现方法doGet()或doPost(),来处理请求;并通过ServletRequest类型的参数接收客户端的请求,以及通过ServletResponse类型的参数处理响应信息。

③销毁

Servlet实例服务完毕以后,就可以通过destroy()方法来指明哪些资源可以被系统回收(注意destroy()方法只是“指明”需要被回收的方法,并不会直接进行回收)。

下面我们通过一个例子,来看一下Servlet生命周期的执行流程:

@WebServlet("/LifeCycleServlet")
public class LifeCycleServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	public void init() throws ServletException {
		System.out.println("init()");
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("doGet(HttpServletRequest request, HttpServletResponse response)");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("doPost(HttpServletRequest request, HttpServletResponse response)");
	}
	
	@Override
	public void destroy() {
		System.out.println("destroy()");
	}
}

前面讲过,通过浏览器的地址栏访问服务器,属于GET方式的请求。现在直接访问 http://localhost:8080/ServletProject30/LifeCycleServlet ,第一次访问时,运行结果:
servlet声明周期
在执行两次后,运行结果:
servlet声明周期2
关闭服务器(注意是在Servers面板中点击红色的关闭按钮,而不是在Console控制台中),可以发现Servlet容器确实执行了destroy()方法,运行结果:
关闭Tomcat
  不难发现,在Servlet生命周期中,初始化init() 方法只在第一次访问时执行一次;而doGet()doPost()方法会在服务器每次接收请求时,都执行一次;销毁destroy()方法只会在关闭服务时执行一次。

5.load-on-start-up

  初始化方法init()默认会在客户端第一次调用servlet服务(即调用doGet()或doPost())时执行,但也可以通过配置(servlet2.5通过 web.xml配置;servlet3.0通过注解配置),让初始化init()方法在Tomcat容器启动时自动执行。具体的配置方法如下:

①如果使用servlet2.5:

在web.xml中的标签中加入,如下:

<servlet>
       <servlet-name>WelcomeServlet</servlet-name>
      <servlet-class>com.lee.servlet.WelcomeServlet</servlet-class>
          <load-on-startup>1</load-on-startup>
</servlet> 
② 如果使用servlet3.0:

在@WebServlet中加入loadOnStart属性,如下:

@WebServlet(value="/LifeCycleServlet",loadOnStartup=1)
public class LifeCycleServlet extends HttpServlet {
	@Override
	public void init() throws ServletException {
		System.out.println("LifeCycleServlet初始化啦!");
	}
	@Override
	public void destroy() {
		System.out.println("LifeCycleServlet销毁化啦!");
	}
}

配置完毕后,再次启动Tomcat服务,可以看到init()方法会在tomcat启动时自动执行,如图
loadonstartup

扩展:表示如果有多个servlet同时配置了loadOnStartp,servlet的启动顺序是怎么样的?

答案:loadOnStartp的值越小,越先启动。
演示一下:
WelcomeServlet30.java
设置loadOnStartup=0

@WebServlet(value="/WelcomeServlet30",loadOnStartup=0)
public class WelcomeServlet30 extends HttpServlet {
	@Override
	public void destroy() {
		System.out.println("welcome销毁!");
	}

	@Override
	public void init() throws ServletException {
		System.out.println("welcome初始化!");
	}
}

LifeCycleServlet.java
设置loadOnStartup=1

@WebServlet(value="/LifeCycleServlet",loadOnStartup=1)
public class LifeCycleServlet extends HttpServlet {
	@Override
	public void init() throws ServletException {
		System.out.println("LifeCycleServlet初始化啦!");
	}
	@Override
	public void destroy() {
		System.out.println("LifeCycleServlet销毁化啦!");
	}
}

启动Tomcat服务,运行结果
多个servlet的加载顺序
关闭服务器(注意是在Servers面板中点击红色的关闭按钮,而不是在Console控制台中),可以发现Servlet容器执行了destroy()方法的顺序,运行结果:
多个servlet的销毁顺序
结论:
①servlet会按照loadOnStartup的值得大小决定加载顺序,loadOnStartup越小越先加载。
②先加载的servlet先销毁。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JSP、JavaBean、ServletMVC模式都是Java Web开发中非常常用的技术。图书管理系统是一个常见的Web应用程序,下面将介绍如何使用JSP、JavaBean、ServletMVC模式来实现图书管理系统。 JSP(Java Server Pages)是一种Java Web技术,可以将Java代码嵌入到HTML页面中,从而实现动态的Web内容。在图书管理系统中,可以使用JSP来呈现图书信息、读者信息和借书信息等页面。 JavaBean是一种Java语言中的标准组件,具有可重用性和可组合性的特点。在图书管理系统中,可以使用JavaBean来表示图书、读者和借书信息等数据模型,从而实现数据的封装和重用。 Servlet是一种Java Web技术,用于在Web服务器上运行Java程序。在图书管理系统中,可以使用Servlet来处理用户请求,例如添加图书、查询图书、删除图书等操作。 MVC模式是一种设计模式,用于将应用程序分成模型、视图和控制器三个部分。在图书管理系统中,模型部分可以使用JavaBean表示数据模型,视图部分可以使用JSP呈现页面,控制器部分可以使用Servlet处理用户请求,从而实现业务逻辑和用户界面之间的分离。 综上所述,JSP、JavaBean、ServletMVC模式都是Java Web开发中非常重要的技术,可以被应用在图书管理系统中。利用这些技术,可以实现一个高效、可扩展和容易维护的Web应用程序,从而提高系统的可靠性和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值