HTTP
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是由W3C(万维网联盟)组织制定的一种应用层协议,是用来规范浏览器与Web服务器之间如何通讯的数据格式,主要涉及浏览器的发请求格式和服务器的响应格式。
HTTP协议通常承载于TCP协议之上,而承载于TLS或SSL协议层之上的协议就是常说的HTTPS协议。
HTTP默认的端口号为80,HTTPS默认的端口号为443。
简单地说,就是对两台计算机收发数据的格式的一种规定。
请求与响应
HTTP有请求与响应的概念。发送数据是发送请求,接收数据是接收响应。
请求/响应的格式为 请求/响应行 请求/响应头 空白行 请求/响应体
//请求行 POST /task01_demo01/demo1.html HTTP/1.1 //请求头 我可没说请求头只有一行,可以很长 Host: localhost:8088 Content-Length: 21 Cache-Control: max-age=0 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) //下一行是空白行 name=scott&pwd=123456 //这些是请求体
下面是响应的例子,对照上面的看很好懂。
HTTP/1.1 200 OK Content-Type: text/html Content-Length: 588 Date: Thu, 08 Sep 2021 12:59:54 GMT <html><head><title>示例1</title></head> <body><h1>这是一个HTML页面</h1></body> </html>
Tomcat
用户会访问网站上的资源,资源应该部署在服务器里。服务器分静态服务器和动态服务器。
Tomcat就是很有名的一款动态服务器。
目录结构
bin 主要存放二进制可执行文件和脚本。
conf 主要存放各种配置文件。
lib 主要用来存放Tomcat运行需要加载的jar包。
logs 主要存放Tomcat在运行过程中产生的日志文件。
temp 主要存放Tomcat在运行过程中产生的临时文件。
webapps 主要存放应用程序,当Tomcat启动时会去加载该目录下的应用程序。
work 主要存放tomcat在运行时的编译后文件,例如JSP编译后的文件。
启动与关闭
双击bin目录下的startup.bat启动,双击bin目录下的shutdown.bat关闭(点X也行,懂吧?我是高档人士)。
正常来说,双击startup.bat之后,一个控制台窗口会一直存在。但有人的控制台窗口会闪退,这是没有配置环境变量JAVA_HOME造成的。
第一次启动,会发现程序正常运行,但是控制台显示的日志是乱码。乱码问题是因为对数据的编码和解码的格式不一样。控制台默认解码方式是GBK,而Tomcat的日志数据默认编码方式是UTF-8。所以简单起见可以把Tomcat的编码方式变成GBK。方法是修改conf目录下的logging.properties。
修改端口号
HTTP协议的默认端口号是80,如果你在自己的电脑上访问自己电脑上的Tomcat,需要显式写好localhost:8080。但如果你把Tomcat的默认端口号改成80的话,就可以不写端口号进行访问了。
修改方式是 找到conf目录下的server.xml,里面Connector开头的标签后面的端口号就是Tomcat的默认端口号。
部署静态资源
在webapps文件夹下创建一个文件夹,文件夹里写点html
接着只需要访问http://localhost:8080/文件夹名/文件名 即可访问静态资源
如果直接访问http://localhost:8080 则会去寻找ROOT文件夹下的index文件
在IDEA里创建web项目
选择java enterprise即可
Servlet
可以运行在Tomcat上的java类
编写servlet的步骤
1 建项目
2 实现Servlet接口并重写service方法/继承GenericServlet并重写service方法/继承HttpServlet类
3 配置servlet到xml文件里(现在也可以用注解)
web.xml写法如下例
<!-- 配置Servlet --> <servlet> <!-- HelloServlet是Servlet类的别名 --> <servlet-name> HelloServlet </servlet-name> <!-- 这里给路径 --> <servlet-class> com.example.HelloServlet</servlet-class> </servlet> <!-- 映射Servlet --> <servlet-mapping> <!-- HelloServlet是Servlet类的别名,与上述名称必须相同 --> <servlet-name> HelloServlet </servlet-name> <!-- /hello是供浏览器使用的地址 --> <url-pattern> /hello </url-pattern> </servlet-mapping>
最好还是继承HttpServlet
HTTPServlet
常见方法如下
可别傻乎乎的自己new class然后一顿写了,idea什么都能做的。。。
Servlet生命周期
构造方法只被调用一次(实例化阶段),当第一次请求Servlet时调用构造方法来创建Servlet的实例。
init方法只被调用一次,当创建好Servlet实例后立即调用该方法实现Servlet的初始化。
service方法被多次调用,每当有请求时都会调用service方法来用于请求的响应。
destroy方法只被调用一次,当该Servlet实例所在的Web应用被卸载前调用该方法来释放当前占用
的资源。
GET/POST简介
一般来说,超链接、浏览器访问、method=GET前提下发送的表单用的是GET。
method=POST前提下发送的表单用的是POST
GET会把发送的数据都接到URL后面
POST不会,POST会把数据塞到请求体里
HttpServletRequest
先看看父类常用的方法:
再看看本类的常用方法:
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); System.out.println("name: " + name); String[] hobbies = request.getParameterValues("hobby"); System.out.println("hobbies: " + Arrays.toString(hobbies)); Enumeration<String> parameterNames = request.getParameterNames(); System.out.println("parameterNames: "); while (parameterNames.hasMoreElements()) { System.out.println(parameterNames.nextElement()); } System.out.println("URI: " + request.getRequestURI()); System.out.println("URL: " + request.getRequestURL()); System.out.println("METHOD: " + request.getMethod()); System.out.println("QUERY: " + request.getQueryString()); System.out.println("Servlet Path: " + request.getServletPath()); }
(Http)ServletResponse
常用方法
以及
有个问题就是response的默认编码方式是ISO-8859-1,这样发中文会乱码。
应该在发消息前setContentType("text/html;charset=UTF-8");
解决接收中文乱码问题
GET(低版本才有问题)
// 接收到get请求的中文字符串 String name = request.getParameter("name"); // 将中文字符重新编码,默认编码为ISO-8859-1 String userName = new String(name.getBytes(“ISO-8859-1”),“utf-8");
POST
//接收之前设置编码方式: request.setCharacterEncoding(“utf-8”) //提示: //必须在调用request.getParameter(“name”)之前设置
ServletConfig
常用方法
ServletContext
javax.servlet.ServletContext接口主要用于定义一组方法,Servlet使用这些方法与它的Servlet容器通信。
服务器容器在启动时会为每个项目创建唯一的一个ServletContext对象,用于实现多个Servlet之间的信息共享和通信。
在Servlet中通过this.getServletContext()方法可以获得ServletContext对象。
重定向
首先客户浏览器发送http请求,当web服务器接受后发送302状态码响应及对应新的location给客户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址,服务器根据此请求寻找资源并发送给客户。
在servlet里,只需要response.sendRedirect()即可
转发
在servlet的语义下,指的是一个Web组件(Servlet/JSP)将未完成的处理通过容器转交给另外一个Web组件继续处理,转发的各个组件会共享Request和Response对象。
具体使用:
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { RequestDispatcher requestDispatcher = request.getRequestDispatcher("target.html"); requestDispatcher.forward(request, response); }
转发之后浏览器地址栏的URL不会发生改变。
转发过程***享Request对象。
转发的URL不可以是其它项目工程。
Servlet与多线程
Servlet是共享资源。服务器对每个请求都会创建一个线程,但每个服务只有一个servlet实例。这会出现问题。
解决方案也很简单,就是加锁。
生命周期
默认情况下,浏览器会将Cookie信息保存在内存中,只要浏览器关闭,Cookie信息就会消失。
如果希望关闭浏览器后Cookie信息仍有效,可以通过Cookie类的成员方法实现。
int getMaxAge() //返回cookie的最长使用期限(以秒为单位) void setMaxAge(int expiry) //设置cookie的最长保留时间(秒) -1则是关闭浏览器后失效
路径
浏览器在访问服务器时,会比较Cookie的路径与请求路径是否匹配,只有匹配的Cookie才会发送给服务器。
Cookie的默认路径等于添加这个Cookie信息时的组件路径,例如:/项目名/目录/add请求添加了一个Cookie信息,则该Cookie的路径是 /项目名/目录。
请求的地址必须符合Cookie的路径或者是其(直接)子路径时,浏览器才会发送Cookie信息。
void setPath(String uri) //设置cookie的路径信息
Cookie
Cookie本意为”饼干“的含义,在这里表示客户端以“名-值”形式进行保存的一种技术。
浏览器向服务器发送请求时,服务器将数据以Set-Cookie消息头的方式响应给浏览器,然后浏览器会将这些数据以文本文件的方式保存起来。
当浏览器再次访问服务器时,会将这些数据以Cookie消息头的方式发送给服务器。
常用方法
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) System.out.println(cookie.getName() + " " + cookie.getValue()); System.out.println("here"); Cookie cookie = new Cookie("name", "Ohio"); response.addCookie(cookie); System.out.println("cookie added"); }
Session
Session本意为"会话"的含义,是用来维护一个客户端和服务器关联的一种技术。
浏览器访问服务器时,服务器会为每一个浏览器都在服务器端的内存中分配一个空间,用于创建一个Session对象,该对象有一个id属性且该值唯一,我们称为SessionId,并且服务器会将这个SessionId以Cookie方式发送给浏览器存储。
浏览器再次访问服务器时会将SessionId发送给服务器,服务器可以依据SessionId查找相对应的Session对象。
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); System.out.println(session.isNew() ? "new" : "old"); System.out.println("session id is " + session.getId()); session.setAttribute("name", "purdue"); System.out.println("attribute is " + session.getAttribute("name")); session.removeAttribute("name"); System.out.println(session.getMaxInactiveInterval()); session.setMaxInactiveInterval(1200); //1200s }
session的生命一般是30min。
getMaxInterval() setMaxInterval()可以获取/设置失效时间。
当然也可以用配置文件去修改相关配置。
特点
数据比较安全。
能够保存的数据类型丰富,而Cookie只能保存字符串。
能够保存更多的数据,而Cookie大约保存4KB。
数据保存在服务器端会占用服务器的内存空间,如果存储信息过多、用户量过大,会严重影响服务
器的性能。