1. java基础
1.1. 修饰符
1.1.1. final
2. servlet
2.1. http协议
http://ip:端口/资源路径?name=
eg : http://127.0.0.1/myweb/servlet?name = zhangsan
- 支持客户/服务端
- 支持get ,post请求
- 传输内容,类型可以有Content-Type
- http无连接,http1.1之后支持可持续连接
- http无状态信息
2.1.1. 请求和responce
2.1.1.1. 请求request
请求行
get的请求放在请求行中
method Request_url http_version 换行
请求头
- 键值对
请求体
- get没有请求行
2.1.1.2. response
- 状态行
- 响应头
- 响应正文
2.1.2. 消息头
- referer: 请求前来位置
- Location: 请求达到位置
- refresh: 自动跳转时间
2.2. 服务器
接受客户端的请求,调用程序处理,返回程序数据
2.2.1. tomcat目录
- bin: 启动或关闭的配置文件
- conf: 配置servel端口号等信息文件
- lib: 运行时使用的java包
- logs :日志文件
- webapps: web应用
- works: 工作目录
2.2.2. 使用idea 集成tomcat
2.3. servlet实现
- 创建java类
- 实现servlet规范, 继承HttpServlet类
- 重写service 方法,用于处理请求
- 设置注释,指定访问方法的路径
@Webservlet(name = , value ={ , }) value可以指定多个名称
2.3.1. servlet执行流程
- 从请求头中找到主机
- 访问请求头中的资源,第一次访问创建一个对象
- 将参数交给req, 通过resp响应参数
2.3.2. 三种访问方式
继承方式
HttpServlet -> GenericServlet > Servlet
2.3.3. service ,doPost, doGet
调用service 实际上调用doPost, doGet
不知道post 或 get ,写service
2.3.4. servlet生命周期
请求访问servlet容器时候,检查容器中是否存在该资源对象,没有调用init方法,第二次访问时,调用service.程序停止售,调用destory方法
2.3.5. HttpServletRequest 获取请求
HTTp的请求都封装在Req对象中
String value = Req.getParameter("") 获取名称对应的值
String[] values = Req.getParameterValues("") 同一个name存在多个值
2.3.5.1. 请求乱码问题
乱码原因: request 封装时候,使用的ISO ,不支持中文编码
get 不会乱码,post有乱码
解决办法: 设置请求的编码方式
req.sertCharacterEncoding("utf-8") // 只值对post代码
String name = new String(req.getParameter(name)).getBytes('ISO-8859-1', charameter = 'utf-8') //适用于所有get 与post
2.3.5.2. 请求转发
- 服务器行为
- 前台地址栏不发生改变,只产生输出
- 只有一个请求
- req, resp对象共享
req.getRequestDispatcher("跳转网址").forward(req, resp);
req.setAttribute(String name , Object value);//设置新的对象值
req.getAttribute(String name);
req.removeAttribute(String name);//删除对象值
2.3.6. HttpServletResponse 响应请求
使用流输出方法响应
- getWritter() 字符输出流(输出字符串)
- getOutputStream(), 字节输出流(输出任意数据)
两种流不能同时使用
2.3.6.1. 响应乱码
原因: 服务端和客户端的编码格式一致
解决办法:同时设置服务端和客户端的编码,保证编码格式一致
// 设置服务端的编码格式
response.setCharacterEncoding("UTF-8");
// 设置客户端代码
response.setHeader("content_type", "text/html; charset= UTF-8");
// 同时设置编码格式
response.setContentType("text/html; charset= UTF-8");
2.3.6.2. 客户端重定向
服务端指导客户端的行为
地址栏发生改变,写入location
服务器接受location
有两次请求
请求对象不共享
response.sendRedirect("s05");
2.3.6.3. 请求转发与重定向的区别
请求转发 | 重定向 |
---|---|
一次请求,request数据共享 | 两次请求 |
服务端跳转 | 客户端跳转 |
绝对地址到当前项目中,不能向外跳转 | 可以向域外跳转 |
2.4. Cookie对象
浏览器中将数据存放在客户端中,在客户端中处理数据,减少网络传输与数据库查询
由服务器写入客户端
// 服务器写入Cookie 到客户端中,客户端保存Cookie
Cookie cookie = new Cookie(name = "a", value = 'b');
response.addCookie(cookie)
// 获取Cookie
Cookie[] conkie = request.getCookies(); // 获取客户端路径下所有的Cookie对象
//将Cookie 的name 与需要查找的Cookie作比较
2.4.1. 设置对象存在时间
设置maxAge存活时间 ,从创建Cookie对象开始
cookie.setMaxAge(time);
/*
1. 负整数,只在浏览器内存中存在
2. 正整数,保存磁盘对应的时间,关闭后依旧计数,时间为s
3. 0 : 删除这个Cookie
*/
2.4.2. 注意点
- Cookie 只在当前浏览器中有效,不跨浏览器和及其
- Cookie不支持存放中文,使用时候需要编码/解码
- 新的同名name Cookie 将覆盖之前的Cookie
- Cookie的存储数量有上限,Cookie的大小有限,4KB左右
String name = "陈龙";
// 中文通过URLEncoder.encode()编码
name = URLEncoder.encoder(name);
// 使用时,需URLDecoder.decoder()解码
name = URLDecoder.decoder(name);
2.4.3. Cookie的访问路径
- 当前浏览器下如何项目任何资源都可以获取Cookie
cookie.setPath("/");
// 默认本项目
cookie.setPaht("/s02");
// 设置指定站点名
cookie.setPath("/sc03");
// 指定项目的指定资源访问cookie
cookie.setPaht("s03/co1");
只有访问的路径包括 cookie的路径 时, 能够获取这个cookie
2.5. HttpSession 对象
属于服务器对象, 标识一次对话,确定是否为一个用户的数据
HttpSession session = request.getSession(); // 如session 对象存在,则获取 ;否则第一次创建对象
一次请求到了服务器,标识启动了会话,客户端向服务器传递JSESSIONID的cookie,用于标识服务器中对应的session, 如果有,则共享数据,没有创建sesion,同时给客户端创建JSESSIONID的cookie.
2.5.1. 设置域对象
HttpSession 与 request 的区别
重定向: 只要session会话不是小,session一直共享数据
HttpSession session = request.getSession();
session.setAttribute("name", "hello");
session.getAttribute("name");
2.5.2. session 对象的销毁
默认是30min, 一旦有操作,session 重新计时
在conf/web.xml中修改session_config中timeout,单位为1min
2.5.2.1. 设置到期时间
session.setMaxInactiveInterval(15); //单位为s
2.5.2.2. 立即销毁
退出登录,立马销毁
session.invalidate();
2.5.2.3. 关闭浏览器,Cookie对象销毁
session 需要JSESSIONID ,JSESSIONID默认在浏览器内存中有效,Cookie消失后,session 结束
2.5.2.4. 关闭服务器失效
2.6. ServletContext对象
2.6.1. 获取对象
ServletContext servletContext1 = request.getServletContext();
// session对象获取
ServletContext servletContext2 = request.getSession().getServletContext();
// ServletConfig对象中获取
getServletConfig().getServletContext();
// servlet中直接获取
ServletContext servletContext4 = getServletContext();
常用方法
// 获取服务器信息
String serverInfo = request.getServletContext().getServerInfo();
// 获取项目路径
String realPath = request.getServletContext().getRealPath("/");// 从根目录下获取
2.6.2. Servlet 域对象
request 域对象
再一次请求中有效,请求转发有效,重定向无效
session 对象
一次会话中有效,session销毁后无效
servletContext 对象
服务器中始终有效
2.7. 文件上传下载
2.7.1. 上传
2.7.1.1. 前端实现
- 准备表单form
- 设置表单的请求类型 ‘method =”post”
- 设置表达类型为文件上传类型 enctype = “multipart/form-data”
- 设置文件提交的地址 active = “提交路径”
- 准备表单元素
- 普通的表单项 type = “text”
- 文件项 type = “file”
- 设置表单元素的name值
2.7.1.2. 后端实现
添加注解MultipartConfig
, servlet将 multipart/form-data 的post封装在part对象中
@MultipartConfig
Part part = request.getPart("name");
String fileName = part.getSubmittedFileName(); // 获取提交文件名称;
String realPath = request.getServletContext().getRealPath("/");
// 需要自行指定保存路径
String saveName= fileName+'/'+ realPath;
part.write(saveName);
2.7.2. 文件下载
2.7.2.1. 超链接下载
- 没有download属性
- 浏览器识别文件,跳转显示,否则下载
- 有download属性
- 指定属性值,为下载名
<a href="download/text.png"> 图片文件</a>
<a href="download/text.png" download>图片文件</a>
2.7.2.2. 后端下载
设置request和response的编码类型
request.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset = UTF-8");
获取文件名称
String fileName = request.getParameter("name")
判断文件名称是否为空
// 文件名= null 或者全是空格 if(fileName == null || "".equals(fileName.trim())){ response.getWritter().write("输出提示信息"); response.getWritter().close();// 关闭信息 }
将路径转换为file 对象
String path = request.getServletContext().getRealPath("/download/"); File file = new File(path+ fileName); // 检查文件存在//是否为文件夹 if(file.exist()&& file.isFile()){ }
输出
设置响应类型, 浏览器无法解析的MINE类型 “application/x-msdoanload”, “application/octet-stream”
- response.setContentType(“application/x-msdoanload”)
设置响应头,下载文件筐和文件名
- response.setHeader(“Content_Dispostion”, ”attachment;filename=”+ fileName);
输出流和输入流
InputStream in = new FileInputSream(file); ServletOutputSream out = response.getOutputStream(); byte[] bytes = new byte[1024]; int len = 0; while((len = in.read(byte))!= -1){ out.write(bytes,0 , len); } // 关闭资源 out.close(); in.close();
简便实现
response.setContentType("application/octet-stream"); // 设置为通用的二进制流类型 response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // 提示浏览器下载文件 // 使用 try-with-resources 确保流被正确关闭 try (InputStream in = new FileInputStream(file); ServletOutputStream out = response.getOutputStream()) { // 使用 transferTo 方法进行拷贝 (Java 9+) in.transferTo(out); // 注意:在 try-with-resources 块结束时,in 和 out 会自动关闭 } catch (IOException e) { // 处理可能的 IO 异常 e.printStackTrace(); // 在实际应用中应该记录日志或返回更友好的错误信息 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "文件读取或传输失败"); }