1.HttpServletRequest概述
我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。
service方法中的request的类型是ServletRequest,而doGet/doPost方法的request的类型是HttpServletRequest,HttpServletRequest是ServletRequest的子接口,功能和方法更加强大,今天我们学习HttpServletRequest。
2.request的运行流程
3.通过抓包工具抓取Http请求
因为request代表请求,所以我们可以通过该对象分别获得Http请求的请求行,请 求头和请求体
4.通过request获得请求行
获得客户端的请求方式:String getMethod()
获得请求的资源:
String getRequestURI()
StringBuffer getRequestURL()
String getContextPath() ---web应用的名称
String getQueryString() ---- get提交url地址后的参数字符串
username=zhangsan&password=123
注意:
request获得客户机(客户端)的一些信息
request.getRemoteAddr() --- 获得访问的客户端IP地址
//1、获得请求方式
String method = request.getMethod();
System.out.println("method:" + method);
//2.获得请求的资源相关的内容
String requestURI = request.getRequestURI();
System.out.println("uri:"+requestURI);
StringBuffer requestURL = request.getRequestURL();
System.out.println("url:"+requestURL);
//获得Web应用的名称
String contextPath = request.getContextPath();
System.out.println("web应用:" + contextPath);
//地址后的参数字符串
String queryString = request.getQueryString();
System.out.println(queryString);
//3.获得客户端的信息--获得访问者的IP地址
String remoteAddr = request.getRemoteAddr();
System.out.println(remoteAddr);
method:post
5.通过request获得请求头
long getDateHeader(String name)
String getHeader(String name)
Enumeration getHeaderNames()
Enumeration getHeaders(String name)
int getIntHeader(String name)
//1.获得指定的头
String header = request.getHeader("User-Agent");
System.out.println(header);
//2.获得所有头的名称
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
System.out.println(headerName + ":" + headerValue);
}
输出:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
host:localhost:8080
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
accept-language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
accept-encoding:gzip, deflate
connection:keep-alive
upgrade-insecure-requests:1
referer头的作用:执行该此访问的的来源
做防盗链
//对新闻的来源进行判断
String header = request.getHeader("referer");
if(header != null && header.startsWith("http://localhost")){
//从自己网站跳转过来,可以看新闻
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("奖牌");
}else{
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("盗链者,可耻");
}
6.通过request获得请求体
请求体中的内容是通过post提交的请求参数,格式是:
username=zhangsan&password=123&hobby=football&hobby=basketball
key ---------------------- value
username [zhangsan]
password [123]
hobby [football,basketball]
以上面参数为例,通过一下方法获得请求参数:
String getParameter(String name)
String[] getParameterValues(String name)
Enumeration getParameterNames()
Map<String,String[]> getParameterMap()
注意:get请求方式的请求参数 上述的方法一样可以获得
解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");
解决get提交的方式的乱码:
parameter = new String(parameter.getbytes("iso8859-1"),"utf-8");
//1.获得单个表单值
String username = request.getParameter("username");
System.out.println(username);//zhangsan
String password = request.getParameter("password");
System.out.println(password);//123
//2.获得多个表单的值
String[] hobbys = request.getParameterValues("hobby");
for(String hobby : hobbys){
System.out.println(hobby);
}
//3.获得所有请求参数的名称
Enumeration<String> parameterNames = request.getParameterNames();
while(parameterNames.hasMoreElements()){
System.out.println(parameterNames.nextElement());
}
System.out.println("---------------------------");
Map<String, String[]> parameterMap = request.getParameterMap();
for(Map.Entry<String, String[]> entry : parameterMap.entrySet()){
System.out.println(entry.getKey());
for(String str : entry.getValue()){
System.out.println(str);
}
System.out.println("---------------------------");
}
7.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)
注意:ServletContext域与Request域的生命周期比较?
ServletContext:
创建:服务器启动
销毁:服务器关闭
域的作用范围:整个web应用
request:
创建:访问时创建request
销毁:响应结束request销毁
域的作用范围:一次请求中
注意:转发与重定向的区别?
1)重定向两次请求,转发一次请求
2)重定向地址栏的地址变化,转发地址不变
3)重新定向可以访问外部网站 转发只能访问内部资源
4)转发的性能要优于重定向
Servlet1
//想request域中存储数据
request.setAttribute("name", "tom");
//将servlet1请求转发给servlet2
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
//执行转发的方法
requestDispatcher.forward(request, response);
Servlet2
//从request域中取出数据
Object attribute = request.getAttribute("name");
response.getWriter().write("hello haohao..." + attribute);
注意:客户端地址与服务器端地址的写法?
客户端地址:
是客户端去访问服务器的地址,服务器外部的地址,
特点:写上web应用名称
直接输入地址:
重定向
服务器端地址:
服务器内部资源的跳转的地址,
特点:不需要写web应用的名称
转发
案例一、完成用户注册
/WEB15A/WebContent/register.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head></head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>会员注册</title>
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
<script src="js/jquery-1.11.3.min.js" type="text/javascript"></script>
<script src="js/bootstrap.min.js" type="text/javascript"></script>
<!-- 引入自定义css文件 style.css -->
<link rel="stylesheet" href="css/style.css" type="text/css" />
<style>
body {
margin-top: 20px;
margin: 0 auto;
}
.carousel-inner .item img {
width: 100%;
height: 300px;
}
font {
color: #3164af;
font-size: 18px;
font-weight: normal;
padding: 0 10px;
}
</style>
</head>
<body>
<!-- 引入header.jsp -->
<jsp:include page="/header.jsp"></jsp:include>
<div class="container"
style="width: 100%; background: url('image/regist_bg.jpg');">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8"
style="background: #fff; padding: 40px 80px; margin: 30px; border: 7px solid #ccc;">
<font>会员注册</font>USER REGISTER
<!-- 当你点击button按钮提交的时候,浏览器的地址为/WEB15/register,页面会刷新但是地址不变 -->
<form class="form-horizontal" style="margin-top: 5px;" action="/WEB15A/register" method="post">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="username" name="username"
placeholder="请输入用户名">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">密码</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="inputPassword3" name="password"
placeholder="请输入密码">
</div>
</div>
<div class="form-group">
<label for="confirmpwd" class="col-sm-2 control-label">确认密码</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="confirmpwd"
placeholder="请输入确认密码">
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
<div class="col-sm-6">
<input type="email" class="form-control" id="inputEmail3" name="email"
placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="usercaption" class="col-sm-2 control-label">姓名</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="usercaption" name="name"
placeholder="请输入姓名">
</div>
</div>
<div class="form-group opt">
<label for="inlineRadio1" class="col-sm-2 control-label">性别</label>
<div class="col-sm-6">
<label class="radio-inline"> <input type="radio"
name="sex" id="inlineRadio1" value="male">
男
</label> <label class="radio-inline"> <input type="radio"
name="sex" id="inlineRadio2" value="female">
女
</label>
</div>
</div>
<div class="form-group">
<label for="date" class="col-sm-2 control-label">出生日期</label>
<div class="col-sm-6">
<input type="date" class="form-control" name="birthday">
</div>
</div>
<div class="form-group">
<label for="date" class="col-sm-2 control-label">验证码</label>
<div class="col-sm-3">
<input type="text" class="form-control">
</div>
<div class="col-sm-2">
<img src="./image/captcha.jhtml" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" width="100" value="注册" name="submit"
style="background: url('./images/register.gif') no-repeat scroll 0 0 rgba(0, 0, 0, 0); height: 35px; width: 100px; color: white;">
</div>
</div>
</form>
</div>
<div class="col-md-2"></div>
</div>
</div>
<!-- 引入footer.jsp -->
<jsp:include page="/footer.jsp"></jsp:include>
</body>
</html>
/WEB15A/src/cn/ithiema/register/RegisterServlet.java
package cn.ithiema.register;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.dbutils.QueryRunner;
import cn.ithiema.utils.DataSourceUtils;
public class RegisterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置request的编码---只适合post方式
request.setCharacterEncoding("UTF-8");
//get方式乱码解决
//String username = request.getParameter("username");//乱码
//先用iso8859-1编码 在使用utf-8解码
//username = new String(username.getBytes("iso8859-1"),"UTF-8");
//1、获取数据
String username = request.getParameter("username");
System.out.println(username);
//String password = request.getParameter("password");
//.....
//2、将散装的封装到javaBean
//User user = new User();
//user.setUsername(username);
//user.setPassword(password);
//使用BeanUtils进行自动映射封装
//BeanUtils工作原理:将map中的数据 根据key与实体的属性的对应关系封装
//只要key的名字与实体的属性 的名字一样 就自动封装到实体中
Map<String, String[]> properties = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user, properties);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//现在这个位置 user对象已经封装好了
//手动封装uid----uuid---随机不重复的字符串32位--java代码生成后是36位
user.setUid(UUID.randomUUID().toString());
//3、将参数传递给一个业务操作方法
try {
regist(user);
} catch (SQLException e) {
e.printStackTrace();
}
//4、认为注册成功跳转到登录页面
//response.sendRedirect(request.getContextPath()+"/login.jsp");
}
//注册的方法
public void regist(User user) throws SQLException{
//操作数据库
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "insert into user values(?,?,?,?,?,?,?,?,?,?)";
runner.update(sql,user.getUid(),user.getUsername(),user.getPassword(),user.getName(),
user.getEmail(),null,user.getBirthday(),user.getSex(),null,null);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
/WEB15A/src/cn/ithiema/register/User.java
package cn.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 + "]";
}
}
注册乱码的解决:
当method=“post”,
//设置request的编码—只适合post方式
//request.setCharacterEncoding(“UTF-8”);
乱码的情况:
当method=“get”,
//设置request的编码—只适合post方式
//request.setCharacterEncoding(“UTF-8”);
乱码的情况:
//get方式乱码解决
String username = request.getParameter("username");//乱码
//先用iso8859-1编码 在使用utf-8解码
username = new String(username.getBytes("iso8859-1"),"UTF-8");
System.out.println(username);
案例二、完成登录错误信息的回显
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>会员登录</title>
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css" />
<script src="js/jquery-1.11.3.min.js" type="text/javascript"></script>
<script src="js/bootstrap.min.js" type="text/javascript"></script>
<!-- 引入自定义css文件 style.css -->
<link rel="stylesheet" href="css/style.css" type="text/css" />
<style>
body {
margin-top: 20px;
margin: 0 auto;
}
.carousel-inner .item img {
width: 100%;
height: 300px;
}
.container .row div {
/* position:relative;
float:left; */
}
font {
color: #666;
font-size: 22px;
font-weight: normal;
padding-right: 17px;
}
</style>
</head>
<body>
<!-- 引入header.jsp -->
<jsp:include page="/header.jsp"></jsp:include>
<div class="container"
style="width: 100%; height: 460px; background: #FF2C4C url('images/loginbg.jpg') no-repeat;">
<div class="row">
<div class="col-md-7">
<!--<img src="./image/login.jpg" width="500" height="330" alt="会员登录" title="会员登录">-->
</div>
<div class="col-md-5">
<div
style="width: 440px; border: 1px solid #E7E7E7; padding: 20px 0 20px 30px; border-radius: 5px; margin-top: 60px; background: #fff;">
<font>会员登录</font>USER LOGIN
<div><%=request.getAttribute("loginInfo")==null?"":request.getAttribute("loginInfo") %></div>
<form class="form-horizontal" action="/WEB15/login" method="post">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">用户名</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="username" name="username"
placeholder="请输入用户名">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">密码</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="inputPassword3" name="password"
placeholder="请输入密码">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">验证码</label>
<div class="col-sm-3">
<input type="text" class="form-control" id="inputPassword3"
placeholder="请输入验证码">
</div>
<div class="col-sm-3">
<img src="./image/captcha.jhtml" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label> <input type="checkbox"> 自动登录
</label> <label> <input
type="checkbox"> 记住用户名
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" width="100" value="登录" name="submit"
style="background: url('./images/login.gif') no-repeat scroll 0 0 rgba(0, 0, 0, 0); height: 35px; width: 100px; color: white;">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- 引入footer.jsp -->
<jsp:include page="/footer.jsp"></jsp:include>
</body>
</html>
package cn.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 cn.ithiema.register.User;
import cn.ithiema.utils.DataSourceUtils;
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置request的编码---只适合post方式
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 (Exception e) {
System.out.println(e);
}
//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){
User user = null;
try {
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from user where username=? and password=?";
user = runner.query(sql, new BeanHandler<User>(User.class),username,password);
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
注册界面
登录成功
总结:
request获得行的内容
request.getMethod()
request.getRequestURI()
request.getRequestURL()
request.getContextPath()
request.getRemoteAddr()
request获得头的内容
request.getHeader(name)
request获得体(请求参数)
String request.getParameter(name)
Map<String,String[]> request.getParameterMap();
String[] request.getParameterValues(name);
注意:客户端发送的参数 到服务器端都是字符串
获得中文乱码的解决:
post:request.setCharacterEncoding(“UTF-8”);
get:
//get方式乱码解决
String username = request.getParameter("username");//乱码
//先用iso8859-1编码 在使用utf-8解码
username = new String(username.getBytes("iso8859-1"),"UTF-8");
request转发和域
request.getRequestDispatcher(转发的地址).forward(req,resp);
request.setAttribute(name,value)
request.getAttribute(name)