tomcat+Servlet基础
一、web服务器
1、基础概念
web服务器是一个应用程序(软件),对HTTP协议的操作进行封装,目的是程序员不必直接对协议进行操作,让web开发更加便捷。将web项目部署到服务器上,对外提供“网上信息浏览服务”
Tomcat是一个轻量级的web服务器,支持Servlet/jsp等少量javeEE规范,也成为Servlet容器、web容器
2、 创建web项目
在idea中使用骨架方式创建一个Maven Web项目
<packaging>war</packaging>表示项目打包为war包,默认是jar包
在main下创建java和resources目录,有提示
将pom中的自动下载的插件去掉,build标签都删掉
3、使用tomcat插件
每次如果都部署项目都要打包放到文件夹里去,这样太慢了,使用tomcat插件会更加方便
1. 在pom文件中添加该插件的依赖alt+insert选择插件模板
名称是tomcat7-maven-plugin,groupId是org开头,2.2版本
还可以在插件中进行一些配置如下:
使用configuration标签中的port标签可以修改端口号,
path标签可以用来修改项目访问路径,如果不配置,需要在网址栏输入项目名称再输入要访问的资源,改成/ 这样可以省略掉项目名称直接输入要访问的资源
2.添加idea中的Maven Helper插件
可以直接在右侧栏Maven中运行:
使用插件更方便:
直接右键:可以点击编译运行等
二、Servlet
1.概念
1. Servlet是Java提供的一门动态web资源开发技术
2. Servlet是JavaEE规范之一,就是一个接口,我们需要定义Servlet类实现这个接口,并由web服务器运行Servlet
2.步骤
1.创建web项目,导入Servlet依赖坐标
alt+insert搜索servlet选择javax.servlet-api
添加之后由于项目在tomcat中运行,而tomcat中已经有了这个jar包,需要设置作用范围为provided
2.定义一个实现类,实现servlet接口,重写5个方法,可以在service中输出,service方法会自动执行
3.若要访问这个servlet需要给这个类提供@WebServlet(“/访问路径”)注解,添加 访问路径。之后就可以运行了
点击红色框的地址
地址栏输入ser1,控制台会输出那句话
3.servlet执行流程
创建项目实现了Servlet接口后,运行这个web项目是由tomcat完成的,
tomcat会自动创建一个实现类的对象,并且会自动执行service方法,
在地址栏中http://localhost:8080/tomcat/ser1中http://localhost:8080会访问到tomcat,加上tomcat会访问到创建的这个web项目,再加上ser1会访问到那个实现类。
4.Servlet体系结构
Servlet是体系根接口,有一个HttpServlet是对HTTP协议的封装的Servlet实现类,
以后自定义Servlet时都会继承HttpServlet
继承之后需要重写doGet和doPost方法
HttpServlet原理:获取请求方式,并根据请求方式调用不同的doXxx方法
5.urlPattern
Servlet要想被访问,必须配置其访问路径(urlPattern)
并且一个Servlet可以配置多个urlPattern
6.Request
在浏览器中访问一些资源时,会输入一些信息,而这些信息会被封装为一个Request对象传给服务器。
*由服务器tomcat来解析请求数据,封装为Request对象传递到service方法中。使用Request对象可以根据HttpServlet接口。可以通过Request对象获取这些信息。
*之后服务端又可以响应浏览器,将要响应的数据封装为Response对象再返回给浏览器,浏览器解析这些数据展现到页面上。
Request的继承体系:
ServletRequest:Java提供的请求对象根接口
HTttpServletRequest:Java提供的对HTTP协议封装的请求对象接口
RequestFacade:tomcat定义的实现类
1.获取请求数据
- 请求数据分为三部分:
- 请求行:GET/tomcat/req1?username=zhangsan HTTP/1.1
- getMethod():获取请求方式:GET
- getContextPath():动态获取项目访问路径(可以在配置文件里修改):/tomcat
- getRequestURL():获取URL:http://localhost:8080/tomcat/req1
- getRequestURI():获取URI:/tomcat/req1
- getQueryString():获取GET方式的请求参数:username=zhangsan
- 请求头:
- getHeader(String name):根据请求值名称获取值
- 请求体
- getInputStream():获取字节输入流
- getReader():获取字符输入流
- Request通用方式获取请求参数:
- getParameterMap():获取所有参数Map集合
- getParameterValues(String name):根据名称获取参数值(数组)
- getParameter(String name):根据名称获取参数值(单个值)
- 解决中文乱码问题
在浏览器一个表单里输入为中文时,返回到idea中显示的是乱码,因为tomcat中是ISO8859-1编码中文,而HTML是UTF-8编码,
- Post:设置输入流编码:.setCharsetEncoding(“UTF-8”)
- 通用方式:将字符串转为指定编码的字节数组再创建一个新的字符串指定要转成的编码。
String username = request.getParameter("username");
username=new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
System.out.println(username);
2.请求转发
是一种在服务器内部的资源跳转方式
实现:
req.getRequestDispatcher("资源B路径").forward(req,resp);
请求转发资源间数据共享
setAttribute(String name,Object,o);存储数据到request域中
getAttribute(String name);根据key获取值
removeAttribute(String name):根据key删除键值对
请求转发特点:
浏览器地址栏不变
只能转发到当前浏览器的内部资源
一次请求,可以在转发的资源间使用req共享数据
//demo2文件
System.out.println("demo2");
req.setAttribute("username","张三");
req.getRequestDispatcher("/demo3").forward(req,resp);
//demo3文件
System.out.println("demo3");
Object attribute = request.getAttribute("username");
System.out.println(attribute);
demo2
demo3
张三
7. Response
通过 Request对象来获取请求数据
通过 Response对象来设置响应数据
1.设置响应数据
响应数据分为3部分:
- 响应行:HTTP/1.1 200 OK
setStatus(int sc):设置响应状态码 - 响应头:Content-Type:text/html
setHeader(String name,String value):设置响应头键值对 - 响应体:
getWriter():获取字符输出流
getOutputStream():获取字节输出流
2.重定向
一种资源跳转方式
浏览器请求资源1,但资源1无法处理,设置响应状态码为302,再设置响应头的location为资源2的访问路径,由资源2处理
重定向特点:
1.浏览器地址栏发生变化
2.可以重定向到任意位置(服务器内部、外部)
3.是两次请求,不能在多个资源中共享数据
//demo3文件
String path = request.getContextPath();
System.out.println("d1");
response.setStatus(302);
response.setHeader("location",path+"/demo2");
//重定向简化书写:sendRedirect,替换原来的两行
response.sendRedirect(path+"/demo2");
//demo2文件
System.out.println("d2");
d2
d1
3.Response响应数据
Response响应字节数据
要想将字节数据写回到浏览器,我们需要两个步骤:
通过Response对象获取字节输出流:ServletOutputStream outputStream = resp.getOutputStream();
通过字节输出流写数据: outputStream.write(字节数据);
Response响应字符数据
要想将字符数据写回到浏览器,我们需要两个步骤:
通过Response对象获取字符输出流: PrintWriter writer = resp.getWriter();
通过字符输出流写数据: writer.write(“aaa”);
// 返回一个中文的字符串你好,需要注意设置响应数据的编码为utf-8
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("qazxsw");
//content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
writer.write("<br><h1>jiafanchen</h1>");
// 注意:一次请求响应结束后,response对象就会被销毁掉,所以不要手动关闭流。
FileInputStream fileInputStream = new FileInputStream("d://0.jpg");
ServletOutputStream outputStream = response.getOutputStream();
byte[] bytes=new byte[1024];
int len=0;
while ((len=fileInputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
fileInputStream.close();
//通过commons-io的IO工具类简化,导入依赖
IOUtils.copy(fileInputStream,outputStream);
fileInputStream.close();
三、会话跟踪
会话:用户打开浏览器,访问web服务器,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应
会话跟踪:服务器需要识别多次请求是否来自同一浏览器,以便在同一次会话的多次请求间共享数据
Http协议是无状态的,每次浏览器向服务器请求时,服务器都会将该请求视为新的请求,因此我们需要会话跟踪技术来实现会话内的数据共享
实现方式:
1. 客户端会话跟踪技术:Cookie
2. 服务端会话跟踪技术:Session
1.Cookie
客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问
1. 发送Cookie
1. 创建Cookie对象,设置数据
new Cookie("key","value")
2. 发送Cookie到客户端:使用response对象
response.addCookie(cookie);
2. 获取Cookie
1. 获取客户端携带的所有Cookie,使用request对象
Cookie[] cookies=request.getCookies();
2. 遍历数组,获取每一个Cookie对象
3. 使用Cookie对象方法获取数据
cookie.getName();
cookie.getValue();
3. Cookie原理
1. 服务器给浏览器发送Cookie数据,tomcat会进行解析并给Cookie数据加上响应头set-cookie,对应的值就是cookie数据
2. 浏览器接收到会对这个响应头解析,将cookie数据保存到浏览器内存中。下一次访问时浏览器会携带所有的cookie数据去访问,这些数据会加上请求头cookie
Cookie的实现是基于HTTP协议的
响应头:set-cookie
请求头:cookie
3. Cookie存活时间
默认情况,Cookie存储在浏览器内存中,当浏览器关闭时,内存释放,Cookie被销毁
通过setMaxAge(int seconds):设置Cookie存活时间。默认负数表示存到浏览器内存中。设置为正数,表示将Cookie写入浏览器所在电脑的硬盘中,到时间后自动删除。
4. Cookie不能直接存储中文,需要通过URL编码进行存储。获取Cookie时再通过URL解码
String s="贾凡琛";
s = URLEncoder.encode(s, "utf-8");
Cookie cookie = new Cookie("user", s);
response.addCookie(cookie);
Cookie[] cookies = request.getCookies();
for (Cookie cookie :cookies) {
if ("user".equals(cookie.getName())){
System.out.println(cookie.getName()+":"+ URLDecoder.decode