Servelt&&JSP进阶

Servlet与JSP进阶

来自mkw的视频课程的总结

1.前言

内容包括 掌握Java Web核心特性,Servlet核心对象以及JSP九大内置对象。主要有以下的内容:

  • 请求结构 && 响应结构
  • 请求转发重定向
  • Cookie && Session
  • ServletContext 与三大作用域
  • 请求响应中文乱码问题解决
  • Web.xml常用配置
  • JSP九大内置对象
  • web应用程序打包和发布

2. 请求结构

请求行,请求头,请求体

请求头包括Accept-Language:zh-CN(国际化),Content-Type等 浏览器的辅助信息。

对于get请求,请求的内容一般放在 query String Parameters,在POST中放在From Data中,此外,格式内容都一样

UserAgent适用于不同终端的开发

3.响应结构

状态码:200 404 500 403(服务器拒绝访问) 301/302 400(无效请求)

Content-Type明确网页解析响应体的格式,一般为 text/html, plain是原文 application/x-msdownload

4.请求转发与响应重定向

从一个页面自动跳转到另一个页面

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("用户登陆成功!");
        //实现了请求转发的功能
        req.getRequestDispatcher("/direct/index").forward(req,resp);
        
        // 响应重定向 需要增加 contextPath
        resp.sendRedirect("/Servlet_advanced_war_exploded/direct/index");
    }

二者的区别,表面上看是 最终的URL不同,请求转发的URL是最初的 /direct/check,而响应重定向是 /direct/index,内容都是 index的内容

二者原理的区别:

请求转发:Tomcat服务器内部,Servlet1处理后,在req.getRequestDispatched().forward()语句下,将原请求原封不动转交给Servlet2。

响应重定向:浏览器跳转,产生两次请求,语句是response.sendRedirect(),这里响应1不是html网页,而是告诉浏览器再发送一个请求给Servlet2的地址。

4.1 设置请求自定义属性

  • 允许创建自定义属性
  • 设置请求属性: request.setAttribute(属性名,属性值)
  • 获取请求属性: request.getAttribute(属性名,属性值)

5.Cookie

​ Cookie的引文原意是“点心”,它是在客户端访问Web服务器时,服务器在客户端硬盘上存放的信息,好像是服务器发送给客户的“点心”。服务器可以根据Cookie来跟踪客户状态(之前是否已经登录),这对于需要区别客户的场合(如电子商务)特别有用。

​ 当客户端首次请求访问服务器时,服务器先在客户端存放包含该客户的相关信息的Cookie,以后客户端每次请求访问服务器时,都会在HTTP请求数据中包含Cookie,服务器解析HTTP请求中的Cookie,就能由此获得关于客户的相关信息。

Cookie是浏览器保存本地,记录用户登录状态和资料的文本,具有时效性,默认是浏览器关闭Cookie就会被清空,可以用setMaxAge()设置。Cookie内容会伴随请求发送给Tomcat,常用的方法有:

LoginServlet.java

@WebServlet("/cookies/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("用户登录成功");
        Cookie cookie = new Cookie("user","admin");
        cookie.setMaxAge(60*60*4*7); 
        resp.addCookie(cookie);
        resp.getWriter().println("login success");
    }
}

IndexServlet.java

@WebServlet("/cookies/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie[] cs = req.getCookies();
        String user = null; //防止空指针异常

        for(Cookie c:cs) {
            if(c.getName().equals("user")) {
                user = c.getValue();
                break;
            }
            System.out.println(c.getName() + ": " + c.getValue());
        }

        if(user == null) {
            resp.getWriter().println("User no login in");
        } else {
            resp.getWriter().println("User:" + user);
        }
    }
}

6.Session

  • Session(用户会话)用于保存与“浏览器窗口”(并不是实际的浏览器窗口)对应的数据;
  • 存储在Tomcat服务器内存中,具有时效性(默认30min没有用到就会被销毁);
  • Session通过浏览器Cookie的SessionID值针对性提取用户数据;

Cookie中保存的sessionID将 cookie和对应的session连接在一起,这里有一个问题需要清楚:

Cookie的生命周期是和浏览器绑定在一起的,关闭浏览器后Cookie(包含sessionID)就会被清除,而一个session的在Tomcat的生命周期是 30min,二者不矛盾。下面内容引用自请叫我丁木西

那么为什么当我们关闭浏览器后,就再也访问不到之前的session了呢?其实之前的Session一直都在服务器端,而当我们关闭浏览器时,此时的Cookie是存在于浏览器的进程中的,当浏览器关闭时,Cookie也就不存在了。其实Cookie有两种:

一种是存在于浏览器的进程中; 一种是存在于硬盘上。

session的Cookie是存在于浏览器的进程中,那么这种Cookie我们称为会话Cookie,当我们重新打开浏览器窗口时,之前的Cookie中存放的Sessionid已经不存在了,此时服务器从tpServletRequest对象中没有检查到sessionid,服务器会再发送一个新的存有Sessionid的Cookie到客户端的浏览器中,此时对应的是一个新的会话,而服务器上原先的session等到它的默认时间到之后,便会自动销毁

附加

当在同一个浏览器中同时打开多个标签,发送同一个请求或不同的请求,仍是同一个session;

当不在同一个窗口中打开相同的浏览器时,发送请求,仍是同一个session; 这个不太好理解

当使用不同的浏览器时,发送请求,即使发送相同的请求,是不同的session;

当把当前某个浏览器的窗口全关闭,再打开,发起相同的请求时,是不同的session。

Code demo

SessionLoginServlet

package com.imooc.servlet.session;

import com.sun.xml.internal.ws.addressing.WsaActionUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/session/login")
public class SessionLoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("登录成功");
        HttpSession session = req.getSession();
        String sessionId = session.getId();
        System.out.println(sessionId);
        session.setAttribute("name","张三");
        req.getRequestDispatcher("/session/index").forward(req,resp); //请求转发到 "/session/index"
    }
}

SessionIndexServlet.java

package com.imooc.servlet.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/session/index")
public class SessionIndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        String sessionId = session.getId();
        System.out.println(sessionId);
        String name = (String) session.getAttribute("name");
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().println("这是首页,当前用户" + name);
    }
}

7.ServletContext与三大作用域对象

7.1 ServletContext

  • ServletContext(Servlet上下文对象),是Web应用全局对象

  • 一个Web应用只会创建一个ServletContext对象

  • ServletContext随着Web应用启动而自动创建

ServletContext适合整个应用/网站的全局信息,在每一个页面都有的,比如页脚的网站的备案信息等。

Code Demo

ContextInitServlet.java

package com.imooc.servlet.ServletContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/context/init")
public class ContextInitServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = req.getServletContext();
        context.setAttribute("copyright","@ 2020 www.imooc.com 京");
        context.setAttribute("title","慕课网-程序员的梦工厂");
        resp.getWriter().println("Init Success");
    }
}

ServletDefaultServlet.java

package com.imooc.servlet.ServletContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/context/default")
public class ServletDefaultServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = req.getServletContext();
        String copyright = (String) context.getAttribute("copyright");
        String title = context.getAttribute("title").toString();
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().println("<h1>" + title + "</h1>" + copyright);
    }
}

与前面不同,当先后访问两个页面之后关闭浏览器,再打开新浏览器直接访问 "/context/default"。结果不变,这是因为ServletContext是应用全局对象,只要应用启动初始化后,就一直存在。

7.2 Java-Web 三大作用域对象

  1. HttpServletRequest 请求对象-瞬时对象;
  2. HttpSession 用户会话对象- 用户第一次请求访问开始创建,然后30min没有用到就会被销毁;
  3. ServletContext web应用全局对象,web启动后就被创建,生命周期最久。

8.Web请求&响应中文乱码

Tomcat默认使用字符集ISO-8859-1,属于西欧字符集,解决乱码即用UTF-8替换即可,在Servlet中,请求与响应都需要设置UTF-8字符集

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
</head>
<body>

<form action="/Servlet_advanced_war_exploded/charset/process" method="post">
    姓名:<input name="ename">
    地址:<input name="address">
    <input type="submit" value="提交">
</form>

</body>
</html>
package com.imooc.servlet.charset;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/charset/process")
public class CharsetServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //方法2 req.setCharacterEncoding("UTF-8");
        String ename = req.getParameter("ename");
        String address = req.getParameter("address");
        //方法1
        // String utf8ename = new String(ename.getBytes("iso-8859-1"), "utf-8")
        System.out.println(ename + ":" + address);
    }
}

控制台产生:???:???é??,解决方案是 单个语句转换可以使用方法1,全局设置可以使用方法2

get请求乱码解决

在 Tomcat version >=8版本不存在这个问题,但是 低版本可以修改 Tomcat安装目录 conf/server.xml 的第69行

添加 URIEncoding="UTF-8" ,即修改成

解决

9.Web.xml常用配置

Web.xml是Java Web项目最重要的配置文件

9.1 默认首页

在默认创建项目后的Web.xml中,会存在如下代码:

<welcom-first>index.html</welcom-first>
<welcom-first>index.htm</welcom-first>
<welcom-first>index.jsp</welcom-first>
<welcom-first>default.html</welcom-first>
<welcom-first>index.htm</welcom-first>
<welcom-first>index.jsp</welcom-first>

功能是 如果在Web目录下有任何一个上述的文件,都会成为其默认的首页,可以用户自定义,同时定义了二级目录中默认的页面

9.2 使用WebServlet通配符

某些URL前缀相同的请求都会被拦截

package com.imooc.servlet.pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class PatternServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String url = req.getRequestURL().toString();
        System.out.println(url);
        String id = url.substring(url.lastIndexOf("/") + 1);
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println(id);

        if(id.equals("1")) {
            out.println("张三");
        }else if(id.equals("2")) {
            out.println("李四");
        }else {
            out.println("其他员工");
        }
    }
}

Web.xml 添加如下信息:

    <servlet>
        <servlet-name>patternServlet</servlet-name>
        <servlet-class>com.imooc.servlet.pattern.PatternServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>patternServlet</servlet-name>
        <url-pattern>/pattern/*</url-pattern>
    </servlet-mapping>

9.4 全局参数的配置

在Web.xml中可以定义全局参数

 <context-param>
        <param-name>copyright</param-name>
        <param-value>@2021 imooc.com 京</param-value>
    </context-param>
    <context-param>
        <param-name>title</param-name>
        <param-value>慕课网-程序员的梦工厂</param-value>
    </context-param>

在Java中获取

String copyright = context.getInitParameter("copyright");

9.3 404 500页面设置

在web项目下新建 error目录,然后新建 404.html和 500.html。在Web.xml上添加

<error-page>
    <error-code>404</error-code>
    <location>/error/404.html</location>
</error-page>

<error-page>
    <error-code>500</error-code>
    <location>/error/500.html</location>
</error-page>

如此设置是避免程序错误产生的系统报错信息直接显示在页面上,泄露一些程序的逻辑信息,提高安全性。

10.JSP九大内置对象

就是不同对象的简略写法。

11.Java-Web打包与发布

  • Java Web应用采用war包进行发布
  • 发布路径: {Tomcat_Home}/webapps
  • Eclipse支持war包导出

这里发现在 server.xml中无法设置 端口号和 path 的默认,找不到视频中要修改的东西。

IDEA打包war 参考小白马上飞Tanyiqu-bili 两个帖子

posted @ 2021-01-30 21:27  又一个蛇佬腔  阅读(93)  评论(0编辑  收藏  举报