javaWeb学习笔记整理(中)

Request

内容
  1. 请求头
  2. 请求参数 重点
  3. 域对象功能 重点
  4. 请求转发 重点
  5. 其他方法, 获取客户端信息, url相关的信息…

request作为域对象的功能

只在同一次请求内有效

获取请求头的方法

request与请求头相关的方法有:

  • String getHeader(String name):获取指定名称的请求头;
  • Enumeration getHeaderNames():获取所有请求头名称;
  • int getIntHeader(String name):获取值为int类型的请求头。

其他方法

  • int getContentLength():获取请求体的字节数,GET请求没有请求体,没有请求体返回-1;
  • String getContentType():获取请求类型,如果请求是GET,那么这个方法返回null;如果是POST请求,那么默认为application/x-www-form-urlencoded,表示请求体内容使用了URL编码;
  • String getMethod():返回请求方法,例如:GET
  • Locale getLocale():返回当前客户端浏览器的Locale。java.util.Locale表示国家和言语,这个东西在国际化中很有用;
  • String getCharacterEncoding():获取请求编码,如果没有setCharacterEncoding(),那么返回null,表示使用ISO-8859-1编码;
  • void setCharacterEncoding(String code):设置请求编码,只对请求体有效!注意,对于GET而言,没有请求体!!!所以此方法只能对POST请求中的参数有效! 重点
  • String getContextPath():返回上下文路径,例如:/hello
  • String getQueryString():返回请求URL中的参数,例如:name=zhangSan
  • String getRequestURI():返回请求URI路径,例如:/hello/oneServlet
  • StringBuffer getRequestURL():返回请求URL路径,例如:http://localhost/hello/oneServlet,即返回除了参数以外的路径信息;
  • String getServletPath():返回Servlet路径,例如:/oneServlet
  • String getRemoteAddr():返回当前客户端的IP地址;
  • String getRemoteHost():返回当前客户端的主机名,但这个方法的实现还是获取IP地址;
  • String getScheme():返回请求协议,例如:http;
  • String getServerName():返回主机名,例如:localhost
  • int getServerPort():返回服务器端口号,例如:8080

请求转发

动态资源(Servlet) 跳转到其他资源(Servlet, html, jsp…)

转发写法

  1. RequestDispatcher getRequestDispatcher(String path) 得到转发器对象

  2. 调用RequestDispatcher对象的forward(request,response)

    RequestDispatcher.forward(request,response);

1与2合并:

request.getRequestDispatcher(String path).forward(request,response);

转发特点:

  1. 只发起一次请求
  2. 客户端的url不会变
  3. 服务器端的转发, 只能转发到服务器内部资源
request域 一般就是在请求转发中使用

获取请求参数

方法1:String getParamter(String name) 根据name获取一个请求参数名对应的一个值

第一种情况: 前端传递请求参数名, 并且传递值

结果: 传递值

第二种情况: 前端传递请求参数名,没有传递值 username=&email=111

结果: “”

扫描二维码关注公众号,回复: 15830719 查看本文章

第三种情况: 前端没有传递请求参数名

结果: null

方法2:String[] getParameterValues(String name) 一个请求参数名对应多个值 例如获取复选框的取值
//一个请求参数名对应多个值
 String[] love = request.getParameterValues("hobbyArr");//获取爱好(复选框)
//数组转换为集合
 List<String> hobbyList = Arrays.asList(hobbyArr);
 System.out.println("love:"+loveList);
//数组转换集合 Arrays.asList(arr)
//asList()这个方法返回的ArrayList不是集合体系中的ArrayList,是一个内部类ArrayList ,是只读的
hobbyList.add("唱歌");//出错!!!!!!
Arrays.asList()这个方法返回的ArrayList不是集合体系中的ArrayList,是一个内部类ArrayList ,是只读的
方法3:Map<String,String[]> getParameterMap() 获取所有的请求参数, 得到一个map集合 一般结合第三方jar, 把map转换为java对象
Map<String, String[]> parameterMap = request.getParameterMap();
遍历Map集合
1.先得到key集合 然后遍历key, 得到value  不推荐
2.得到EntrySet   Entry(key/value键值对)  推荐
Map<String, String[]> parameterMap = request.getParameterMap();
Set<Map.Entry<String, String[]>> entries = parameterMap.entrySet();
for (Map.Entry<String, String[]> entry : entries) {
    
    
    System.out.println(entry.getKey() +"-->"+Arrays.asList(entry.getValue()));
}

浏览器缓存问题:

修改页面, 访问的时候,页面没有改, 可能是浏览器缓存问题

chrome: ctrl + F5 底层刷新

Response

内容

  1. 设置响应头
  2. 发送状态码
  3. 设置响应正文: 得到响应输出流,输出 重要
  4. 重定向 重要

设置响应头

  • void setIntHeader(String name, int value) 设置响应头, 响应头的值int类型
  • void addIntHeader(String name, int value)
  • void addHeader(String name,String value) 设置响应头, 响应头的值String
  • void setHeader(String name,String value)
  • void setContentType(String )设置content-type的响应头

重要的响应头:

content-type: “text/html;charset=UTF-8”:

告诉浏览器, 服务器响应的内容类型 ,浏览器根据内容类型进行解析

charset: 只对对文本文件有效

取值类型

text/html: 响应html文本

图片: 二进制文件

  • image/gif:gif图片格式
  • image/jped:jpg图片格式
  • image/png:png图片格式

css:

text/css

js:

text/javascript

json:

application/json

setHearder()

发送状态码 了解

  • response.setStatus(200):设置状态码;
  • response.sendError(404, “您要查找的资源不存在”):当发送错误状态码时,Tomcat会跳转到固定的错误页面去,但可以显示错误信息。

200: 成功

304: 转发

404: 资源不存在

405: 不支持请求方式

400: 失败请求

500: 服务器内部错误, 后台出现异常

响应正文

通过响应输出流

字符响应输出流: response.getWriter() 输出文本、json数据

字节响应输出流: response.getOutputStream() 万能流, 文本,文件

注意:

这个两个流不能共存, 同时使用, 会抛异常java.lang.IllegalStateException

案例: 服务器响应图片

response.setContentType("image/gif");
//使用字节响应输出流  网络IO
ServletOutputStream outputStream = response.getOutputStream();

//服务器响应一张图片  图片位于服务器硬盘

//1.使用本地输入IO流   读取服务器硬盘图片   到服务器内存
FileInputStream fis = new FileInputStream("D:\\图片\\nbagif.gif");
int content = -1;  //变量, 内存
while((content = fis.read()) != -1){
    
    
    //2.再使用网络输出IO流, 把服务器内存的资源写到客户端
    outputStream.write(content);
}

重定向

response.sendRedirect(重定向的路径)

特点;

  1. 两次请求, request域无效
  2. 客户端地址栏发生变化
  3. 跳转发生在客户端
  4. 跳转资源:可以是服务器内部资源(无法跳转到WEB-INF目录的资源), 也可以是服务器外部资源

重定向与转发资源路径问题:

访问的项目名: /web
重定向到demo1.html
重定向的url写绝对路径:   直接写/ 表示忽略项目名
如果没有设置访问的项目名: 必须加 /项目名/资源路径
项目名 通过request.getContextPath()获取到
重定向的url: 统一的写: req.getContextPath()+"/资源路径"
resp.sendRedirect(req.getContextPath()+"/demo1.html");

 //转发
 // 转发的url, 有项目名,没有项目名, 都不需要加/项目名
 // 统一写法:  /资源路径req.getRequestDispatcher("/demo1.html").forward(req,resp);
重定向的路径
//req.getContextPath()+"/资源路径"
resp.sendRedirect(req.getContextPath()+"/demo1.html");

乱码处理

产生乱码的原因:项目的编码统一为UTF-8,而tomcat的编码(post)为ISO-8859-1

get请求, 通过url

处理方式:

  1. Tomcat 从8开始, 处理Get请求编码, 默认使用的编码: UTF-8
  2. Tomcat7或者之前的, 没有处理Get请求编码 编码还是ISO-8859-1

    1. 在server.xml 指定get请求编码: UTF-8 (tomcat 7之前可以设置)
    <Connector URIEncoding= "UTF-8"  connectionTimeout= "20000"  port= "8888"  protocol= "HTTP/1.1"  redirectPort= "8443" />
    
    1. 对所有的web服务器都有效, 通过代码处理
    //1.打散
    byte[] bytes = name.getBytes("UTF-8");
    //2.组装成字符串
    name = new String(bytes,"UTF-8");
    
get请求时: byte[] bytes = name.getBytes(“UTF-8”);的取值要看tomcat的版本 tomcat7之前为ISO-8859-1

post请求, 通过请求体

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

乱码处理总结:

  1. get请求编码: tomcat8以上已经处理,不需要管
  2. post请求编码, 调用request.setCharacterEncoding(“UTF-8”);
  3. 响应编码设置: 响应编码(不区分get或post请求) response.setContentType(“text/html;charset=UTF-8”);
  4. 2,3代码在获取参数之前, 响应数据之前, 作为servlet前两行代码

案例 某资源一个IP地址一小时只能访问一次

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        response.setContentType("text/html;charset=utf-8");
        ServletContext application  = this.getServletContext();
        Integer count = (Integer)application.getAttribute("count");
        HashMap<String,Long> map = (HashMap) application.getAttribute("map");
        if(map == null){
    
    
//            application.setAttribute("map",new HashMap<String,Long>()); 错误
            map = new HashMap<String,Long>();
        }
        if(count == null){
    
    
            count = 0;
        }
        String ip = request.getRemoteAddr();
        long visitTime = System.currentTimeMillis();
        if(!map.containsKey(ip)){
    
    
            map.put(ip,visitTime);
            count++;
        }else {
    
    
            if(System.currentTimeMillis()-map.get(ip)<3600000){
    
    
                response.getWriter().println("刚刚来过啦,过会再来吧~");
            }else {
    
    
                map.put(ip,System.currentTimeMillis());
                count++;
            }
        }
        response.getWriter().print("<h1>本页面一共被访问" + count + "次!</h1>");
        application.setAttribute("count", count);
        application.setAttribute("map",map);
}

JSP

JSP

本质是一个Servlet的Java类

jsp是动态的资源包含Java脚本、html,浏览器无法直接访问

浏览器请求jsp, 需要web服务器执行jsp的代码, 执行之后的结果转换静态的html,响应给浏览器

JSP脚本

  • <%…%>:java方法内能写的代码,都可以写在它内部
  • <%=…%>:表达式, 表达式的结果在页面展示
  • <%!..%>:Java定义类成员;定义属性,定义方法
jsp本质相当于是一个Servlet的Java类

JSP指令

jsp九大内置对象-- 面试题

内置对象: 不需要创建,可以直接使用

四大域对象: pageContext, request,session,application

响应对象: response

响应流对象: out

配置对象: config

表示this: page

异常对象: exception

会话跟踪技术 Cookie Session

http是无状态的,服务器无法区分浏览器的请求是否来自同一个浏览器

Cookie特征:

创建于服务器, 保存在客户端浏览器, 以后每次请求, 把该服务器存在客户端的浏览器的cookie通过请求头带回到服务器

使用场景:用户名,密码保存到cookie,(记住密码)

提供方法: getName() getValue()

案例:记住密码

当用户登录页面, 勾选记住密码, 登录, 登录成功之后, 下一次再登录, 显示上一次登录的用户名和密码

思路:

LoginServlet:

  1. 判断是否登录成功
  2. 登录成功之后, 判断是否勾选"记住我"
  3. 如果勾选, 把用户名,密码保存到cookie,
  4. 如果没有勾选: 判断是否有用户名,密码的cookie, 如果有,就删除

login.jsp:

用户名,密码的表单值获取cookie的值,动态显示

<%= %> 往页面输出内容: 缺点:如果内容为null, 也会在页面显示

替换<%= %>, 使用EL表达式 : ${域中的属性名} 从全域获取数据

${域中的属性名} 全域查找:

​ 首先从page域查找,如果找到,直接返回

​ 如果没找到, 从request查找, 如果找到,直接返回

​ 如果没找到, 从session查找, 如果找到,直接返回

如果没找到, 从application查找, 如果找到,直接返回

如果没找到: 直接返回null

如果el表达式的结果为null, 在页面不展示

EL表达式支持 对象导航语言: ${对象.属性名..}

**前提:**域中存了user对象

java操作cookie:

服务器这边: 创建cookie: 构造方法 Cookie(String name,String value)

保存到客户端的方法: response对象的方法: addCookie(Cookie)

如果没有addCookie(), 那这个cookie不会保存到客户端

服务器获取cookie:

cookie是通过请求头传递到服务器:

request对象的Cookie[] getCookies()

Cookie的细节

  1. Cookie的max-age

    max-age: cookie最大存活时间 Cookie的setMaxAge(int )

    ​ 默认值: -1 在会话中存活, 打开浏览器到关闭浏览器,称为一次会话

    > 0 Cookie存活数值(秒)时间, 时间一到, 浏览器把cookie删除

    0: 立即删除Cookie

  2. Cookie的path

    设置Cookie的path, 限制那些资源允许访问

    资源的上级目录下的cookie可以访问

    资源的上上级目录的cookie可以访问

    /目录下Cookie可以访问.

    Cookie的path设置为/ ,表示该cookie可以被这个项目的所有的资源访问

  3. 修改Cookie的value

    调用Cookie的setValue()

    隐形修改:

    Cookie c2 = new Cookie(“name”,“wangwu”)

    如果客户端浏览器存在该key的cookie,并且path一样, 修改cookie的值

    如果客户端浏览器不存在该key的cookie, 添加

    如果客户端浏览器存在该key的cookie,但是path不一样, 添加

Cookie存放中文:

tomcat7之后可以存储了,不需要考虑

tomcat7以及之前的, Cookie不能存储中文, 需要把中文使用url编码

UTF-8: 中文(占3个字节): %两位十六进制%两位十六进制%两位十六进制

String str ="中国";  
//URL编码
String str1 = URLEncoder.encode(str, "UTF-8");
System.out.println(str1);//%E4%B8%AD%E5%9B%BD

//URL解码
String str2 = URLDecoder.decode(str1, "UTF-8");
System.out.println(str2);//中国
Tomcat8以及之后, Cookie支持中文, 如果有特殊符号, 不能存储, 借助url编码

HttpSession

主要作用:

实现一次会话多次请求之间数据的共享

一次会话的范围:

从打开浏览器访问服务器开始, 到关闭浏览器

使用Session

1.得到HttpSession对象 request.getSession() ; request.getSession(boolean)

getSession(): 如果当前请求有session,返回当前请求session的对象, 如果没有,创建一个新的session对象

getSession(boolean create):

true: 与getSession() 一样,

false: 如果当前请求有session,返回当前请求session的对象,如果没有, 返回null

2.删除Session void invalidate()

让session失效, 这个session无效, session中存储的数据都失效

3.设置session最大存活时间 void setMaxInactiveInterval(int interval) 单位:秒

Session默认的存放时间:

30分钟, 从上一次请求到下一次请求之间超过30分钟, session被服务器删除(Tomcat维护一个session池

Session的特征

创建于服务器, 保存于服务器

Session实现原理 面试题

服务器会为用户创建一个Session对象,并且把sessionId 以cookie的形式,保存在客户端浏览器上, 用户之后每次请求, 自动把cookie(JSESSIONID) 带回到服务器, 服务器根据sessionId匹配session池的对应的session的对象, 服务器知道当前请求是哪个会话的(来自哪个浏览器),

如果客户端的cookie被删除, 请求不会带JSessionId, 服务器就不知道哪个Session是这个用户的(浏览器的), 之前的为该用户创建的session,谁也无法访问,就是个垃圾,服务器默认30分钟之后删除这个session,

如果服务器把session删除, 就算客户端有JSessionid的Cookie, 也无法得到Session, 服务器会为浏览器重新创建Session,并新的sessionId以Cookie的形式保存客户端

案例:退出登录

1.点击退出按钮,发送请求到LogoutServlet

2.让session失效

3.重定向到login.jsp

案例:验证码的实现

生成验证码的servet将生成的验证码预先存储在session

request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);

1.用户填写验证码,点击登录,发送登录请求LoginServlet

2.判断验证码是否正确

3.不正确:直接响应“验证码错误”,转发到login.jsp

4.正确:重定向到index.jsp

案例:点击刷新验证码

<a href="javascript:;" onclick="refreshCode()" >
    <img src="${pageContext.request.contextPath}/checkCodeServlet" title="看不清点击刷新" id="vcode"/>
</a>


另一种写法
<a href="javascript:refreshCode();">
    <img src="${pageContext.request.contextPath}/checkCodeServlet" title="看不清点击刷新" id="vcode"/>
</a>
点击a标签后调用函数,点击a标签触发href里的地址,执行js
//切换验证码
function refreshCode(){
    
    
    //1.获取验证码图片对象
    var vcode = document.getElementById("vcode");

    //2.设置其src属性,加时间戳
    vcode.src = "${pageContext.request.contextPath}/checkCodeServlet?time="+new Date().getTime();
}

为什么加时间戳

防止浏览器缓存,如果地址栏不改变,服务器会认为没有发起新的请求,通过缓存展示上一次的资源,验证码也就不会更新

MVC

MVC是一种**软件架构模式,**这种模式把项目分为三大模块:

M: model 模型层: pojo, dao

C: controller 控制层: Servlet

V: view 视图层: jsp,html

java中视图层和模型层不能直接访问

javaWeb开发

经典三层模型, java类的分层概念

接收用户请求的角色: web层

处理业务逻辑的角色: service层

与数据库通信的角色: dao层

分层目的:技术隔离

比如dao层使用到的技术,只能在dao层存在, 不能延伸到其他

好处: 项目扩展时, 需要替换某一层的技术,只需要更换这一层,其他层不需要改变

注意事项:
  1. 跨层调用, 调用顺序: web层调用->service层调用->dao层
  2. 只能上层调用下层, web调用service, service调用到dao, 不能下层调用上层
  3. 层与层使用接口隔离, service:提供接口, 让web使用, dao层提供接口,让service使用

JSTL标签 (了解)

**作用:**替换Java脚本,通常和EL表达式一起使用

在服务器端执行, 把jstl执行之后的结果响应给客户端浏览器,JSTL标签在Html标签之前执行

使用步骤:

1.导入支持JSTL的依赖

2.在使用jstl标签的jsp页面, 使用 taglib指令,导入标签库

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

prefix: 前缀, 任意取名, 规范名: c (core标签库): 比如: <c:div> 使用前缀区分html标签

core所有的标签名: <c:标签名>

uri: 对应jstl标签的url, 固定写法, 导入jstl标签库, 选择的是 jsp/jstl的标签库

3.使用JSTL标签

常见JSTL标签

(1)<c:if test=“条件”> </c:if>>

(没有else标签,没有else if标签)

(2)choose标签
<c:choose>
      <c:when test="${score >= 90}">
          <p>优秀</p>
      </c:when>
      <c:when test="${score >= 80}">
          <p>良好</p>
      </c:when>
      <c:when test="${score >= 60}">
          <p>及格</p>
      </c:when>
      <c:otherwise>
          <p>不及格</p>
      </c:otherwise>
  </c:choose>
(3)foreach标签: for循环

for i

<c:forEach var="i" begin="0" end="9" step="2">
      <h1>${i}</h1>
 </c:forEach>

增强for循环:

<c:forEach var="admin" items="${admins}">
    <tr>
        <th>${admin.id}</th>
        <th>${admin.username}</th>
        <th>${admin.password}</th>
    </tr>
</c:forEach>
forEach循环 有一个varStatus=“变量” , 得到for循环的循环状态对象

forEach标签还有一个属性:varStatus,这个属性用来指定接收“循环状态”的变量名,例如:<forEach varStatus=”vs” …/>,这时就可以使用vs这个变量来获取循环的状态了。

vs的取值可以是:

  • count:int类型,当前已经遍历元素的个数(序号); 第几次循环,从1开始
  • index:int类型,当前元素的下标; 从0开始
  • first:boolean类型,是否为第一个元素;
  • last:boolean类型,是否为最后一个元素;

猜你喜欢

转载自blog.csdn.net/m0_48895748/article/details/127728805
今日推荐