jsp+servlet


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
  1. 支持客户/服务端
  2. 支持get ,post请求
  3. 传输内容,类型可以有Content-Type
  4. http无连接,http1.1之后支持可持续连接
  5. http无状态信息

2.1.1. 请求和responce

2.1.1.1. 请求request

  1. 请求行

    get的请求放在请求行中

    method Request_url http_version 换行

  2. 请求头

    1. 键值对
  3. 请求体

    1. get没有请求行

2.1.1.2. response

  1. 状态行
  2. 响应头
  3. 响应正文

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实现

  1. 创建java类
  2. 实现servlet规范, 继承HttpServlet类
  3. 重写service 方法,用于处理请求
  4. 设置注释,指定访问方法的路径
@Webservlet(name = , value ={ , }) value可以指定多个名称

2.3.1. servlet执行流程

  1. 从请求头中找到主机
  2. 访问请求头中的资源,第一次访问创建一个对象
  3. 将参数交给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方法

image-20250503221820723

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. 请求转发

  1. 服务器行为
  2. 前台地址栏不发生改变,只产生输出
  3. 只有一个请求
  4. 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 响应请求

使用流输出方法响应

  1. getWritter() 字符输出流(输出字符串)
  2. 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. 注意点

  1. Cookie 只在当前浏览器中有效,不跨浏览器和及其
  2. Cookie不支持存放中文,使用时候需要编码/解码
  3. 新的同名name Cookie 将覆盖之前的Cookie
  4. Cookie的存储数量有上限,Cookie的大小有限,4KB左右
String name = "陈龙";

// 中文通过URLEncoder.encode()编码
name = URLEncoder.encoder(name);

// 使用时,需URLDecoder.decoder()解码
name = URLDecoder.decoder(name);

2.4.3. Cookie的访问路径

  1. 当前浏览器下如何项目任何资源都可以获取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 域对象

  1. request 域对象

    再一次请求中有效,请求转发有效,重定向无效

  2. session 对象

    一次会话中有效,session销毁后无效

  3. servletContext 对象

    服务器中始终有效

2.7. 文件上传下载

2.7.1. 上传

2.7.1.1. 前端实现

  1. 准备表单form
  2. 设置表单的请求类型 ‘method =”post”
  3. 设置表达类型为文件上传类型 enctype = “multipart/form-data”
  4. 设置文件提交的地址 active = “提交路径”
  5. 准备表单元素
    1. 普通的表单项 type = “text”
    2. 文件项 type = “file”
    3. 设置表单元素的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. 超链接下载

  1. 没有download属性
    1. 浏览器识别文件,跳转显示,否则下载
  2. 有download属性
    1. 指定属性值,为下载名
<a href="download/text.png"> 图片文件</a>
<a href="download/text.png" download>图片文件</a>

2.7.2.2. 后端下载

  1. 设置request和response的编码类型

    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html; charset = UTF-8");
    
  2. 获取文件名称

String fileName = request.getParameter("name")
  1. 判断文件名称是否为空

    // 文件名= null 或者全是空格
    if(fileName == null || "".equals(fileName.trim())){
        response.getWritter().write("输出提示信息");
        response.getWritter().close();// 关闭信息
    }
    
  2. 将路径转换为file 对象

    String path = request.getServletContext().getRealPath("/download/");
    File file = new File(path+ fileName);
    // 检查文件存在//是否为文件夹
    if(file.exist()&& file.isFile()){
        
    }
    
  3. 输出

    1. 设置响应类型, 浏览器无法解析的MINE类型 “application/x-msdoanload”, “application/octet-stream”

      1. response.setContentType(“application/x-msdoanload”)
    2. 设置响应头,下载文件筐和文件名

      1. response.setHeader(“Content_Dispostion”, ”attachment;filename=”+ fileName);
    3. 输出流和输入流

      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();
      
    4. 简便实现

      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, "文件读取或传输失败");
      }
      

文章作者: 小白菜
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小白菜 !
评论
  目录