Servlet与JSP进阶

来自mkw的视频课程的总结

1.前言

内容包括 掌握Java Web核心特性,Servlet核心对象以及JSP九大内置对象。主要有以下的内容:

  • 请求结构 && 响应结构
  • 请求转发重定向
  • Cookie && Session
  • ServletContext 与三大作用域
  • 请求响应中文乱码问题解决
  • Web.xml常用配置
  • JSP九大内置对象
  • web应用程序打包和发布

2. 请求结构

请求行,请求头,请求体

请求头包括Accept-Language:zh-CN(国际化),Content-Type等 浏览器的辅助信息。

对于get请求,请求的内容一般放在 query String Parameters,在POST中放在From Data中,此外,格式内容都一样

UserAgent适用于不同终端的开发

3.响应结构

状态码:200 404 500 403(服务器拒绝访问) 301/302 400(无效请求)

Content-Type明确网页解析响应体的格式,一般为 text/html, plain是原文 application/x-msdownload

4.请求转发与响应重定向

从一个页面自动跳转到另一个页面

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("用户登陆成功!");
//实现了请求转发的功能
req.getRequestDispatcher("/direct/index").forward(req,resp); // 响应重定向 需要增加 contextPath
resp.sendRedirect("/Servlet_advanced_war_exploded/direct/index");
}

二者的区别,表面上看是 最终的URL不同,请求转发的URL是最初的 /direct/check,而响应重定向是 /direct/index,内容都是 index的内容

二者原理的区别:

请求转发:Tomcat服务器内部,Servlet1处理后,在req.getRequestDispatched().forward()语句下,将原请求原封不动转交给Servlet2。

响应重定向:浏览器跳转,产生两次请求,语句是response.sendRedirect(),这里响应1不是html网页,而是告诉浏览器再发送一个请求给Servlet2的地址。

4.1 设置请求自定义属性

  • 允许创建自定义属性
  • 设置请求属性: request.setAttribute(属性名,属性值)
  • 获取请求属性: request.getAttribute(属性名,属性值)

5.Cookie

​ Cookie的引文原意是“点心”,它是在客户端访问Web服务器时,服务器在客户端硬盘上存放的信息,好像是服务器发送给客户的“点心”。服务器可以根据Cookie来跟踪客户状态(之前是否已经登录),这对于需要区别客户的场合(如电子商务)特别有用。

​ 当客户端首次请求访问服务器时,服务器先在客户端存放包含该客户的相关信息的Cookie,以后客户端每次请求访问服务器时,都会在HTTP请求数据中包含Cookie,服务器解析HTTP请求中的Cookie,就能由此获得关于客户的相关信息。

Cookie是浏览器保存本地,记录用户登录状态和资料的文本,具有时效性,默认是浏览器关闭Cookie就会被清空,可以用setMaxAge()设置。Cookie内容会伴随请求发送给Tomcat,常用的方法有:

LoginServlet.java

@WebServlet("/cookies/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("用户登录成功");
Cookie cookie = new Cookie("user","admin");
cookie.setMaxAge(60*60*4*7);
resp.addCookie(cookie);
resp.getWriter().println("login success");
}
}

IndexServlet.java

@WebServlet("/cookies/index")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie[] cs = req.getCookies();
String user = null; //防止空指针异常 for(Cookie c:cs) {
if(c.getName().equals("user")) {
user = c.getValue();
break;
}
System.out.println(c.getName() + ": " + c.getValue());
} if(user == null) {
resp.getWriter().println("User no login in");
} else {
resp.getWriter().println("User:" + user);
}
}
}

6.Session

  • Session(用户会话)用于保存与“浏览器窗口”(并不是实际的浏览器窗口)对应的数据;
  • 存储在Tomcat服务器内存中,具有时效性(默认30min没有用到就会被销毁);
  • Session通过浏览器Cookie的SessionID值针对性提取用户数据;

Cookie中保存的sessionID将 cookie和对应的session连接在一起,这里有一个问题需要清楚:

Cookie的生命周期是和浏览器绑定在一起的,关闭浏览器后Cookie(包含sessionID)就会被清除,而一个session的在Tomcat的生命周期是 30min,二者不矛盾。下面内容引用自请叫我丁木西

那么为什么当我们关闭浏览器后,就再也访问不到之前的session了呢?其实之前的Session一直都在服务器端,而当我们关闭浏览器时,此时的Cookie是存在于浏览器的进程中的,当浏览器关闭时,Cookie也就不存在了。其实Cookie有两种:

一种是存在于浏览器的进程中; 一种是存在于硬盘上。

session的Cookie是存在于浏览器的进程中,那么这种Cookie我们称为会话Cookie,当我们重新打开浏览器窗口时,之前的Cookie中存放的Sessionid已经不存在了,此时服务器从tpServletRequest对象中没有检查到sessionid,服务器会再发送一个新的存有Sessionid的Cookie到客户端的浏览器中,此时对应的是一个新的会话,而服务器上原先的session等到它的默认时间到之后,便会自动销毁

附加

当在同一个浏览器中同时打开多个标签,发送同一个请求或不同的请求,仍是同一个session;

当不在同一个窗口中打开相同的浏览器时,发送请求,仍是同一个session; 这个不太好理解

当使用不同的浏览器时,发送请求,即使发送相同的请求,是不同的session;

当把当前某个浏览器的窗口全关闭,再打开,发起相同的请求时,是不同的session。

Code demo

SessionLoginServlet

package com.imooc.servlet.session;

import com.sun.xml.internal.ws.addressing.WsaActionUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session/login")
public class SessionLoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("登录成功");
HttpSession session = req.getSession();
String sessionId = session.getId();
System.out.println(sessionId);
session.setAttribute("name","张三");
req.getRequestDispatcher("/session/index").forward(req,resp); //请求转发到 "/session/index"
}
}

SessionIndexServlet.java

package com.imooc.servlet.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException; @WebServlet("/session/index")
public class SessionIndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
String sessionId = session.getId();
System.out.println(sessionId);
String name = (String) session.getAttribute("name");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("这是首页,当前用户" + name);
}
}

7.ServletContext与三大作用域对象

7.1 ServletContext

  • ServletContext(Servlet上下文对象),是Web应用全局对象

  • 一个Web应用只会创建一个ServletContext对象

  • ServletContext随着Web应用启动而自动创建

ServletContext适合整个应用/网站的全局信息,在每一个页面都有的,比如页脚的网站的备案信息等。

Code Demo

ContextInitServlet.java

package com.imooc.servlet.ServletContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet("/context/init")
public class ContextInitServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = req.getServletContext();
context.setAttribute("copyright","@ 2020 www.imooc.com 京");
context.setAttribute("title","慕课网-程序员的梦工厂");
resp.getWriter().println("Init Success");
}
}

ServletDefaultServlet.java

package com.imooc.servlet.ServletContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet("/context/default")
public class ServletDefaultServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = req.getServletContext();
String copyright = (String) context.getAttribute("copyright");
String title = context.getAttribute("title").toString();
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().println("<h1>" + title + "</h1>" + copyright);
}
}

与前面不同,当先后访问两个页面之后关闭浏览器,再打开新浏览器直接访问 "/context/default"。结果不变,这是因为ServletContext是应用全局对象,只要应用启动初始化后,就一直存在。

7.2 Java-Web 三大作用域对象

  1. HttpServletRequest 请求对象-瞬时对象;
  2. HttpSession 用户会话对象- 用户第一次请求访问开始创建,然后30min没有用到就会被销毁;
  3. ServletContext web应用全局对象,web启动后就被创建,生命周期最久。

8.Web请求&响应中文乱码

Tomcat默认使用字符集ISO-8859-1,属于西欧字符集,解决乱码即用UTF-8替换即可,在Servlet中,请求与响应都需要设置UTF-8字符集

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body> <form action="/Servlet_advanced_war_exploded/charset/process" method="post">
姓名:<input name="ename">
地址:<input name="address">
<input type="submit" value="提交">
</form> </body>
</html>
package com.imooc.servlet.charset;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet("/charset/process")
public class CharsetServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//方法2 req.setCharacterEncoding("UTF-8");
String ename = req.getParameter("ename");
String address = req.getParameter("address");
//方法1
// String utf8ename = new String(ename.getBytes("iso-8859-1"), "utf-8")
System.out.println(ename + ":" + address);
}
}

控制台产生:???:???é??,解决方案是 单个语句转换可以使用方法1,全局设置可以使用方法2

get请求乱码解决

在 Tomcat version >=8版本不存在这个问题,但是 低版本可以修改 Tomcat安装目录 conf/server.xml 的第69行

添加 URIEncoding="UTF-8" ,即修改成

解决

9.Web.xml常用配置

Web.xml是Java Web项目最重要的配置文件

9.1 默认首页

在默认创建项目后的Web.xml中,会存在如下代码:

<welcom-first>index.html</welcom-first>
<welcom-first>index.htm</welcom-first>
<welcom-first>index.jsp</welcom-first>
<welcom-first>default.html</welcom-first>
<welcom-first>index.htm</welcom-first>
<welcom-first>index.jsp</welcom-first>

功能是 如果在Web目录下有任何一个上述的文件,都会成为其默认的首页,可以用户自定义,同时定义了二级目录中默认的页面

9.2 使用WebServlet通配符

某些URL前缀相同的请求都会被拦截

package com.imooc.servlet.pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; public class PatternServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = req.getRequestURL().toString();
System.out.println(url);
String id = url.substring(url.lastIndexOf("/") + 1);
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println(id); if(id.equals("1")) {
out.println("张三");
}else if(id.equals("2")) {
out.println("李四");
}else {
out.println("其他员工");
}
}
}

Web.xml 添加如下信息:

    <servlet>
<servlet-name>patternServlet</servlet-name>
<servlet-class>com.imooc.servlet.pattern.PatternServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>patternServlet</servlet-name>
<url-pattern>/pattern/*</url-pattern>
</servlet-mapping>

9.4 全局参数的配置

在Web.xml中可以定义全局参数

 <context-param>
<param-name>copyright</param-name>
<param-value>@2021 imooc.com 京</param-value>
</context-param>
<context-param>
<param-name>title</param-name>
<param-value>慕课网-程序员的梦工厂</param-value>
</context-param>

在Java中获取

String copyright = context.getInitParameter("copyright");

9.3 404 500页面设置

在web项目下新建 error目录,然后新建 404.html和 500.html。在Web.xml上添加

<error-page>
<error-code>404</error-code>
<location>/error/404.html</location>
</error-page> <error-page>
<error-code>500</error-code>
<location>/error/500.html</location>
</error-page>

如此设置是避免程序错误产生的系统报错信息直接显示在页面上,泄露一些程序的逻辑信息,提高安全性。

10.JSP九大内置对象

就是不同对象的简略写法。

11.Java-Web打包与发布

  • Java Web应用采用war包进行发布
  • 发布路径: {Tomcat_Home}/webapps
  • Eclipse支持war包导出

这里发现在 server.xml中无法设置 端口号和 path 的默认,找不到视频中要修改的东西。

IDEA打包war 参考小白马上飞Tanyiqu-bili 两个帖子

Servelt&&JSP进阶的更多相关文章

  1. JSP进阶 之 SimpleTagSupport 开发自定义标签

    绝大部分 Java 领域的 MVC 框架,例如 Struts.Spring MVC.JSF 等,主要由两部分组成:控制器组件和视图组件.其中视图组件主要由大量功能丰富的标签库充当.对于大部分开发者而言 ...

  2. jsp进阶

    Jsp,前段的数据读取到后端 获取前段输入框数据 request.getParameter(前段输入框的name值) Request.代表转发,(代码在服务器内部执行的一次性请求,url地址不会发生改 ...

  3. 9.JSP进阶

    1.JSP内置对象 JSP容器在_jspService()方法中声明并初始化9个内置对象. 名称 作用 接口/类 out 客户端打开的输出流 javax.servlet.jsp.JspWriter 接 ...

  4. tomcat各版本和jsp、jstl、servlet的依赖关系(转)

    Servlet / JSP / Tomcat  Version  Servlet/ JSP    Tomcat  2.5/2.1 6.0.18 2.4/2.0 5.5.27 2.3/1.2 4.1.3 ...

  5. JSP概述

    一.JSP页面本质上时一个Servlet,然而,用JSP开发比使用Servlet更容易,主要有两个原因,首先不必编译Servlet,其次JSP页面是一个以.jsp为扩展名的文本文件,可以使用任何编辑器 ...

  6. JavaWeb学习记录(十九)——jstl自定义标签之简单标签

    一.简单标签共定义了5个方法: setJspContext方法 setParent和getParent方法 setJspBody方法 doTag方法 二.方法介绍 osetJspContext方法 用 ...

  7. Java并发简介

    年轻的时候学会了“使用”Servlet后,感觉自己什么都会做了,之后就不停的写所谓的业务逻辑,框架(这里说的不是structs,spring等,就是说servlet)给人们屏蔽了很多复杂性(更别说构建 ...

  8. Maven 初学+http://mvnrepository.com/

    了解 maven是一款服务于java平台的自动化构建工具(项目管理工具) 构建:全方位.多角度.深层次地建立 项目构建是一个项目从:源代码.编译.测试.打包.部署.运行的过程 用来解决团队开发遇到的问 ...

  9. 【Web】CSS中的浮动float

    CSS中的float 文章目录 CSS中的float 1.float浮动属性 2.float文字环绕图片 3.float浮动的真正原因以及副作用分析 4.清除浮动的四种解决方法 5.实际应用 导航效果 ...

随机推荐

  1. PostgreSQL用户和权限问题

    PostgreSQL用户 其实用户和角色都是角色,只是用户是具有登录权限的角色. 创建用户 create user sonar password '123'; 删除用户 drop user sonar ...

  2. .NET Core授权失败如何自定义响应信息?

    前言 在.NET 5之前,当授权失败即403时无法很友好的自定义错误信息,以致于比如利用Vue获取到的是空响应,不能很好的处理实际业务,同时涉及到权限粒度控制到控制器.Action,也不能很好的获取对 ...

  3. MySQL 卡死的问题

    1. 执行show full processlist观察state和info两列,查看有哪些线程在运行. 2.使用kill命令+对应线程前面id杀死卡死的线程. 其他的方式: -- 查询是否锁表 sh ...

  4. ios关键字

    self:类似JAVA中的this指针,是隐藏参数,指向当前调用方法的类 super:调用父类的方法 if(self=[super init]),是一种通用写法,赋值并测零是为了防止超类在初始化过程中 ...

  5. WPF教程十五:数据模板的使用(重发)

    数据模板 数据模板是一段如何显示绑定在VM对象的XAML代码.数据模板可以包含任意元素的组合,基于Binding来显示不同的信息. 在实际的开发中数据模板的应用场景很多,同样一个控件可以根据不同的绑定 ...

  6. 机器学习Sklearn系列:(三)决策树

    决策树 熵的定义 如果一个随机变量X的可能取值为X={x1,x2,..,xk},其概率分布为P(X=x)=pi(i=1,2,...,n),则随机变量X的熵定义为\(H(x) = -\sum{p(x)l ...

  7. 「CF521D」 Shop

    「CF521D」 Shop 传送门 题目说是有三种操作,首先可以知道赋值操作是可以转化为加法操作的,即 \((1,b) \rightarrow (2,b-a_i)\) 然后加法对于一个数你肯定优先选择 ...

  8. C语言:体现\r的结果

    #include <stdio.h> #include <windows.h> //体现\r的结果 //转义字符\r,回车,将光标移动到当前行最开始 main() { char ...

  9. python 模拟点击微信

    from PyQt5 import QtCore,QtWidgets import win32gui, win32api, win32con # 调用win32api的模拟点击功能实现ctrl+v粘贴 ...

  10. flutter实战demo,仿luckin coffee。

    flutter_luckin_coffee flutter luckin coffee application(仿瑞幸咖啡) 目录 前言 安卓扫码体验 flutter版本信息 安装 相关插件 维护者 ...