Servlet入门

Servlet概述

1、什么是Servlet
  • 接受请求数据
  • 处理请求
  • 完成响应
    在这里插入图片描述
2、实现Servlet的方式
  • 实现Servlet有三种方式

  • 实现:javax.servlet.Servlet 接口;

  • 继承:javax.servlet.GenericServlet 类;

  • 继承:javax.servlet.http.HttpServlet 类;

  • 在这里插入图片描述

3、生命周期
  • 生命周期方法:
    • void init(ServletConfig):出生之后;
    • void service(ServletRequest request , ServletResponse response) :每次处理请求都会被调用
    • void destroy(): 临死之前;
  • 特性:
    • 单例 : 一个类只有一个对象,当然可能存在多个Servlet类
    • 属于线程不安全 , 效率高
  • Servlet类由开发者编写,对象有服务器创建,并由服务器调用相应的方法;
4、ServletConfig

在这里插入图片描述

GenericServlet

HttpServlet

在这里插入图片描述

在这里插入图片描述

  • protected void doGet(HttpServletRequest req,HttpServletResponse resp)throws ServletException,
    IOException
  • protected void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,
    IOException

Servlet细节

1、Servlet与线程安全
  • 不要在Servlet中创建对象!创建局部变量即可
  • 可以创建无状态成员
  • 可以创建有状态成员,但状态必须为只读的
2、让服务器启动时就创建Servlet

在这里插入图片描述

3、<url–pattern>

在这里插入图片描述

  • 在这里插入图片描述
4、web.xml文件的(继承)

在这里插入图片描述

  • 404 -> default
    • org.apache.catalina.servlets.DefaultServlet
  • jsp -> jsp
    • org.apache.jasper.servlet.JspServlet
5、Servlet与反射
  • 通过web.xml中类名的路径反射创建实例

ServletContext

  • 一个项目只有一个ServletContext对象
  • 可以在N多个Servlet中获取这唯一的对象,使他可以给多个Servlet传递数据
  • 与天地同寿!!! 这个对象在tomcat启动时就创建,在Tomcat关闭时才会死去
1、ServletContext概述

在这里插入图片描述

2、获取ServletContext

在ServletContext中获取ServletContext对象

  • ServletConfig类的getServletContext()可以获取ServletContext对象

    • 在void(ServletConfig servletConfig)中:ServletContext servletContext = servletConfig.getServletContext();
  • 在GenericeServlet或HttpServlet中获取ServletContext对象

    • GenericeServlet类有getServletContext(),所以可以直接使用this.getServletContext()来获取

    在这里插入图片描述

3、域对象功能

在这里插入图片描述

  • 存储一个对象:public void setAttribute(String name,Object object);
  • 获取ServletContext中的数据:public Object getAttribute(String name);
  • 移除ServletContext中的域属性:public void removeAttribute(String name);
  • 获取所有属性的名称:public Enumeration getAttributeNames();

在这里插入图片描述

4、获取应用初始化参数

在这里插入图片描述

在这里插入图片描述

5、获取资源的相关方法
1、获取真实路径

在这里插入图片描述

/**
		 *  	得到盘符路径
		 *  	D:\WebStorm\TomCat\apache-tomcat-9.0.34\webapps\Web\login.html
		 */
		String path = this.getServletContext().getRealPath("/login.html");
		System.out.println(path);
2、获取资源流

在这里插入图片描述

/**
		 *	 获取资源路径, 在创建输入流对象
		 */
		InputStream input = this.getServletContext().getResourceAsStream("/login.html");
3、获取指定目录下所有的资源路径

在这里插入图片描述

/**
		 * 	获取当前路径下所有资源的路径
		 * 	[/WEB-INF/lib/, /WEB-INF/classes/, /WEB-INF/web.xml]
		 */
		Set<String> paths = this.getServletContext().getResourcePaths("/WEB-INF");
		System.out.println(paths);
  • 这些方法必须从“/”开头
6、练习:访问量统计

在这里插入图片描述

public class AServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		/**
		 * 	获取servletContext对象
		 * 	从ServleContext对象中获取名为count的属性
		 * 	如果存在:给访问量加1,然后在保存回去
		 * 	如果不存在:说明是第一次访问,向ServletContext中保存名为count的属性,值为1
		 */
		
		ServletContext application = this.getServletContext();
		Integer count =(Integer)application.getAttribute("count");
		
		if(count == null) {
			application.setAttribute("count", 1);
		}else {
			application.setAttribute("count", count + 1);
		}
		
		/**
		 * 	向浏览器输出
		 * 	使用相应对象
		 */
		PrintWriter pw = resp.getWriter();
		pw.print("<h1>" +  count  + "</h1>");
		
	}

获取类路径下的资源

  • Class
  • ClassLoader

在这里插入图片描述

在这里插入图片描述

BaseServlet

在这里插入图片描述

public abstract class BaseServlet extends HttpServlet {
	@Override
	public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		/**
		 * 	获取参数,用来识别用户想请求的方法
		 * 	然后判断是哪一个方法,是哪一个就调用哪一个
		 */
		String methodName = req.getParameter("method");
		
        if(methodName == null || methodName.trim().isEmpty()) {
			throw new RuntimeException("您没有传递method参数!无法确定您想要调用的方法");
		}
        
		/**
		 * 	得到方法名称,通过方法名在得到Method类的对象
		 * 		需要的到Class,然后调用他的方法进行查询!得到Method
		 * 		要查询当前类的方法,所以需要得到当前类的Class
		 */
		Class c = this.getClass(); //得到当前class对象
		Method method = null;
		try {
			method = c.getMethod(methodName, HttpServletRequest.class , HttpServletResponse.class);
		} catch (Exception e) {
			throw new RuntimeException("您要调用的方法" + methodName + "(HttpServletRequest,HttpServletResponse),它不存在");
		} 
		/**
		 * 	调用method表示的方法
		 */
		try {
			method.invoke(this, req,resp); // this.addUser(req,resp) ,method(this,req,resp)
		} catch (Exception e) {
			System.out.println("您要调用的方法:" +methodName + ",它内部抛出了异常!");
			throw new RuntimeException(e);
		}
		
	}
}
  • 转发:req.getRequestDispatcher("/xxx").forward(req, resp); 不改变地址位置
  • 重定向:resp.sendRedirect(req.getContextPath()+"/xxx.jsp"); 改变地址位置
package cn.itcast.servlet;

import java.io.IOException;
import java.lang.reflect.Method;

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

public abstract class BaseServlet extends HttpServlet {
	@Override
	public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		/**
		 * 	获取参数,用来识别用户想请求的方法
		 * 	然后判断是哪一个方法,是哪一个就调用哪一个
		 */
		String methodName = req.getParameter("method");
		if(methodName == null || methodName.trim().isEmpty()) {
			throw new RuntimeException("您没有传递method参数!无法确定您想要调用的方法");
		}
		
		/**
		 * 	得到方法名称,通过方法名在得到Method类的对象
		 * 		需要的到Class,然后调用他的方法进行查询!得到Method
		 * 		要查询当前类的方法,所以需要得到当前类的Class
		 */
		Class c = this.getClass(); //得到当前class对象
		Method method = null;
		try {
			method = c.getMethod(methodName, HttpServletRequest.class , HttpServletResponse.class);
		} catch (Exception e) {
			throw new RuntimeException("您要调用的方法" + methodName + "(HttpServletRequest,HttpServletResponse),它不存在");
		} 
		/**
		 * 	调用method表示的方法
		 */
		try {
			String result = (String)method.invoke(this, req,resp); // this.addUser(req,resp) ,method(this,req,resp)
			/**
			 * 	获取请求处理方法执行后返回字符串 ,它表示转发或重定向的路径!
			 * 	帮它完成转发或者重定向
			 */
			/**
			 * 	如果用户返回的是字符串为null,或"",那什么也不用做
			 */
			if(result == null || result.trim().isEmpty()) {
				return ;
			}
			/**
			 * 	查看返回的字符串是否包含冒号,如果没有默认为转发
			 * 	如果有,使用冒号分割字符串,得到前缀和后缀
			 * 	其中前缀如果是f,表示转发,如果是r表示重定向,后缀就是要转发或者重定向的路径
			 */
			if(result.contains(":")) {
				//使用冒号分割字符串,得到前缀和后缀
				int index = result.indexOf(":"); // 获取冒号的位置
				String s = result.substring(0, index);// 截取出前缀,表示操作
				String path = result.substring(index);//截取出后缀,表示路径
				if(s.equalsIgnoreCase("r")) {//如果前缀是r,那么重定向
					resp.sendRedirect(req.getContextPath() + path);
				}else if (s.equalsIgnoreCase("f")) {//如果前缀是f,那么转发
					req.getRequestDispatcher(path).forward(req, resp);
				}else {
					throw new RuntimeException("您指定的操作" + s + ",当前版本还不支持!");
				}
				
			}else {// 没有冒号 默认为转发
				req.getRequestDispatcher(result).forward(req, resp);
			}
			
			
		} catch (Exception e) {
			System.out.println("您要调用的方法:" + methodName + ",它内部抛出了异常!");
			throw new RuntimeException(e);
		}
		
	}
}

;
}else if (s.equalsIgnoreCase(“f”)) {//如果前缀是f,那么转发
req.getRequestDispatcher(path).forward(req, resp);
}else {
throw new RuntimeException(“您指定的操作” + s + “,当前版本还不支持!”);
}

		}else {// 没有冒号 默认为转发
			req.getRequestDispatcher(result).forward(req, resp);
		}
		
		
	} catch (Exception e) {
		System.out.println("您要调用的方法:" + methodName + ",它内部抛出了异常!");
		throw new RuntimeException(e);
	}
	
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值