【JavaEE】Servlet丶ServletContext丶Response丶Request

1.Servlet

1.1 web.xml
<!-- 默认首页,从上到下依次查找,如果找到则显示,找不到则继续往下找 -->
<welcome-file-list>
	<welcome-file>index.html</welcome-file>
	<welcome-file>index.htm</welcome-file>
	<welcome-file>index.jsp</welcome-file>
	<welcome-file>default.html</welcome-file>
	<welcome-file>default.htm</welcome-file>
	<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

<servlet>
	<!-- servlet名称 -->
	<servlet-name>MyServlet</servlet-name>
	<!-- Servlet的完整路径 -->
	<servlet-class>com.servlet.MyServlet</servlet-class>
	<!-- 初始化变量,可以在Servlet的inti()被访问 -->
	<init-param>
		<param-name>var</param-name>
		<param-value>我是变量值</param-value>
	</init-param>
	
	<!-- 在Tomcat启动时就创建本Servelt,值越小优先级越大 -->
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<!-- 这里的servlet名称对应上面的servlet名称-->
	<servlet-name>MyServlet</servlet-name>
	<!-- 浏览器访问servlet的url -->
	<!-- 多个url-pattern从上到下查找 -->
	
	<!-- 1.完全匹配方式,必须以/开头 -->
	<url-pattern>/MyServlet</url-pattern>
	
	<!-- 2.目录模糊匹配,必须以/开头,这里只需输入/ABC就能匹配,后面可以输入任何东西 -->
	<url-pattern>/ABC/*</url-pattern>
	
	<!-- 3.后缀名模糊匹配,不能使用/开头,以.jsp结尾的url都能匹配 -->
	<url-pattern>*.jsp</url-pattern>
	
	<!-- 4.任意匹配,所有url都能匹配到 -->
	<url-pattern>/</url-pattern>
</servlet-mapping>
1.2 HttpServlet
package com.servlet;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//Servlet由Tomcat创建,默认是首次访问本Servlet创建
public class MyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;


	//init()在Servlet创建时访问,因为Servlet只会创建一次,所以init()也只会被访问一次
	public void init(ServletConfig config) throws ServletException {
		//获取web.xml的servlet-name
		String servletName=config.getServletName();
		//获取web.xml的init-param
		String var=config.getInitParameter("var");
		ServletContext sc= config.getServletContext();
		
		System.out.println(servletName);
		System.out.println(var);
	}

	//Tomcat关闭时会执行一次
	public void destroy() {
		
	}

	//每次请求都会访问该方法
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("我是service");
	}

	//service()方法根据get请求访问doGet()方法
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("我是doGet");
	}

	//service()方法根据post请求访问doPost()方法
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("我是doPost");
	}
}
1.3登录例子
  • login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
	<form action="/Web01/LoginServlet" method="post">
		用户名:<input type="text" name="username"><br> 
		密码:<inputtype="password" name="password"><br> 
		<input type="submit" value="登录">
	</form>
</body>
</html>
  • LoginServlet
package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;

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

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import com.domain.User;
import com.util.C3P0Util;

public class LoginServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//设置请求和响应的编码
		response.setContentType("text/html;charset=utf-8");
		request.setCharacterEncoding("utf-8");
		PrintWriter out = response.getWriter();
		
		//获取参数值
		String username=request.getParameter("username");
		String password=request.getParameter("password");

		//构建sql语句
		String sql="select * from user where username=? and password=?";
		
		//执行查询
		QueryRunner qr=new QueryRunner(C3P0Util.getDataSource());
		User user=null;
		try {
			user= qr.query(sql, new BeanHandler<>(User.class),username,password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		//根据查询结果判断安是否登录成功
		if(user==null) {
			out.print("登录失败!用户名与密码不匹配!!!");
		}else {
			out.println("<h1>登录成功</h1>");
			out.print(user);
		}

	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

2.ServletContext

ServletContext是Web应用的上下文对象,封装了有关应用的信息,一个Web应用只有一个ServletContext,随着项目启动而存在,随着项目停止而销毁。

2.1 获取ServletContext对象
//1.使用Servlet自身对象获取ServletContext
ServletContext context= this.getServletContext();
//2.使用request获取ServletContext
ServletContext context=request.getServletContext();
2.2 获取web.xml全局变量
  • web.xml
<web-app>
  <!-- 在web-app节点下定义全局变量 -->
  <context-param>
  	<param-name>globalVar</param-name>
  	<param-value>我是全局变量</param-value>
  </context-param>
</web-app>
  • ContextServletServlet
public class ContextServletServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//在Servlet中可以直接获取ServletContext对象
		ServletContext context= this.getServletContext();
		//获取web.xml全局变量
		String value=context.getInitParameter("globalVar");
		System.out.println(value);
	}
2.3 获取物理路径
//使用Servlet自身对象获取ServletContext
ServletContext context= this.getServletContext();

//getRealPath()参数是相对与网站的路径,按照发布到Tomcat中的路径为准,与Eclipse文件结构无关
String realPath=context.getRealPath("WEB-INF/classes/c3p0-config.xml");
System.out.println(realPath);
2.4 域对象
	//ServletContext域对象存储的数据可以被所有Web动态资源访问(共享)
	//把数据online_count存放到ServletContext中
	context.setAttribute("online_count", 0);
	
	//从ServletContext中取出数据online_count
	int count=(int)context.getAttribute("online_count");

3. Response

3.1 重定向
  • 重定向是来回两次请求响应
  • 地址栏会改变
  • 重定向会先执行sendRedirect()后面的代码再跳转
  • 可以重定向站外资源
	//重定向方式1
	//设置302状态码
	response.setStatus(302);
	//设置响应头的Location值
	response.setHeader("Location", "http://www.baidu.com");
		
	//重定向方式2
	//重定向中以/开头是相对于服务器的,所以需要手动加上网站名称
	response.sendRedirect("/Web02/TestServlet");

	//等待5秒后跳转
	response.setHeader("refresh", "5;url=http://www.baidu.com");
3.2 设置字符编码防止乱码
	//设置字符串编码
	response.setCharacterEncoding("UTF-8");
	//设置文件类型和字符编码,要在输出内容前设置编码才生效
	response.setContentType("text/html;charset=UTF-8");
	
	PrintWriter out = response.getWriter();
	out.print("你好");
3.3 文件下载
	// 获取客户端传递过来的要下载的文件名
	String filename = request.getParameter("filename");
	
	// 解决get请求的中文乱码
	filename = new String(filename.getBytes("ISO-8859-1"), "UTF-8");
	
	// 设置文件的MIME
	response.setContentType(this.getServletContext().getMimeType(filename));

	/* ↓ ↓ ↓兼容下载文件中文名乱码↓ ↓ ↓ */
	String encodeFilename="";
	String userAgent = request.getHeader("User-Agent");
	if (userAgent.indexOf("MSIE")!=-1 || userAgent.indexOf("Trident")!=-1 || userAgent.indexOf("Edge")!=-1 ) {
		// IE浏览器
		encodeFilename = URLEncoder.encode(filename, "utf-8").replace("+", " ");				
	} else if (userAgent.contains("Firefox")) {
		// 火狐浏览器			
		encodeFilename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";
	} else {
		// 其它浏览器(IE10+,Edge,谷歌测试都成功)	,空格在转码时会变成+,所以需要替换回去	
		encodeFilename = URLEncoder.encode(filename, "utf-8").replace("+", " ");
	}		
	/* ↑ ↑ ↑ 兼容下载文件中文名乱码 ↑ ↑ ↑ */

	// 告知浏览器下载的附件和文件名
	response.setHeader("Content-Disposition", "attachment;filename=" + encodeFilename);

	// 获取文件的物理路径
	String realPath = this.getServletContext().getRealPath("/imgs/" + filename);

	// 把文件写出到客户端
	BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));
	OutputStream os = response.getOutputStream();
	int len;
	byte[] bs = new byte[1024];
	while ((len = bis.read(bs)) != -1) {
		os.write(bs, 0, len);
	}
	os.close();
	bis.close();

4.Request

4.1 获取请求行信息
	//地址栏网址:http://localhost:6060/Web03/RequestServlet?key=name&value=zhangsan
	
	//  GET
	String method=request.getMethod();
	//  http://localhost:6060/Web03/RequestServlet
	StringBuffer url=request.getRequestURL();	
	//  /Web03/RequestServlet
	String uri=request.getRequestURI();
	//  /Web03
	String contextPath=request.getContextPath();
	//  /RequestServlet
	String servletPath=request.getServletPath();	
	//  key=name&value=zhangsan
	String queryString=request.getQueryString();
	
	//获取客户端的IP地址 
	String ip=request.getRemoteAddr();
	//获取客户端的主机名
	String host=request.getRemoteHost();
	//获取客户端的端口号
	int port=request.getRemotePort();
4.2 获取请求头信息
	// 获取浏览器信息
	String userAgent = request.getHeader("User-Agent");
	if (userAgent.indexOf("MSIE") != -1 || userAgent.indexOf("Trident") != -1 || userAgent.indexOf("Edge") != -1) {
		System.out.println("我是IE浏览器");
	} else if (userAgent.contains("Firefox")) {
		System.out.println("我是火狐浏览器");
	} else {
		System.out.println("我是其他浏览器");
	}
	
	// 获取访问来源网址
	String referer=request.getHeader("referer");
	
	if(referer!=null&&referer.startsWith("http://localhost:6060/Web03")) {
		out.print("正常访问");
	}else {
		out.print("站外访问,盗链访问");
	}
4.3 获取请求参数值
		
	//解决post请求参数的中文乱码问题
	request.setCharacterEncoding("UTF-8");
	
	//获取查询字符串参数的值
	String operate=request.getParameter("operate");
	//解决get请求参数或查询字符串中文乱码问题
	operate=new String(operate.getBytes("ISO-8859-1"),"UTF-8");
	System.out.println(operate);
	
	//1.获取表单参数的值
	String username=request.getParameter("username");
	System.out.println(username);
	
		
	//2.获取拥有多个值的参数
	String[] hobby=request.getParameterValues("hobby");
	for(String s : hobby) {
		System.out.println(s);
	}
	
	//3.获取所有参数的名称
	Enumeration<String> names=request.getParameterNames();
	while(names.hasMoreElements()) {
		System.out.println(names.nextElement());
	}
	
	System.out.println("------------------------------");
	//4.获取所有的参数名称和参数值
	Map<String, String[]> parameterMap=request.getParameterMap();
	for (Entry<String,String[]> entry : parameterMap.entrySet()) {
		String key=entry.getKey();
		for (String value : entry.getValue()) {
			System.out.println("key:"+key+",value:"+value);
		}
	}
}
4.4 请求转发

请求转发:客户端发送请求到服务器端某一个处理程序,该程序把处理权转发给另一个程序,最好把处理结果响应给客户端

  • 转发过程浏览器只发送了一次请求
  • 原处理程序和被转发的处理程序的Request对象是共用的
  • 地址栏不会改变
  • 不能转发站外资源
  • 转发等同于一个普通方法,所以执行到forward()方法会马上去执行被转发的处理程序的代码,执行完毕后再执行原处理程序forward()后面的代码
  • include()与forword()都可以转发, 如果使用forward跳转则后面的response输出则不会执行,而用include来跳转,则include的servlet执行完后,再返回到原来的servlet执行response的输出
public class Servlet1 extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		
		String username=request.getParameter("username");
		//输出zhangsan
		System.out.println(username);
		
		//在请求域中存储数据
		request.setAttribute("data", "mydata");
		
		//在网站内部访问站内资源不需要以网站名称开头
		//转发时把request和response传递给下一个Servlet,所以下一个Servlet也可以从request中获取同样的信息
		request.getRequestDispatcher("/Servlet2").forward(request, response);
	}
public class Servlet2 extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//这里的数据跟Servlet1的数据是一样的
		String username=request.getParameter("username");
		
		//从请求域中获取数据
		String data=(String)request.getAttribute("data");
		//从请求域中移除数据
		request.removeAttribute("data");
		
		//输出zhangsan
		System.out.println(data);
		//输出mydata
		System.out.println(username);
	}
}
4.5 Request域对象
  • 只在单次请求中数据共享(请求转发也有效)
  • 代码参考4.3例子

5. 总结区别

5.1 重定向与转发区别
  • 重定向两次请求,转发一次请求
  • 重定向地址栏的地址变化,转发地址不变
  • 重新定向可以访问外部网站 转发只能访问内部资源
  • 转发的性能要优于重定向
5.2 客户端访问服务器端资源与服务器端访问站内资源的路径区别
  • 前端页面所有访问服务器端资源都要在路径前面加上网站名称(/网站名称/XXX)
  • 服务器端资源访问站内资源不需要加上网站名称(/XXX),包括各种静态资源,转发资源
  • 重定向需要加上网站名称,因为重定向是先响应到客户端,再次发起的请求
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值