Servlet(二)与JSP的学习笔记
- requset和response对象的原理
一、HttpServletReaquest类
1.1HttpServletRequest类有什么作用
- 每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中。然后传递到service方法(doGet和doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息。
1.2 HttpServletRequest类的常用方法
方法名 | 作用 |
---|---|
getRequestURI() | 获取请求的资源路径 |
getRequestURL() | 获取请求的统一资源定位符(绝对路径) |
getRemoteHost() | 获取客户端的ip地址 |
getHeader() | 获取请求头 |
getParameter() | 获取请求的参数 |
getParameterValues() | 获取请求的参数(多个值的时候使用) |
getMethod() | 获取请求的方式GET或POST |
setAttribute(key,value) | 设置域数据 |
getAttribute(key) | 获取域数据 |
getRequestDispatcher() | 获取请求转发对象 |
常用方法演示
@WebServlet(name = "ServletTest", value = "/test")
public class ServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String method = request.getMethod();
String contextPath = request.getContextPath();//获取项目名称
String requestURI = request.getRequestURI();//获取URI
StringBuffer requestURL = request.getRequestURL();//获取URL
String remoteAddr = request.getRemoteAddr();//获取客户端IP地址
String queryString = request.getQueryString();//get请求时获取请求参数
String protocol = request.getProtocol();//获取协议版本
// request 请求对象
System.out.println(method); //GET
System.out.println(contextPath); // /GuoQingWebDay01_war_exploded
System.out.println(requestURI); // /GuoQingWebDay01_war_exploded/test
System.out.println(requestURL); // http://localhost:8080/GuoQingWebDay01_war_exploded/test
System.out.println(remoteAddr); //0:0:0:0:0:0:0:1
System.out.println(queryString); //username=zhangsan&age=23
// username=%E5%BC%A0%E4%B8%89&age=%E5%8D%81%E5%85%AB%E5%B2%81
System.out.println(URLDecoder.decode(queryString, "utf-8"));
System.out.println(protocol); //HTTP/1.1
//URL:统一资源定位符 协议://ip:端口/资源路径
//URI: 统一资源标识符:
}
}
1.3 POST请求的中文乱码解决
@Override
protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{
//设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
req.setCharacterEncoding("UTF-8");
System.out.println("-------------doPost------------");
//获取请求参数
Stringusername=req.getParameter("username");
Stringpassword=req.getParameter("password");
String[]hobby=req.getParameterValues("hobby");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("兴趣爱好:"+Arrays.asList(hobby));
}
1.4 如何获取请求参数
表单
<body>
<formaction="http://localhost:8080/GuoQingWebDay01_war_exploded/parameterServlet"method="get">
用户名:<inputtype="text"name="username"><br/>
密码:<inputtype="password"name="password"><br/>
兴趣爱好:<inputtype="checkbox"name="hobby"value="cpp">C++
<inputtype="checkbox"name="hobby"value="java">Java
<inputtype="checkbox"name="hobby"value="js">JavaScript<br/>
<inputtype="submit">
</form>
</body>
java代码
@WebServlet(value = "/demo3", name = "parameterServlet")
public class parameterServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Get Post 获取请求参数,有个通用方法
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username);
System.out.println(password);
//针对复选框,用这个方法
String[] hobbies = request.getParameterValues("hobby");
System.out.println(Arrays.toString(hobbies));
System.out.println("=========================");
//request.getParameterMap(); 获取所有参数的map集合
Map<String, String[]> parameterMap = request.getParameterMap();
parameterMap.forEach((key, strings) -> System.out.println(key + "===" + Arrays.toString(strings)));
System.out.println("====================");
//request.getParameterNames(); 获取所有参数的名称 枚举 不常用 了解
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String key = parameterNames.nextElement();
System.out.println(key + "==" + request.getParameter(key));
}
}
二、HttpServletResponse类
2.1 HttpServletResponse类的作用
HttpServletResponse类和HttpServletRequest类一样。每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息,我们如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置
2.2 俩个输出流的说明
字节流 | getOutputStream() | 常用于下载(传递二进制数据) |
---|---|---|
字符类 | getWriter() | 常用于回传字符串(常用) |
- 两个流同时只能使用一个。使用了字节流,就不能再使用字符流,反之亦然,否则就会报错。
@WebServlet(value = "/demo7", name = "ServletDemo7")
public class ServletDemo7 extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// response 响应对象
System.out.println("请求来了");
//我想响应一些数据给浏览器,使用响应对象,来封装
//响应文本数据,其实响应HTML代码,也就是响应了一个HTML页面
PrintWriter writer = response.getWriter();
writer.write("<html>");
writer.write("<head>");
writer.write("<title>my page</title>");
writer.write("</head>");
writer.write("<body>");
writer.write("<h1 style='color:red'>");
writer.write("Welcome 欢迎光临我的首页");
writer.write("</h1>");
writer.write("</body>");
writer.write("</html>");
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
2.3 响应的乱码解决
-
响应中文时,他会乱码,为什么? 乱码问题,其实就是编解码用的码表不一致
-
web项目来说 乱码问题,其实就是服务器和浏览器使用的码表不一致
- Tomcat服务器,默认的使用的编码是 ISO-8859-1
- 浏览器在解码时,浏览器没有这个ISO-8859-1码表
- 我们可以在服务端来设置编码
//设置响应编码 //response.setCharacterEncoding("utf-8"); //还得告诉浏览器,服务端用的是utf-8编码,你浏览器切换成utf-8 来解码 //通过响应头,来告诉浏览器你用utf-8来解码 //response.setHeader("content-type", "text/html;charset=utf-8"); //以上两行代码,综合成一个方法 response.setContentType("text/html;chartset=UTF-8");
响应字节数据
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//可以下逻辑,比如说你是登录用户,我才会给你响应这张图片
//使用响应对象,响应字节数据
ServletContext servletContext = this.getServletContext();
//获取服务器真实路径
String realPath = servletContext.getRealPath("/WEB-INF/0.png");
System.out.println(realPath);
FileInputStream in = new FileInputStream(realPath);
//通过响应对象来获取输出流
ServletOutputStream out = resp.getOutputStream();
//读写图片响应
/* int len = 0;
byte[] bytes = new byte[1024];
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
out.flush();
}*/
//使用工具类 流的对拷
CopyUtils.copy(in, out);
in.close();
out.close();
//web项目的第三方jar 放在 WEB-INF/lib 目录
}
三、请求重定向
- 请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)。
@WebServlet(value = "/demo9", name = "ServletDemo9")
public class ServletDemo9 extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//重定向可以进行,资源(图片,servlet,页面,文件)的跳转
System.out.println("/demo9,请求来了");
//200 404 500
// response.setStatus(302); //重定向 设置响应状态码
//再设置响应头,让浏览器去找谁
// response.setHeader("location", "https://www.163.com");
//重定向时,要带上项目路径
// response.setHeader("location", "/ServletDemoDay01/Home.jsp");
//重定向,上面两步代码可以,简化成一个方法
response.sendRedirect("/ServletDemoDay01/Home.jsp");
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
- 总结一下 重定向的特点:
- 1.两次请求,两次响应
- 2.地址栏,会发生变化。
- 3.重定向,即可以跳转外部资源,也可以跳转自己服务器的资源,但是不能跳转到WEB-INF下资源
四、请求转发
- 什么是请求的转发?
- 请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发
demo5
@WebServlet(name = "ServletDemo5", value = "/demo5")
public class ServletDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("/demo5收到请求了");
//内部转发
request.getRequestDispatcher("/demo6").forward(request, response);
System.out.println("回到/demo5");
}
}
demo6
WebServlet(name = "ServletDemo6", value = "/demo6")
public class ServletDemo6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("/demo6收到请求了");
}
}
内部转发可以访问到WEB-INF下的资源
域对象:
ServletContext 全局域对象 ,代表整个 web 项目,范围最大
HttpServletRequest request 请求对象,他也是一个域对象,他代表的范围是一次请求和响应间,进行数据的共享
demo8
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("/demo8,收到请求了");
int num = 100;
//存到全局域对象
this.getServletContext().setAttribute("num", num);
String username = "张三";
//存到请求域
request.setAttribute("username", username);
//重定向,要写上项目路径,不要写死,动态取
// response.sendRedirect(request.getContextPath() + "/demo9");
//内部转发过去 ,不需要写项目路径
request.getRequestDispatcher("/demo9").forward(request, response);
}
demo9
@WebServlet(name = "ServletDemo9", value = "/demo9")
public class ServletDemo9 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("/demo9收到请求了");
ServletContext servletContext = this.getServletContext();
System.out.println(servletContext.getAttribute("num"));
System.out.println(request.getAttribute("username"));
}
}
当我们分别向全局域和请求域中存取数据时,不难发现第一次可以成功取到,但第二次,请求域中的数据为Null,这是因为一次请求一次响应,所以在使用重定向时是取不到请求域中的数据。
五、JSP
5.1 概述
- jsp的全换是javaserverpages。Java的服务器页面
- jsp的主要作用是代替Servlet程序回传html页面的数据
5.2 jsp的本质
- jsp页面本质上是一个Servlet程序
- 当我们第一次访问jsp页面时。Tomcat服务器会帮我们把jsp页面翻译成为一个java源文件。并且对进行编译成为.class字节码程序。我们打开java源文件不难发现其里面内容:
- 我们跟踪源代码发现,HttpJspBase类。它直接地继承了HttpServlet类。也就是说。jsp翻译出来的java类,它间接了继承了HttpServlet类。也就是说,翻译出来的是一个Servlet程序
- 总结:通过翻译的java源代码我们就可以得到结果:jsp就是Servlet程序。
- 翻译出来的Servlet程序的源代码,不难发现。其底层实现,也是通过输出流。把html页面数据回传给客户端。
5.3 jsp的三种语法
5.3.1 jsp头部的page指令
jsp的page指令可以修改jsp页面中一些重要的属性,或者行为。
<%@ page contetType=“text/html;charset=UTF-8” language=“java” % >
- language属性 表示jsp翻译后是什么语言文件。暂时只支持java。
- contentType属性 表示jsp返回的数据类型是什么。也是源码中response.setContebtType()参数值
- pageEncoding属性 表示当前jsp页面文件本身的字符集。
- import属性 跟java源代码中的一样,用于导包,导类。
- autoFlush 设置当out输出流缓冲区满了之后,是否自动刷新冲级区。默认值是true。
- butter属性 设置out缓冲区的大小。默认是8kb
- errorPage属性 设置当jsp页面运行时出错,自动跳转去的错误页面路径。
- iserrorPage属性 设置当前jsp页面是否是错误信息页面。默认是false。如果是true可以获取异常信息
- session属性 设置访问当前jsp页面,是否会创建HttpSession对象。默认是true。
- extends属性 设置jsp翻译出来的java类默认继承谁
5.3.2 JSP中常用脚本
Ⅰ、声明脚本
- 声明脚本的格式:<%! 声明java代码 %>
作用:可一给jsp翻译出来的java类定义属性和方法甚至是静态代码块,内部类等。
代码示例:
<%-- 1、声明类属性--%>
<%!
private Integer id;
private String name;
private static Map<String,Object> map;
%>
<%-- 2、声明static静态代码块--%>
<%!
static {
map=new HashMap<String,Object>();
map.put("key1","values");
map.put("key2","values")
}
%>
<%-- 3、方法--%>
<%!
public int abc(){
return 12;
}
%>
Ⅱ、表达式脚本
- 表达式脚本的格式是:<%=表达式%>
表达式脚本的作用是:的jsp页面上输出数据
表达式脚本的特点:
-
所有的表达式脚本都会被翻译到_jspService()方法中
-
表达式脚本都会被翻译成为out.print()输出到页面上
-
由于表达式脚本翻译的内容都在_jspService()方法中,所以_jspService()方法中的对象都可以直接使用
-
表达式脚本中的表达式不能以分号结束
练习:1.输出整型2.输出浮点型3.输出字符串4.输出对象
<%= 23%><br>
<%=23.23%><br>
<%="我是字符串"%><br>
<%=map%>
Ⅲ、代码脚本
- 代码脚本的格式是:<%java 语句%>
代码脚本的作用是:可以在jsp页面中,编写我们自己需要的功能(java语句)
代码脚本的特点是:
- 代码脚本翻译之后都在_jspService方法中
- 代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用
- 还可以由多个代码脚本块组合完成一个完整的java语句
- 还可以由多个代码脚本块组合完成一个完整的java语句
练习一:在jsp页面上输出九九乘法口诀表
<h1 align="center">九九乘法表</h1>
<table align="center">
<%
for (int i = 1; i < 10; i++) {%>
<tr>
<% for (int j = 1; j <=i; j++) {%>
<td> <%=j+"x"+i+"="+(i*j) %><td>
<%
}%>
</tr>
<% }
%>
</table>
练习二:jsp输出应一个表格,里面有十个学生信息
student类
public class Student {
private Integer id;
private String name;
private Integer age;
private String phone;
public Student() {
}
public Student(Integer id, String name, Integer age, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.phone = phone;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
serchStudentServlet程序:
@WebServlet(name = "SerchStudentServlet", value = "/serchStudentServlet")
public class SerchStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ArrayList<Student> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
int t=i+1;
list.add(new Student(t,"name"+t,18+t,"phone"+t));
}
request.setAttribute("studentList",list);
request.getRequestDispatcher("showStudent.jsp").forward(request, response);
}
}
showStudent.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
table{
border: 1px black solid;
width: 600px;
border-collapse: collapse;
}
td,th{
border: 1px blueviolet solid;
}
</style>
</head>
<body>
<%List<Student> studentList = (List<Student>) request.getAttribute("studentList");%>
<table>
<tr>
<td>编号</td>
<td>姓名</td>
<td>年龄</td>
<td>电话</td>
<td>操作</td>
</tr>
<%for(Student student:studentList){%>
<tr>
<td><%=student.getId()%></td>
<td><%=student.getName()%></td>
<td><%=student.getAge()%></td>
<td><%=student.getPhone()%></td>
<td>删除、修改</td>
</tr>
<%}%>
</table>
</body>
</html>
5.4 jsp九大内置对象
request | 请求对象 |
---|---|
response | 响应对象 |
pageContext | jsp的上下文对象 |
session | 会话对象 |
application | ServletContext对象 |
config | ServletConfig对象 |
out | jsp输出流对象 |
page | 指向当前jsp的对象 |
exception | 异常对象 |
5.5 jsp四大域对象
四个域对象分别是:
pageContext | PageContextimpl类 | 当前jsp页面范围内有效 |
---|---|---|
requsest | HttpServletRequest类 | 一次请求内有效 |
session | HttpSession类 | 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器) |
application | ServletContext类 | 整个web工程范围内都有效(只要web工程不停止,数据都在) |
- 域对象是可以像Map一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存取范围
- 四个域在使用的时候,优先顺序分别是,他们从小到大的范围的顺序:
pageContext== = = >>> request === = >> > session= = ==>>>application
xception** | 异常对象 |
5.5 jsp四大域对象
四个域对象分别是:
pageContext | PageContextimpl类 | 当前jsp页面范围内有效 |
---|---|---|
requsest | HttpServletRequest类 | 一次请求内有效 |
session | HttpSession类 | 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器) |
application | ServletContext类 | 整个web工程范围内都有效(只要web工程不停止,数据都在) |
- 域对象是可以像Map一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存取范围
- 四个域在使用的时候,优先顺序分别是,他们从小到大的范围的顺序:
pageContext== = = >>> request === = >> > session= = ==>>>application