顶级架构师学习——第十一阶段:Web开发之Response&Request

Hello!对,没错,又是我!梦想做一只咸鱼的我~~

我知道我很懒了~~不要在意这些细节,我会学完的啦~~

目录

一、Response

先简单介绍一下HttpServletResponse

response的运行流程

通过response设置响应行、响应头和响应体

二、Request

HttpServletRequest概述

response的运行流程

通过request获得请求行

通过request获得请求头

通过request获得请求体

Request的其他功能

三、一打打子小重点

四、简单的总结

五、咳咳...深夜小福利


今天是Response和Request的学习,会给出提供远程下载、简单的验证码实现以及与数据库关联的登录反馈代码!代码来源itheima,在此表示感谢~

一、Response

先简单介绍一下HttpServletResponse

我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。

service方法中的response的类型是ServletResponse,而doGet/doPost方法的response的类型是HttpServletResponse,HttpServletResponse是ServletResponse的子接口,功能和方法更加强大,今天我们学习的是HttpServletResponse。

response的运行流程

运行流程比较简单,这张图就很清楚了,不多讲了(ps:绝对不是我没有记住老师说了什么)

通过response设置响应行、响应头和响应体

前面我们已经说过,response响应分为响应头、响应行和响应体,现在我们分别通过代码对它们进行人为的设置。

setStatus(int sc)  用于设置响应行的状态码,如302、404、500等

setHeader(String name, String value)  用于设置响应头的各个属性

addHeader(String name, String value)   可以为响应头添加一种属性

敲黑板,响应体圈起来,考试要考!

1.响应体设置文本

PrintWriter getWriter()

获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览 器端。

PS:关于设置中文的乱码问题

原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,可以通过 response的setCharacterEncoding(String charset) 设置response的编码

但我们发现客户端还是不能正常显示文字

原因:我们将response缓冲区的编码设置成UTF-8,但浏览器的默认编码是本地系统的编码,因为我们都是中文系统,所以客户端浏览器的默认编码是GBK,我们可以手动修改浏览器的编码为UTF-8。

我们还可以在代码中指定浏览器解析页面的编码方式:

通过response的setContentType(String type)方法指定页面解析时的编码是UTF-8

response.setContentType("text/html;charset=UTF-8");

上面的代码不仅可以指定浏览器解析页面时的编码,同时也内含 setCharacterEncoding的功能,所以在实际开发中只要编写 response.setContentType("text/html;charset=UTF-8");就可以解决页面输出中文乱码问题。

2.响应头设置字节

ServletOutputStream  getOutputStream()

获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,在由Tomcat服务器将字节内容组成Http响应返回给浏览器。

二、Request

HttpServletRequest概述

我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。

service方法中的request的类型是ServletRequest,而doGet/doPost方法的request的类型是HttpServletRequest,HttpServletRequest是ServletRequest的子接口,功能和方法更加强大,今天我们学习HttpServletRequest。

response的运行流程

emmm,其实上面已经给了,不过,这么好心的我决定再给一遍!不用感谢我!

通过request获得请求行

获得客户端的请求方式:String getMethod()

获得请求的资源:

String getRequestURI() ---得到访问的地址,如/web/(URI的范围更广,包括了URL)

StringBuffer getRequestURL() ---得到访问的网址,如http://localhost:8080/web/

String getContextPath() ---得到web应用的名称

String getQueryString() ---- 得到get提交url地址后的参数字符串:username=zhangsan&password=123

注意:request获得客户机(客户端)的一些信息

request.getRemoteAddr() --- 获得访问的客户端IP地址

为了安全起见,99.9%的web应用会选择post来提交表单,因为这样的传输内容不可见(只是相对get而言,这种东西在真正的黑客面前不值一提emmm好想当个黑客qwq)

通过request获得请求头

String getHeader(String name)

Enumeration getHeaderNames()

Enumeration getHeaders(String name)

通过request获得请求体

String getParameter(String name) 

Map<String,String[]> getParameterMap()

对于request的乱码问题,可以通过下面的方法来尝试解决:

解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");

解决get提交的方式的乱码: parameter = new String(parameter.getbytes("iso8859-1"),"utf-8");

Request的其他功能

1.request是一个域对象

request对象也是一个存储数据的区域对象,所以也具有如下方法:

setAttribute(String name, Object o)  设置属性

getAttribute(String name)  得到属性

removeAttribute(String name)  删除属性

注意:request域的作用范围:一次请求中

2.request完成请求转发

获得请求转发器----path是转发的地址

RequestDispatcher getRequestDispatcher(String path)

通过转发器对象转发

requestDispathcer.forward(ServletRequest request, ServletResponse response)

三、一打打子小重点

1.注意:ServletContext域与Request域的生命周期比较?

ServletContext

创建:服务器启动

销毁:服务器关闭

域的作用范围:整个web应用

request

创建:访问时创建request

销毁:响应结束request销毁

域的作用范围:一次请求中

2.注意:转发与重定向的区别?

1)重定向两次请求,转发一次请求

2)重定向地址栏的地址变化,转发地址不变

3)重新定向可以访问外部网站 转发只能访问内部资源

4)转发的性能要优于重定向

3.注意:客户端地址与服务器端地址的写法?

客户端地址:是客户端去访问服务器的地址,服务器外部的地址,需要写上web应用名称。主要方式为直接输入地址重定向

服务器端地址:服务器内部资源的跳转的地址,不需要写web应用的名称。主要方式为转发

四、简单的总结

1.request获得行的内容

request.getMethod()

request.getRequestURI()

request.getRequestURL()

request.getContextPath()

request.getRemoteAddr()

2.request获得头的内容

request.getHeader(name)

3.request获得体(请求参数)

String request.getParameter(name)

Map<String,String[]> request.getParameterMap();

String[] request.getParameterValues(name);

注意:客户端发送的参数 到服务器端都是字符串

4.获得中文乱码的解决:

post:request.setCharacterEncoding(“UTF-8”);

get:parameter = new String(parameter.getBytes(“iso8859-1”),”UTF-8”);

5.request转发和域

request.getRequestDispatcher(转发的地址).forward(req,resp);

request.setAttribute(name,value)

request.getAttribute(name)

五、咳咳...深夜小福利

趁自己还有大把头发的时候多看一眼,一定要控寂住寄几!!!

1.下载文件servlet

对于浏览器能够解析的文件,当我们点击之后它都会直接打开而不是下载下来,对于不能直接解析的文件如zip等压缩文件时才会弹出下载框,但我们有时候仅仅需要将它下载下来,这时候就可以用到下面的这个servlet来解决问题。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

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

public class DownloadServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 获得要下载的文件的名称
		String filename = request.getParameter("filename");

		// 要下载的这个文件的类型-----客户端通过文件的MIME类型去区分类型
		response.setContentType(this.getServletContext().getMimeType(filename));
		// 告诉客户端该文件不是直接解析 而是以附件形式打开(下载)
		response.setHeader("Content-Disposition", "attachment;filename="+filename);

		// 获取文件的绝对路径
		String path = this.getServletContext().getRealPath("download/"+filename);
		// 获得该文件的输入流
		InputStream in = new FileInputStream(path);
		// 获得输出流---通过response获得的输出流 用于向客户端写内容
		ServletOutputStream out = response.getOutputStream();
		// 文件拷贝的模板代码
		int len = 0;
		byte[] buffer = new byte[1024];
		while((len=in.read(buffer))>0){
			out.write(buffer, 0, len);
		}

		in.close();
		//out.close();// 浏览器会帮你自动关闭,所以有没有都可以,但是一般写上是个好习惯

	}

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

2.验证码servlet

记得把new_words.txt放在WEB-INF目录下哟~~

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

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

/**
 * 验证码生成程序
 */
public class CheckImgServlet extends HttpServlet {

	// 集合中保存所有成语
	private List<String> words = new ArrayList<String>();

	@Override
	public void init() throws ServletException {
		// 初始化阶段,读取new_words.txt
		// web工程中读取文件,必须使用绝对磁盘路径
		String path = getServletContext().getRealPath("/WEB-INF/new_words.txt");
		try {
			BufferedReader reader = new BufferedReader(new FileReader(path));
			String line;
			while ((line = reader.readLine()) != null) {
				words.add(line);
			}
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 禁止缓存
		// response.setHeader("Cache-Control", "no-cache");
		// response.setHeader("Pragma", "no-cache");
		// response.setDateHeader("Expires", -1);

		int width = 120;
		int height = 30;

		// 步骤一 绘制一张内存中图片
		BufferedImage bufferedImage = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);

		// 步骤二 图片绘制背景颜色---通过绘图对象
		Graphics graphics = bufferedImage.getGraphics();// 得到画图对象 --- 画笔
		// 绘制任何图形之前 都必须指定一个颜色
		graphics.setColor(getRandColor(200, 250));
		graphics.fillRect(0, 0, width, height);

		// 步骤三 绘制边框
		graphics.setColor(Color.WHITE);
		graphics.drawRect(0, 0, width - 1, height - 1);

		// 步骤四 四个随机数字
		Graphics2D graphics2d = (Graphics2D) graphics;
		// 设置输出字体
		graphics2d.setFont(new Font("宋体", Font.BOLD, 18));

		Random random = new Random();// 生成随机数
		int index = random.nextInt(words.size());
		String word = words.get(index);// 获得成语

		// 定义x坐标
		int x = 10;
		for (int i = 0; i < word.length(); i++) {
			// 随机颜色
			graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random
					.nextInt(110), 20 + random.nextInt(110)));
			// 旋转 -30 --- 30度
			int jiaodu = random.nextInt(60) - 30;
			// 换算弧度
			double theta = jiaodu * Math.PI / 180;

			// 获得字母数字
			char c = word.charAt(i);

			// 将c 输出到图片
			graphics2d.rotate(theta, x, 20);
			graphics2d.drawString(String.valueOf(c), x, 20);
			graphics2d.rotate(-theta, x, 20);
			x += 30;
		}

		// 将验证码内容保存session
		request.getSession().setAttribute("checkcode_session", word);

		// 步骤五 绘制干扰线
		graphics.setColor(getRandColor(160, 200));
		int x1;
		int x2;
		int y1;
		int y2;
		for (int i = 0; i < 30; i++) {
			x1 = random.nextInt(width);
			x2 = random.nextInt(12);
			y1 = random.nextInt(height);
			y2 = random.nextInt(12);
			graphics.drawLine(x1, y1, x1 + x2, x2 + y2);
		}

		// 将上面图片输出到浏览器 ImageIO
		graphics.dispose();// 释放资源
		
		//将图片写到response.getOutputStream()中
		ImageIO.write(bufferedImage, "jpg", response.getOutputStream());

	}

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

	/**
	 * 取其某一范围的color
	 * 
	 * @param fc
	 *            int 范围参数1
	 * @param bc
	 *            int 范围参数2
	 * @return Color
	 */
	private Color getRandColor(int fc, int bc) {
		// 取其随机颜色
		Random random = new Random();
		if (fc > 255) {
			fc = 255;
		}
		if (bc > 255) {
			bc = 255;
		}
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}

}

 3.登录反馈servlet

package com.ithiema.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DataSourceUtils {

	private static DataSource dataSource = new ComboPooledDataSource();

	private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();

	// 直接可以获取一个连接池
	public static DataSource getDataSource() {
		return dataSource;
	}

	// 获取连接对象
	public static Connection getConnection() throws SQLException {

		Connection con = tl.get();
		if (con == null) {
			con = dataSource.getConnection();
			tl.set(con);
		}
		return con;
	}

	// 开启事务
	public static void startTransaction() throws SQLException {
		Connection con = getConnection();
		if (con != null) {
			con.setAutoCommit(false);
		}
	}

	// 事务回滚
	public static void rollback() throws SQLException {
		Connection con = getConnection();
		if (con != null) {
			con.rollback();
		}
	}

	// 提交并且 关闭资源及从ThreadLocall中释放
	public static void commitAndRelease() throws SQLException {
		Connection con = getConnection();
		if (con != null) {
			con.commit(); // 事务提交
			con.close();// 关闭资源
			tl.remove();// 从线程绑定中移除
		}
	}

	// 关闭资源方法
	public static void closeConnection() throws SQLException {
		Connection con = getConnection();
		if (con != null) {
			con.close();
		}
	}

	public static void closeStatement(Statement st) throws SQLException {
		if (st != null) {
			st.close();
		}
	}

	public static void closeResultSet(ResultSet rs) throws SQLException {
		if (rs != null) {
			rs.close();
		}
	}

}
package com.ithiema.register;

public class User {

	private String uid;
	private String username;
	private String password;
	private String name;
	private String email;
	private String sex;
	private String birthday;
	public String getUid() {
		return uid;
	}
	public void setUid(String uid) {
		this.uid = uid;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getBirthday() {
		return birthday;
	}
	public void setBirthday(String birthday) {
		this.birthday = birthday;
	}
	@Override
	public String toString() {
		return "User [uid=" + uid + ", username=" + username + ", password=" + password + ", name=" + name + ", email="
				+ email + ", sex=" + sex + ", birthday=" + birthday + "]";
	}	
}
package com.ithiema.login;

import java.io.IOException;
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.ithiema.register.User;
import com.ithiema.utils.DataSourceUtils;

public class LoginServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		request.setCharacterEncoding("UTF-8");
		
		//1、获得用户名和密码
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		//2、调用一个业务方法进行该用户查询
		User login = null;
		try {
			login = login(username,password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		//3、通过user是否为null判断用户名和密码是否正确
		if(login!=null){
			//用户名和密码正确
			//登录成功 跳转到网站的首页
			response.sendRedirect(request.getContextPath());
		}else{
			//用户名或密码错误
			//跳回当前login.jsp
			//使用转发 转发到login.jsp  向request域中存储错误信息
			request.setAttribute("loginInfo", "用户名或密码错误");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
		}
		
	}
	
	public User login(String username,String password) throws SQLException{
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		String sql = "select * from user where username=? and password=?";
		User user = runner.query(sql, new BeanHandler<User>(User.class), username,password);
		return user;
	}

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

猜你喜欢

转载自blog.csdn.net/qq_39391192/article/details/86775752