WEB17_Request对象
本节概要:
1.请求行,获得信息的方法
2.请求头,获得信息的方法;防盗链
3.请求体,获得信息的方法
4.其他:登录的信息回显
首先,可以抓包想一下请求行、头、体能获得到那些信息?
这里我默写一下
请求行:GET\POST /WEB应用名/.. 协议
请求头:各项数据
请求体:GET没有,POST表单提交的数据键值对
请求行
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
//获取请求表单的提交方式
String method = request.getMethod();
//获取应用名称
String name = request.getContextPath();
//获取请求表单的URI
String uri = request.getRequestURI();
//获取请求表单的URL
StringBuffer url = request.getRequestURL();
//获取请求表单的协议
String protocol = request.getProtocol();
System.out.println("method:"+method+"\nURI:"+uri+"\nURL:"+url+"\nProtocol:"+protocol);;
}
其中最常用到的是:getContextPath()。我们可以借用其动态的做一些事情,比如说什么时候你突然修改了项目的名称,这会导致一些你在项目中写死的一些带有项目名称的代码出错,我们这是就可以利用这个方法动态获得项目的名称了!
另外顺带说一下,获得客户端的IP的代码
String addr = request.getRemoteAddr();
请求头
这个方法比较多,我们一般使用的是getHeader(String)
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// getHeader演示
String user_agent = request.getHeader("User-Agent");
// 获得所有的头名称
Enumeration names = request.getHeaderNames();
//取出头名称
while(names.hasMoreElements()){
String name = (String) names.nextElement();
// 配合getHeader()输出全部头及其值
String value = request.getHeader(name);
System.out.println(name+":"+value);
}
System.out.println(user_agent);
}
另外,讲一下防盗链。
这个技术需要依靠一个请求头里的key。即referer。
referer是什么?就是比如说你通过百度去百度新闻,从百度发送请求,则referer是百度的地址,通过网易去百度新闻,从网易发送请求,则referer就是网易的地址。而防盗链就是我们获得了这个referer,然后判断一下请求的地址是不是,我们自己的网站,不是我就显示另一个页面,防止页面的盗取。
代码如下
//设置中文
response.setContentType("text/html;charset=UTF-8");
//防盗链
String referer = request.getHeader("referer");
System.out.println(referer);
if(referer.startsWith("http://localhost")){
response.getWriter().write("欢迎你的到来!");
}else{
response.getWriter().write("请从正确地址进入!");
}
请求体
1.getParameter(String):重要
2.getParameterValues(String) 我们通过这个方法获得类似于Checkbox这样的同一个name多个value。
3.getParameterNames()
4.getParameterMap():重要
//post:设置编码格式
request.setCharacterEncoding("UTF-8");
//获得单个表单值
String username = request.getParameter("username");
System.out.println(username);
//获得多个表单值
String[] hobbys = request.getParameterValues("hobby");
for(String hobby:hobbys){
System.out.println(hobby);
}
//获取多个表单的key
Enumeration names = request.getParameterNames();
while(names.hasMoreElements()){
System.out.println(names.nextElement());
}
//获得一个map
Map<String,String[]> map = request.getParameterMap();
for(Map.Entry<String, String[]> me:map.entrySet()){
//获取key值
System.out.println(me.getKey());
//遍历获取value
for(String str:me.getValue()){
System.out.println(str);
}
}
BeanUtil的使用
什么是BeanUtil呢?
其实就是一个程序员自己偷懒作品 先贴出来Jar包>>>
提取码:d21j
现在说一下在哪里偷懒!
首先,我们从表单拿数据要怎么拿呢?
我们可以使用getParameter()方法拿啊!那要是表单传的数据太多了呢,比如我们表单要传十个数据,那我们要写是个getParameter()么?
我们怎么办?我们懒啊!于是我们就依据OO(Object Oriented)思想,将这些数据封装到一个对象中。
BeanUtil的思想就是我们有一个对象,这里我们一般使用那个我们定义的domain包的对象,有时也称POJO
使用这个User类来作为封装对象。
好像有点说不明白,贴一下代码吧!
//设置编码类型
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//BeanUtil封装对象
Map<String,String[]> map = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user, map);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
我们首先看到要用到这个很重要的getParameterMap()方法,因为数据都在这里呗。
然后还有User,因为我们即将将其作为数据存储对象呗。
然后使用BeanUtil类的populate方法了,而这个populate方法的功能就是将你的那个表单的name的value值相等的User类里的各个值传值!
解释有点困难,贴代码!先看html里的代码,这里我们看表单里的name属性,这里例如account
再看我们的domain包的User类
这里可以看出,User类里的account和表单上的name="account"这两个值都是一样的!
只有这样的我们才能将值传到user对象里!
其他
request对象域
类似与ResponseContext域,这个域的功能差不多。列一些不同。
ResponseContext域:
创建:服务器启动
销毁:服务器关闭
范围:整个Web应用
Request域:
创建:访问开始
销毁:响应结束
访问:此次请求
UUID的使用
UUID这里我们使用其功能是生成一个随机的32位的字符串,在哪里用呢?我们数据库的主键ID可以用到啊!而且大公司一般都是这样用的。
UUID uu = UUID.randomUUID();
System.out.println(uu);
如果你数一下位数会看出来,其实是36位,因为Java会添加四个-。
转发功能
写贴出代码
//服务器内部转发,获取转发对象
RequestDispatcher dispatcher = request.getRequestDispatcher("/headServlet");
//进行转发
dispatcher.forward(request, response);
这里可以看出,我的url地址栏上显示的是这个dispatcherServlet的地址,但其实是转发到了服务器的headServlet这个地址,显示的是其内部的内容。
转发与重定向的区别:
1.重定向请求两次,转发请求一次
2.重定向地址栏变化,转发地址栏不变
3.重定向可以访问外部服务器,转发只可以访问内部服务器
4.转发性能优于重定向
服务器端地址:不需要写web应用名称
客户端地址:需要写web应用名称
另外,进行注册界面书写时,注册完成跳转页面要使用重定向,即serRedirect()方法。
登录失败回显
这里我们需要使用到jsp写的界面,而HTML和JSP的一个不同之处就是JSP可以在<%%>里书写Java代码。
然后我们就可以通过request来确认是否显示账户密码错误了!
简单说一下原理,在登录的servlet里面我们有判断是否登录成功的代码,然后判断出来登陆失败的话,我们就使用转发功能,将request对象添加一个键值对比如
key:loginInfo value:"账户密码错误!"
然后我们就转发给login页面,这时候在login页面里我们使用一个div来显示账户密码错误的信息,在div里写入Java代码<%= request.getAttribute("loginInfo")==null?"":request.getAttribute("loginInfo") %>由此只要我们一转发给login页面,就会在此div里显示账户密码错误。实现了回显!
代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// 响应内容类型
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
//获取表单信息
String account = request.getParameter("uaccount");
String password = request.getParameter("upassword");
//处理表单消息
boolean result = loginDao.dealMessage(account,password);
PrintWriter out = response.getWriter();
//登录结果处理
if(result){
loginSuccess(out, account);
}else{
request.setAttribute("loginInfo", "用户名密码错误!");
request.getRequestDispatcher("/cz/login.jsp").forward(request, response);
}
}
这里主要看的是登录失败,也就是最后几行的处理。我们使用request域装入了一对键值对,然后将request转发给了服务器内部的login.jsp
我们就可以在login里拿到request对象的数据了
我们在login.jsp里的div里接受一下数据
<div class="row">
<%= request.getAttribute("loginInfo")==null?"":request.getAttribute("loginInfo") %>
</div>
于是数据就显示在了页面上
另外,我还出现了一些错误,当我转发给login.jsp的时候,css样式表丢失了。打开F12可以看到,404错误,这就是路径的问题。
看一下这个请求网址,在看一下我的项目结构,我们可以知道请求网址应该是:http://localhost:8080/WEB05/css/mycss.css
开始,我的路径是这样的。
<link rel="stylesheet" href="../css/mycss.css">
我的登录本来是Html代码后来改的jsp。所以路径没有变动,本来没有事的,可是一转发路径就变了。
我在网上找了一些方法,但是都没有说的清除,这里我自己写一遍。
修改方法:
在login.jsp的最上边加上这些代码
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
就是设置基本路径在哪里的,现在我们访问的话,其实还是404,因为我们还需要改一下上边代码设置的基本路径,这里我们看basePath这一行,那些方法别看,主要看最后是path+"/"也就是说把我们的路径设置为了/,但实际上呢?我们应该是WEB/css啊!
好吧,我写着博客,然后想把路径先改到原先错误的地方,截几张图再发到博客上,结果代码改回去就忘了怎么改回来了。于是,我自闭了。最后,我发现直接将css的href地址改成绝对地址就行了。类似这样的
<link rel="stylesheet" href="/WEB05/css/mycss.css">
这个WEB05从上边的项目结构图来看,就是我的根目录。反正我自闭了,再见!
本节概要:
1.请求行,获得信息的方法
2.请求头,获得信息的方法;防盗链
3.请求体,获得信息的方法
4.其他:登录的信息回显