首先用idea创建一个project,步骤如下:
1.在idea中点击file-new-project,出现如下图所示:
注意勾选上web application,然后点击next
2.给project命名为MyFirstServlet,点击finish:
3.此时project创建成功,在src文件上点击右键new-package,将package命名为servlet,点击ok:
4.在servlet这个包上点击右键new-java class,将这个类命名为HelloServlet:
5.最后project创建完成,目录如下:
代码内容
1.project创建成功之后,打开WEB-INF下的web.xml文件,文件内如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--注册servlet-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/servlet/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
上面是一个最简单的web.xml的内容,但是包含了web.xml中很重要的知识点。配置完这个xml文件,首先我们要知道一个web应用的这个web.xml配置文件的作用。通俗的讲,web.xml就是给jsp页面定制名称和指定其URL。用<servlet>
定制名称,用<servlet-mapping>
映射该名称的URL,因为如上代码中所示:<servlet>
和<servlet-mapping>
中的<servlet-name
>必须是一致的,因为两者是映射关系。
然后我们需要知道的是web.xml的加载过程,加载过程而已总结为四个步骤<context-param>
-> <listener>
-> <filter>
-> <servlet>
:
- 当启动容器时,首先会读取project中的web.xml里的配置,读取的时候配置中的
<listener>
和<content-param>
- 然后容器创建一个ServletContent,整个web项目都将共享这个上下文
- 容器以
<content-param>
的name作为键,value作为值,将其转化为键值对,存入到ServletContent - 容器创建
<listener>
当中的类实例,根据class的类路径listener-class来创建监听 - 最后容器会读取
<filter>
,根据指定的类路径来实例化过滤器。 - 以上都是在WEB项目还没有完全启动起来的时候就已经完成了的工作。如果系统中有Servlet,则Servlet是在第一次发起请求的时候被实例化的,而且一般不会被容器销毁,它可以服务于多个用户的请求。
看到了上面代码中出现了两个配置的标签<servlet>
和<servlet-mapping>
,应该看出来了吧<servlet>
和<servlet-mapping>
里面的<servlet-name>
是一样的,为什么是一样的呢?
<servlet-name>
是我们注册servlet的名字,这个一般和我们程序中的类名相关。<servlet-class>
是指向我们要注册的类地址,也就是对应的class文件,这个写的时候要带上类所在的包名。<servlet-mapping>
用来配置注册servlet的访问路径(即浏览器的访问地址),其实就是上面注册的sevlet的一个映射,它里面的<url-pattern>
就是其访问路径。2.HelloServlet的代码内容:
package servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by lizhi on 2016-11-02.
*/
//继承HttpServlet
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("处理get请求!");
// PrintWriter给浏览器获得对象
PrintWriter out = response.getWriter();
// 指定输出的文件类型
response.setContentType("text/html;charset=utf-8");
out.println("<strong>HelloServlet</strong>");
}
@Override
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
System.out.println("处理post请求!");
// PrintWriter给浏览器获得对象
PrintWriter out = response.getWriter();
// 指定输出的文件类型
response.setContentType("text/html;charset=utf-8");
out.println("<strong>HelloServlet</strong>");
}
}
如代码该类中重写了servlet的doGet()和doPost()两个方法,写了System.out.println()来在控制台输出查看方法的调用顺序。由于是要从浏览器端获取请求,需要用到PrintWriter给浏览器获得对象,并且使用setContentType来指定是输出文件类型,不然在浏览器端出现中文或者html标签会导致显示不出的问题,然后在浏览器端用out输出我们想要的内容。
3.index.jsp的代码内容
<%--
Created by IntelliJ IDEA.
User: hspcadmin
Date: 2016-11-02
Time: 10:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>servlet第一个小例子</h1>
<hr>
<a href="servlet/HelloServlet">get方式请求helloservlet</a>
<form action="servlet/HelloServlet" method="post">
<input type="submit" value="post方式请求helloservlet">
</form>
</body>
</html>
在a标签中采用的是get方式请求,在form表单中采用post方式请求,此时第一个servlet编写完成。
运行第一个servlet
配置tomcat:
配置依赖:
输出
控制台输出:
浏览器端输出:
此刻第一个servlet程序就编写完成啦!
补充
在HelloServlet中,代码PrintWriter out = response.getWriter();此处我们用getWriter()来返回一个PrintWriter Object,但为什么用response呢,为什么不new一个PrintWriter呢?此处就涉及到一个“流”的概念。PrintWriter out = response.getWriter()的意思是获取到流,而非response这个实体,拿到了PrintWriter 这个字符流,然后对流进行操作,你做的操作的结果应该想要反映到response对应的位置,于是你要拿到属于response的流,而不是new一个出来。