servlet 入门实战

在实际使用servlet的过程中,一般不推荐直接实现servlet接口,可以通过继承servlet接口的子类,重写其中的方法进行扩展开发,避免一些无用方法。
例如:直接继承HttpServlet

servlet 入门实战_第1张图片
servlet 入门实战_第2张图片
并且在servlet3.0之后,为了简化servlet开发,servlet 3.0提供了注解的方式简化servlet的配置。
例如:
servlet 入门实战_第3张图片
Servlet请求API-HttpServletRequest
设置参数编码
在这里插入图片描述
servlet 入门实战_第4张图片
servlet 入门实战_第5张图片
servlet 入门实战_第6张图片
在这里插入图片描述
相关API

package com.bjsxt.servlet;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

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

@WebServlet("/api.do")// 赋值给了 value  和  urlPatterns 等价
public class ServletApi  extends HttpServlet {

	private static final long serialVersionUID = 782338046693469415L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置处理请求数据的编码
		req.setCharacterEncoding("UTF-8");
		//doParam(req,resp);
		//doNetInfo(req,resp);
		forward(req,resp);
	}
	/**
	 * @Title: doParam
	 * @author: james  
	 * @date: 2020年6月30日 上午11:15:26 
	 * @Description: 处理请求参数
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 * @return: void
	 */
	protected void doParam(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//getParameter(参数名) : 根据参数名 获取请求参数对应的值
		System.out.println("文本:"+req.getParameter("username"));
		System.out.println("密码框值:"+req.getParameter("password"));
		System.out.println("单选:"+req.getParameter("sex"));
		System.out.println("下拉:"+req.getParameter("city"));
		System.out.println("复选:"+req.getParameter("like"));
		//getParameterValues(name) : 根据名称 获取对应的值  值是字符串数组  用于获取复选框的值
		String[] strs = req.getParameterValues("like");
		List<String> list = Arrays.asList(strs);
		System.out.println("复选:"+list);
		//getParameterMap() : 获取请求参数信息  将参数名作为key  参数值是字符串数组
		//复选框 在传递时 是一个name 对应多个值,为了兼容所以值使用字符串数组
		Map<String, String[]> parameterMap = req.getParameterMap();
		System.out.println(parameterMap);
		System.out.println("----------------------------");
		//getParameterNames() : 获取所有请求参数的名称
		Enumeration<String> names = req.getParameterNames();
		while(names.hasMoreElements()) {
			System.out.println(names.nextElement());
		}
		//getPart(name) : 根据名称 获取part 对应的数据信息 一般用于非文本信息数据 用于文件上传
		//getParts() : 获取所有的数据信息 
	}
	
	/**
	 * @Title: doNetInfo
	 * @author: james   
	 * @date: 2020年6月30日 上午11:35:58 
	 * @Description: 获取网络信息
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 * @return: void
	 */
	protected void doNetInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//getMethod()   获取请求方法 GET  POST  DELETE  PUT  等等
		System.out.println(req.getMethod());
		//getLocalPort() 获取端口
		System.out.println(req.getLocalPort());
		//getProtocol() 获取协议
		System.out.println(req.getProtocol());
		//getRequestURL() 获取请求的url
		System.out.println(req.getRequestURL());
		//getRequestURI() 获取资源路径
		System.out.println(req.getRequestURI());
		//获取请求头
		//请求数据类型
		System.out.println(req.getContentType());
		//req.getHeader(name)  获取指定的请求头 
		System.out.println(req.getHeader("Accept-Language"));
	}
	/**
	 * @Title: setEncoding
	 * @author: Mr.T   
	 * @date: 2020年6月30日 上午11:44:08 
	 * @Description: 设置处理请求的字符编码
	 * 			在servlet中,处理请求的数据只会处理一次,且tomcat 8.0以上 get请求按照UTF-8编码处理
	 * 			post请求按照默认的编码 : ISO-8859-1 处理,tomcat 8.0 以下get和post请求都使用 ISO-8859-1 处理
	 * 			如果请求参数有汉字,则使用setCharacterEncoding进行编码设置
	 * 			注意,设置编码一定要在getParameter方法前面进行设置
	 * 
	 * 
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 * @return: void
	 */
	protected void setEncoding(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
	}
	
	/**
	 * @Title: forward
	 * @author: james   
	 * @date: 2020年6月30日 上午11:56:05 
	 * @Description: 内部转发
	 * 				内部转发,是指当前程序不处理当前请求 而是将当前请求转发到下一个程序让其处理。
	 * 				这种形式可以实现跳转的效果的。但是不推荐使用。
	 * 				内部转发时,会将当前的request、response对象信息传递给指定的转发地址
	 * 				内部转发是服务器内部进行程序调用,所以浏览器上面的url地址不会发生改变
	 * 				由于内部转发浏览器上的url地址不会发生改变,那么一旦浏览器刷新,之前所有关联的
	 * 				业务代码会重复执行一次,这样会加大服务器压力,也可能造成数据异常。
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 * @return: void
	 */
	protected  void forward(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//getRequestDispatcher("需要将请求转发的地址")
		//forward(req,resp) :进行转发
		System.out.println("servlet api");
		req.getRequestDispatcher("servlet04.do").forward(req, resp);
	}
	/**
	 * @Title: doScope
	 * @author: james  
	 * @date: 2020年7月1日 上午9:06:23 
	 * @Description: 作用域相关方法
	 * 	什么是作用域:起作用的范围
	 * 	作用域对象:
	 * 		在Javaweb中,作用域分为4类:
	 * 		当前页面 :当前页面pageContext   page
	 * 		当前请求 : 一次请求  request 
	 * 		当前会话 :  一次会话  ,指客户端与服务器的多次应答。默认一次会话时间没有断开过的话是30分钟。每次会话开启服务器会给一个标识符给客户端
	 * 					客户端会将这个标识符下次请求时,带给服务器,这样同样的标识符的请求就是同一次会话。 session
	 * 		当前应用 : 每个应用程序,在启动的时候就会创建一个全局的容器,标识是当前应用的容器。这个容器有且只有一个  application
	 * 以上4个作用域,pageContext作用域只有JSP存在
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 * @return: void
	 */
	protected  void doScope(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//获取其他作用域对象
		//获取session
		HttpSession session = req.getSession();//每个请求都有个关联的session
		//获取application  
		ServletContext context = req.getServletContext();
		//作用域中公共方法
		//setAttribute(name, o) : 向作用域存放数据  K-V形式
		req.setAttribute("name", "韩梅梅");
		req.setAttribute("age", 18);
		//getAttribute(name) : 根据name 从作用域中获取值
		System.out.println(req.getAttribute("name"));
		//getAttributeNames() : 获取作用域中所有的name值
		Enumeration<String> attributeNames = req.getAttributeNames();
		System.out.println("----------------------------");
		while(attributeNames.hasMoreElements()) {
			System.out.println(attributeNames.nextElement());
		}
		//删除作用域中的值
		req.removeAttribute("name");
	}
}

Servlet响应API-HttpServletResponse
相关API

/**
	 * @Title: doRespHeader
	 * @author: Mr.T   
	 * @date: 2020年7月1日 上午9:25:28 
	 * @Description: 响应头相关方法
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 * @return: void
	 */
	protected  void doRespHeader(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//设置自定义的响应头
		resp.addHeader("zhangsan", "李四");
		//设置响应的编码
		resp.setCharacterEncoding("UTF-8");
		//设置响应的数据的类型
		resp.setContentType("text/html;charset=utf-8");
		//获取响应流中字符串
		//PrintWriter writer = resp.getWriter();
		//writer.print("Hello  客户端");
		//writer.flush();
		//获取响应数据的字节流
		//字节流  和  字符流区别 :字节流处理的数据单位是字节   字符流处理数据的单位是字符
		/**
		 *  一般而言  字符流适合处理文本数据
		 *  字节流适合处理文件数据: 音频 视频 其他文件等等。
		 */
		ServletOutputStream os = resp.getOutputStream();
		String str = "不要歧视我,我是字符流的爹!";
		os.write(str.getBytes());
		os.flush();
	}

	/**
	 * @Title: redirect
	 * @author: james  
	 * @date: 2020年7月1日 上午9:49:07 
	 * @Description: 重定向 
	 * 	是指服务器通知浏览器,重新请求的地址。
	 * 	这种方式也能实现跳转的效果
	 * @param req
	 * @param resp
	 * @throws ServletException
	 * @throws IOException
	 * @return: void
	 */
	protected  void redirect(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//通知浏览器  重定向到 index.html 
		//通知浏览器 你去请求 index.html 这个地址
		resp.sendRedirect("https://www.baidu.com");
	}

重定向和内部转发的比较

重定向和内部转发都能实现页面刷新。
但是重定向是浏览器重新请求,内部转发是上服务器内部让新的程序协助原程序处理当前的请求。相较而言,重定向是多次请求,而内部转发是一次请求。重定向会产生多个请求对象,内部转发则是同一个请求对象,而request对象又是一个作用域对象,使用内部转发,则多个程序是同一个request作用域,如果参数想要传递,则可以利用request作用传递参数,但是重定向每次都是新的request对象,所以没有办法利用作用域传递参数。

由于内部转发是同一个请求,浏览器的URL不会发生变化,刷新浏览器时之前相关业务代码会重新执行一次,对服务器性能会造成一定额外压力,且易造成数据异常的问题。
但是重定向是浏览器进行二次请求,当前浏览器的URL地址会发生改变,如果刷新URL,之前的业务代码不会执行,只会执行与当前URL相关的代码。

下方上图 简单理解下:
servlet 入门实战_第7张图片
servlet 入门实战_第8张图片


感谢来自bjsxt的唐老师的讲解,谢谢老师。

你可能感兴趣的:(web,servlet)