Servlet

1. Servlet 简介

JavaSE:
java标准版本,Sun公司为java程序员提供的一套基础类库。这套类库主要包括,基本语法、异常、IO、集合、反射、线程等。

JavaEE:
java企业版,Sun公司为java程序员准备的另一套庞大的类库,帮助程序员完成企业级项目开发。(高效、稳定)

Servlet:
是JavaEE13大子规范中的一个规范(接口:解耦合、可插拔),主要功能在于交互式的浏览和生成数据,用于开发动态web 的一门技术。

2. Servlet 实现

2.1 实现Servlet 接口

(直接实现Servlet 接口的方式,实际开发并不常用,作为了解)

2.1.1 创建类并实现Servlet 接口

public class HelloServlet implements Servlet{
	// 若希望在销毁时刻执行一段特殊代码,编写在此处,自动被容器调用,且只执行一次
	// destory方法执行的时候,Servlet对象还没有被销毁,而是即将被销毁
	@Override
	public void destroy() {
	}
	// 为子类提供ServletConfig方法
	@Override
	public ServletConfig getServletConfig() {
		return null;
	}
	@Override
	public String getServletInfo() {
		return null;
	}
	// 若希望初始化时执行一段特殊程序,可以编写在此方法内,会自动被调用,且只执行一次
	// 注意:init方法执行时,Servlet对象已经被创建好了
	// ServletConfig:是一个Servlet 对象的配置信息对象,web.xml文件中配置的信息,一个Servlet对象对应一个ServletConfig对象
	@Override
	public void init(ServletConfig config) throws ServletException {
	}
	// 将业务逻辑重写到该方法中,请求处理、完成响应。
	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		// 请求分发
		HttpServletRequest httpServletRequest = (HttpServletRequest)req;
		String method = httpServletRequest.getMethod();
		if("GET".equals(method)){
			System.out.println("GET");
		}else {
			System.out.println("POST");
		}
	}
}

2.1.2 映射

Web.xml 文件中配置servlet 映射

  <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>com.chengyu.servlet.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>

2.1.3 JSP界面访问Servlet

<form action="hello" method="POST">
	<input type="submit"/>
</form>

2.2 继承HttpServlet 类

2.2.1 创建类并继承HttpServlet 类

public class HelloHttpServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("HelloHttpServlet doGet()");
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("HelloHttpServlet doPost()");
	}
}

2.2.2 映射

  <servlet>
    <servlet-name>helloHttpServlet</servlet-name>
    <servlet-class>com.chengyu.servlet.HelloHttpServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>helloHttpServlet</servlet-name>
    <url-pattern>/hello2</url-pattern>
  </servlet-mapping>

2.2.3 JSP界面访问Servlet

<form action="hello2" method="POST">
	<input type="submit"/>
</form>

2.3 补充

1)若希望在web服务器启动阶段实例化Servlet对象,需要在web.xml中配置如下内容:

  <servlet>
    <servlet-name>helloServlet</servlet-name>
    <servlet-class>my.service.factory.myServlet</servlet-class>
  	
  	<load-on-startup>N</load-on-startup>
  </servlet>

N 处设置自然数,越小级别越高,可直接设置为 1;

2)web.xml文件只能有一个,服务器启动阶段被解析;
3)tomcat服务器是一个实现了Servlet规范和JSP规范的容器。

3. Servlet 生命周期

用户发送URL 请求,web 容器截取到请求路径后,在上下文中查找对应的Servlet 对象;

若没有,则根据web.xml 文件中的配置信息,通过反射技术调用Servlet 类的无参构造器,完成Servlet 对象的创建,web 容器调用Servlet 对象的init() 进行初始化,调用 service() 提供服务;

若已存在,web 容器直接调用 Servlet 对象的 service() 提供服务;

web 容器关闭、webapp 重新部署、该Servlet 对象长时间没有再次被访问的情况下,web 容器会将Servlet 对象销毁,销毁前调用该对象的 destory() 完成销毁前的准备。

4. ServletContext 对象

web 容器启动的时候,会创建一个ServletContext 对象,它代表了当前web 应用,服务关闭时被销毁。

4.1 servlet 之间共享数据

public class ServletContext1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String name = "chengyu";
        context.setAttribute("name",name);
    }
}
public class ServletContext2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String name = (String) context.getAttribute("name");
        System.out.println(name);
    }
}

4.2 获取xml 中初始化参数

web.xml

<context-param>
        <param-name>url</param-name>
        <param-value>www.baidu.com</param-value>
    </context-param>

    <servlet>
        <servlet-name>paramServlet</servlet-name>
        <servlet-class>com.chengyu.controller.ContextTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>paramServlet</servlet-name>
        <url-pattern>/getparam</url-pattern>
    </servlet-mapping>
public class ContextTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String url = context.getInitParameter("url");
        System.out.println(url);
    }
}

4.3 请求转发

public class ContextTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
	 	context.getRequestDispatcher("/servlet2").forward(req, resp);
    }
}

ServletContext 的请求转发应用并不多,请求转发的详细介绍参考 5.2。

4.4 读取资源文件

WEB-INF/db.properties

username=root
password=tiger
public class ContextTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        InputStream is = context.getResourceAsStream("/WEB-INF/db.properties");

        Properties properties = new Properties();
        properties.load(is);

        String username = properties.getProperty("username");
        System.out.println(username);
    }
}

5. 请求信息 HttpServletRequest

5.1 获取页面参数

1)页面

<form action="helloApi" method="POST">
	姓名:<input type="text" name="username"><br/>
	年龄:<input type="text" name="userage"><br/>
	技术:<input type="checkbox" name="study" value="java">java 	 <input type="checkbox" name="study" value="C#">C# <br/>
	<input type="submit"/>
</form>

2)Web.xml

<servlet>
    <servlet-name>HttpServletRequestApi</servlet-name>
    <servlet-class>com.chengyu.servlet.HttpServletRequestAPI</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HttpServletRequestApi</servlet-name>
    <url-pattern>/helloApi</url-pattern>
  </servlet-mapping>

3)获取参数

	// 获取请求参数
	System.out.println("username ⇒ " + req.getParameter("username"));
	System.out.println("userage ⇒ " + req.getParameter("userage"));
	// 获取请求参数(多个值)
	String[] study = req.getParameterValues("study");
	System.out.println("study ⇒ " + Arrays.asList(study));

补充:
POST 请求时,会出现中文乱码,解决方法如下

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
	System.out.println("========doPost=======");
	req.setCharacterEncoding("UTF-8");
	// 获取请求参数
	System.out.println("username ⇒ " + req.getParameter("username"));
}

5.2 请求转发

Servlet1 调取Servlet2
1)创建Servlet1

public class Servlet1 extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("====== Servlet1  doGet ======");
		String username = req.getParameter("username");
		System.out.println("Servlet1 获取用户名:" + username);
		req.setAttribute("key", "OK");
//		RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
//		requestDispatcher.forward(req, resp);
		req.getRequestDispatcher("/servlet2").forward(req, resp);
		// 也可转发到页面		
//		req.getRequestDispatcher("/index.jsp").forward(req, resp);
	}
}

2)创建Servlet2

public class Servlet2 extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("====== Servlet2  doGet ======");
		String username = req.getParameter("username");
		String key = (String)req.getAttribute("key");
		System.out.println("Servlet2 获取Servlet1参数:" + key);
	}
}

3)Web.xml

  <servlet>
    <servlet-name>Servlet1</servlet-name>
    <servlet-class>com.chengyu.servlet.Servlet1</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Servlet1</servlet-name>
    <url-pattern>/servlet1</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>Servlet2</servlet-name>
    <servlet-class>com.chengyu.servlet.Servlet2</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Servlet2</servlet-name>
    <url-pattern>/servlet2</url-pattern>
  </servlet-mapping>

4)index1.jsp

	<body>
		<form action="servlet1" method="Get">
			姓名:<input type="text" name="username"><br/>
			<input type="submit"/>
		</form>
	</body>

5)URL
http://localhost:8080/WebProjectTest04/index1.jsp

特点
① 浏览器地址栏不变;
② 是一次请求;
③ 共享Reqest 域中的数据;
可以转发到WEB-INF 目录下(WEB-INF 目录不可直接用浏览器访问)

5.3 补充路径问题 ※

【.】:当前目录
【…】:上一级目录
【/】:将路径映射到【WebContent】目录下
页面访问Servlet 时,不用加【/】,因为页面在【WebContent】下。例,action=“servlet1”
Java 中访问Servlet 时,用加【/】。例,req.getRequestDispatcher("/servlet1").forward(req, resp);

Web端解析到端口
如,<… href="/"> 浏览器解析为:http://localhost:8080/

服务器端解析到工程
如servletContext.getReadPath("/"):服务器端解析为:http://localhost:8080/WebProjectTest04
特例:response.sendRedirect("/"),虽然在服务器端,但将斜杠发送给浏览器解析,得到http://localhost:8080/

相对路径在工作时会参照当前浏览器地址进行跳转,如果设置了base标签,则会参照地址base标签设置的地址。

<head>
	<base href="http://localhost:8080/WebProjectTest04/a/b/c.jsp">
</head>
<body>
	<a href="../../index.jsp">返回</a>
</body>

http://localhost:8080/WebProjectTest04/a/b/c.jsp
…/…/index.jsp

http://localhost:8080/WebProjectTest04/index.jsp
注意:【c.jsp】不算地址

6. 响应信息 HttpServletResponse

6.1 设置响应信息

字节流getOutputStream():下载,传递二进制数据;
字符流getWrite():回传字符串(常用);
注意:两者不能同时使用。

public class HttpServletResponse extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)
			throws ServletException, IOException {
		PrintWriter writer = resp.getWriter();
		writer.write("response information!!!");
	}
}

6.2 乱码问题

req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=utf-8");

6.3 请求重定向

客户端给服务器发请求,服务器提供新地址,然后去新地址访问。

public class Response1 extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("====== HttpServletResponse1 ======");
		// 重定向状态吗
//		resp.setStatus(302);
//		resp.setHeader("Location", "http://localhost:8080/WebProjectTest04/response2");
		resp.sendRedirect("http://localhost:8080/WebProjectTest04/response2");
	}
}
public class Response2 extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.getWriter().write("====== HttpServletResponse2 ======");
	}
}

特点
① 浏览器地址发生变化;
② 发生两次请求;
③`不共享response 数据;
④ 不能访问WEB-INF目录资源;
⑤ 可以访问当前工程以外的资源。

7. 过滤器 Filter

实现Filter 接口:
利用过滤器处理乱码

public class FilterDemo01 implements Filter {

    // 初始化:Web服务器启动时调用
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init");
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("doFilter");
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");
		// 过滤器继续执行
        filterChain.doFilter(req,resp);
    }
    // 销毁:Web服务器关闭时调用
    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

有乱码的代码:

public class ShowServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloHttpServlet doGet()");
        resp.getWriter().write("你好");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloHttpServlet doPost()");
    }
}

web.xml

    <filter>
        <filter-name>demo01</filter-name>
        <filter-class>com.cheng.FilterDemo01</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>demo01</filter-name>
        <!--过滤的请求-->
        <url-pattern>/servlet/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>com.cheng.ShowServlet</servlet-class>
    </servlet>
    <!--走过滤器-->
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/servlet/show</url-pattern>
    </servlet-mapping>
    <!--不走过滤器-->
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/show</url-pattern>
    </servlet-mapping>

8. 监听器 Listener

实现监听器接口:

public class ListenerDemo implements HttpSessionListener {
    // 创建Session 监听:一旦创建Session 就会触发一次这个事件
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext context = se.getSession().getServletContext();
        Integer count = (Integer) context.getAttribute("OnlineCount");
        if(count == null){
            count = new Integer(1);
        }else {
            int countInt = count.intValue();
            count = new Integer(countInt ++);
        }
        context.setAttribute("OnlineCount",count);
    }
    // 销毁Session 监听:
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
    }
}

index.jsp

    <listener>
        <listener-class>com.cheng.ListenerDemo</listener-class>
    </listener>

页面

<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <h1><%= this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></h1>
  </body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值