理解Servlet

这周遇到了一个很尴尬的错误

org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [spring-config.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'userDaoImpl' for bean class [com.iflytek.kcloud.web.dao.bucketApp.impl.UserDaoImpl] conflicts with existing, non-compatible bean definition of same name and class [com.iflytek.kcloud.web.dao.bucket.impl.UserDaoImpl]

把报错贴到百度上搜到了解决方法如下:

https://stackoverflow.com/questions/10299895/conflicts-with-existing-non-compatible-bean-definition-of-same-name-and-class-a

其实就是两个目录下的bean的名字是一样的,Spring没法对应吧,在注释里面取个新的名字就好了:@Repository("appUserDao")……

于是就发现自己对这些基本的东西完全不求甚解,真的是“面向百度编程”了。SpringMVC的项目也写过几个了,决心反过头来研究一下理论知识。SpringMVC是基于Servlet的,只有先深入理解Servlet才能理解后面的新技术。

 

 

基本介绍

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
主要功能在于交互式地浏览和修改数据,生成动态Web内容。
这个过程为:
  1. 客户端发送请求至服务器端;
  2. 服务器将请求信息发送至 Servlet;
  3. Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
  4. 服务器将响应返回给客户端。
Servlet 看起来像是通常的 Java 程序。Servlet 导入特定的属于 Java Servlet API 的包。因为是对象字节码,可动态地从网络加载,可以说 Servlet 对 Server 就如同 Applet对 Client 一样,但是,由于 Servlet 运行于 Server 中,它们并不需要一个图形用户界面。从这个角度讲,Servlet 也被称为 FacelessObject。
 
一个 Servlet 就是 Java 编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。虽然 Servlet 可以对任何类型的请求产生响应,但通常只用来扩展 Web 服务器的应用程序。
 
 
生命周期
  1. 客户端请求该 Servlet;
  2. 加载 Servlet 类到内存;
  3. 实例化并调用init()方法初始化该 Servlet;
  4. service()(根据请求方法不同调用doGet() 或者 doPost(),此外还有doHead()、doPut()、doTrace()、doDelete()、doOptions()、destroy())。
  5. 加载和实例化 Servlet。这项操作一般是动态执行的。然而,Server 通常会提供一个管理的选项,用于在 Server 启动时强制装载和初始化特定的 Servlet。
Server 创建一个 Servlet的实例
第一个客户端的请求到达 Server
Server 调用 Servlet 的 init() 方法(可配置为 Server 创建 Servlet 实例时调用,在 web.xml 中 <servlet> 标签下配置 <load-on-startup> 标签,配置的值为整型,值越小 Servlet 的启动优先级越高)
一个客户端的请求到达 Server
Server 创建一个请求对象,处理客户端请求
Server 创建一个响应对象,响应客户端请求
Server 激活 Servlet 的 service() 方法,传递请求和响应对象作为参数
service() 方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息
service() 方法使用响应对象的方法,将响应传回Server,最终到达客户端。service()方法可能激活其它方法以处理请求,如 doGet() 或 doPost() 或程序员自己开发的新的方法。
对于更多的客户端请求,Server 创建新的请求和响应对象,仍然激活此 Servlet 的 service() 方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用 init() 方法。一般 Servlet 只初始化一次(只有一个对象),当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方法。
 
Hello World
 1 // 导入必需的 java 库
 2 import java.io.*;
 3 import javax.servlet.*;
 4 import javax.servlet.http.*;
 5 
 6 // 扩展 HttpServlet 类
 7 public class HelloWorld extends HttpServlet {
 8  
 9   private String message;
10 
11   public void init() throws ServletException
12   {
13       // 执行必需的初始化
14       message = "Hello World";
15   }
16 
17   public void doGet(HttpServletRequest request,
18                     HttpServletResponse response)
19             throws ServletException, IOException
20   {
21       // 设置响应内容类型
22       response.setContentType("text/html");
23 
24       // 实际的逻辑是在这里
25       PrintWriter out = response.getWriter();
26       out.println("<h1>" + message + "</h1>");
27   }
28   
29   public void destroy()
30   {
31       // 什么也不做
32   }
33 }

把上面的代码写在 HelloWorld.java 文件中,把这个文件放在 C:\ServletDevel(在 Windows 上)或 /usr/ServletDevel(在 UNIX 上)中,还需要把这些目录添加到 CLASSPATH 中。

假设环境已经正确地设置,进入 ServletDevel 目录,并编译 HelloWorld.java,如下所示:

$ javac HelloWorld.java
 

默认情况下,Servlet 应用程序位于路径 <Tomcat-installation-directory>/webapps/ROOT 下,且类文件放在 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中。

如果我们有一个完全合格的类名称 com.myorg.MyServlet,那么这个 Servlet 类必须位于 WEB-INF/classes/com/myorg/MyServlet.class 中。

把 HelloWorld.class 复制到 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中,并在位于 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/ 的 web.xml 文件中创建以下条目:

<web-app>      
    <servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>HelloWorld</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld</url-pattern>
    </servlet-mapping>
</web-app>

 

上面的条目要被创建在 web.xml 文件中的 <web-app>...</web-app> 标签内。

接下来使用 <Tomcat-installation-directory>\bin\startup.bat启动 tomcat 服务器,最后在浏览器的地址栏中输入 http://localhost:8080/HelloWorld。页面上输出了“Hello World”。

 

servlet 浏览器访问路径配置有个小问题:

1、java 类里的注解 —— @WebServlet("/HelloServlet") 对应浏览器路径:

http://localhost:8080/TomcatTest/HelloServlet

2、配置文件(we.xml)里对应的浏览器访问路径:

http://localhost:8080/TomcatTest/TomcatTest/HelloServlet

这两种配一个就好了,不然路径重名的话反而会让tomcat启动不了。

例如这样就启动不了:

修改 web.xml :

<url-pattern>/HelloServlet</url-pattern>

修改后,web.xml 和 java 类的注解,对应路径都是:

http://localhost:8080/TomcatTest/HelloServlet

导致

命名的 servlet[HelloServlet]和 [com.runoob.test.HelloServlet] 都被映射到 URL 模式 [/ HelloServlet] 这是不允许的。

解决办法:

将注解去掉或者保留注解进入web.xml将映射删除就可以。

 
 
Reference:
[1] https://baike.baidu.com/item/servlet/477555?fr=aladdin
[2] http://www.runoob.com/servlet/servlet-first-example.html
[3] https://www.zhihu.com/question/21142149
 
posted @ 2018-01-07 22:51  purr  阅读(136)  评论(0编辑  收藏  举报