1 HttpServletRequest概述
在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。
service方法中的request的类型是ServletRequest,
而doGet/doPost方法的request的类型是HttpServletRequest,
HttpServletRequest是ServletRequest的子接口,功能和方法更加强大
1.1 request的运行流程
1.2通过抓包工具抓取Http请求
因为request代表请求,所以可以通过该对象分别获得Http请求的请求行,请求头和请求体:
2通过request获得请求行
1)获得客户端的请求方式:String getMethod()
2)获得请求的资源:
String getRequestURI() 绝对路径或相对路径或网络地址
StringBuffer getRequestURL() 网络地址
String getContextPath() ---web应用的名称(重要)因为项目名有可能改,所以不能写死
String getQueryString() ---- get提交url地址后的参数字符串,只有get请求才有
request.getRemoteAddr() --- 获得访问的客户端IP地址
例:
建一个login.jsp:
<form action="/20190111WEB/LoginServlet" method="get"> 用户名:<input type="text" name="username" /><br /> 密码:<input type="password" name="password" /><br /> <input type="submit" value="提交" /> </form>
建一个LoginServlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求行中内容 //1获取请求方式 String method=request.getMethod(); System.out.println("请求方式为"+method); //2获得请求资源的相关内容 String requestURI=request.getRequestURI(); StringBuffer requestURL=request.getRequestURL(); System.out.println("URI"+requestURI); System.out.println("URL"+requestURL); //3获得web应用名称 String contextPath=request.getContextPath(); System.out.println("web应用名称"+contextPath); //4获取get方式提交的url后的参数字符串 String queryString=request.getQueryString(); System.out.println("get提交的参数"+queryString); //5获取访问者的ip地址 String ip=request.getRemoteAddr(); System.out.println("ip为"+ip); }
3通过request获得请求头
3.1常用方法
String getHeader(String name)
long getDateHeader(String name)
Enumeration getHeaderNames() 枚举
Enumeration getHeaders(String name)
int getIntHeader(String name)
例:HeaderServlet
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //通过枚举获得所有头的名称 Enumeration<String> headNames=request.getHeaderNames(); while(headNames.hasMoreElements()){ String headerName=headNames.nextElement(); String headerValue=request.getHeader(headerName); System.out.println(headerName+":"+headerValue); } }
3.2 referer头做防盗链
referer头的作用:获取该访问的来源
例:news.jsp:
<a href="/20190111WEB/ReferServlet">某某新闻标题</a>
ReferServlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取请求头中的referer String referer=request.getHeader("referer"); //判断referer if(referer!=null&&referer.startsWith("http://localhost")){ response.sendRedirect("/20190111WEB/login.jsp"); }else{ //解决中文乱码 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("你是盗链者,可耻"); } }
如果改成:(随意改)
4通过request获得请求体
请求体中的内容是通过post提交的请求参数,格式是:
username=zhangsan&password=123&hobby=football&hobby=basketball
key value
username [zhangsan]
password [123]
hobby [football,basketball]
4.1获得请求参数方法
String getParameter(String name)
String[] getParameterValues(String name)(多选可用这个)
Map<String,String[]> getParameterMap()
一个key对应多个value,例如多选,就可以用map
Map集合作用:例如注册,封装成一个对象,传到后台
get请求方式的请求参数上述的方法一样可以获得
4.2中文乱码问题
1)解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");
2)解决get提交的方式的乱码:
因为get的参数是从地址栏获得,所以一次只能解决一个字符串的中文乱码,
先获得参数,用iso8859-1编码,getbytes("iso8859-1")
再用utf-8解码:new String(byte[], "utf-8")
完整为:
parameter = new String(parameter.getbytes("iso8859-1"),"utf-8");
表单一般不用get提交,所以不常用
例:
Login.jsp:
<form action="/20190111WEB/BodyServlet" method="post"> 用户名:<input type="text" name="username" /><br /> 密码:<input type="password" name="password" /><br /> 爱好: <input type="checkbox" name="hobby" value="zq"/>足球 <input type="checkbox" name="hobby" value="lq"/>蓝球 <input type="checkbox" name="hobby" value="ppq"/>乒乓球 <input type="checkbox" name="hobby" value="pq"/>排球<br> <input type="submit" value="提交" /> </form>
BodyServlet:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解决中文乱码-post方式提交 request.setCharacterEncoding("utf-8"); //获取request请求体的指定参数 String uesrname=request.getParameter("username"); //解决中文乱码-get方式 uesrname=new String(uesrname.getBytes("iso8859-1"),"utf-8"); String password=request.getParameter("password"); System.out.println(uesrname+":"+password); System.out.println("-------------"); //获取所有参数的map集合 Map<String,String[]> map=request.getParameterMap(); Set<String> set=map.keySet(); for(String s:set){ //获取name值 String name=s; System.out.print(name+":"); //获取value数据 String[] values=map.get(name); //遍历数组 for(String v:values){ System.out.println(v); } System.out.println("-------------"); } }
5 request是一个域对象
5.1方法和作用范围
request对象也是一个存储数据的区域对象,所以也具有如下方法:
setAttribute(String name, Object o)
getAttribute(String name)
removeAttribute(String name)
request域的作用范围:一次请求中
5.2 ServletContext域与Request域的生命周期比较
ServletContext:
创建:服务器启动
销毁:服务器关闭
域的作用范围:整个web应用
request:
创建:访问时(请求时)创建request
销毁:响应结束request销毁
域的作用范围:一次请求中
6 request完成请求转发
6.1方法
获得请求转发器----path是转发的地址
RequestDispatcher getRequestDispatcher(String path)
通过转发器对象转发
requestDispathcer.forward(ServletRequest request, ServletResponse response)
例:
Servlet01:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //请求转发 //设置一个值 request.setAttribute("name", "zhangsan"); //1获得转发器 RequestDispatcher dis=request.getRequestDispatcher("/Servlet02"); //因为是在项目内部,所以不用写项目名 //2调用转发方法 dis.forward(request, response); }
Servlet02:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name=(String)request.getAttribute("name"); response.getWriter().write("hello! "+name+",this is Servlet02..."); }
6.2请求转发与重定向的区别
相同点:都跳转
不同点:
1)请求转发是Request对象的,重定向是response对象的
2)重定向两次请求,转发一次请求
3)重定向地址栏的地址变化,转发地址不变
4)重新定向可以访问外部网站,转发只能访问内部资源
5)转发的性能要优于重定向(因为只请求一次)
需要带值,用请求转发
不需要,可以用重定向
6.3客户端地址与服务器端地址的写法
客户端地址:
是客户端去访问服务器的地址,是服务器外部的地址
所以要写上web应用名称
服务器端地址:
服务器内部资源的跳转的地址,所以不需要写web应用的名称
7注册实例
1)准备数据库和表
2)建项目,分包,导入jsp页面,添加工具类(注意修改数据库名)和jdbc jar包
3)建Users实体类
4)register.jsp上添加form的action和method,表单元素加上name,必须要和Users实体类对应上
5)编写RegisterServlet
1.BeanUtils工具实现自动映射封装:
将map中的数据根据key与实体的属性对应关系进行封装,所在要保证jsp表单中的name和Users中的成员变量一样。
只要key的名字与实体属性的名字一样,就会自动封装到实体中
把两个jar包导进去
//创建对象
Users users=new Users();
//调用方法
BeanUtils.populate(users, map);
2.手动封装uid--利用工具UUID,随机生成不重复的32位字符串,但是经过java代码生成生是36位
users.setUid(UUID.randomUUID().toString());
(返回值是UUID对象,再toString成字符串)
6)登录错误提示信息的处理
带着值,所以用请求转发
LoginServlet中添加一个loginInfo,
Login.jsp页面中加上:
<%=request.getAttribute("loginInfo")==null?"":request.getAttribute("loginInfo")%>
完整项目源码:
(过两天贴上)
重点总结:
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是一个域对象,方法和作用范围
setAttribute(String name, Object o)
getAttribute(String name)
removeAttribute(String name)
作用范围:一次请求中
6请求转发
request.getRequestDispatcher(转发的地址).forward(request, response);
请求转发与重定向的区别
7注册实例
BeanUtils工具进行对象封装
UUID工具封装uid
错误提示信息的处理