Java Web快速入门

Tomcat10版本

一、Servlet

一、前置知识

一、报文格式

HTTP请求、响应报文格式:

请求行、请求头、空行、请求体

状态行、响应头、空行、响应体

在这里插入图片描述

二、请求头
Accept指定客户端能够接收的内容类型Accept: text/plain, text/html
Accept-Charset浏览器可以接受的字符编码集。Accept-Charset: iso-8859-5
Accept-Encoding指定浏览器可以支持的web服务器返回内容压缩编码类型。Accept-Encoding: compress, gzip
Accept-Language浏览器可接受的语言Accept-Language: en,zh
Accept-Ranges可以请求网页实体的一个或者多个子范围字段Accept-Ranges: bytes
AuthorizationHTTP授权的授权证书Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control指定请求和响应遵循的缓存机制Cache-Control: no-cache
Connection表示是否需要持久连接。(HTTP 1.1默认进行持久连接)Connection: close
CookieHTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。Cookie: $Version=1; Skin=new;
Content-Length请求的内容长度Content-Length: 348
Content-Type请求的与实体对应的MIME信息Content-Type: application/x-www-form-urlencoded
Date请求发送的日期和时间Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect请求的特定的服务器行为Expect: 100-continue
From发出请求的用户的EmailFrom: user@email.com
Host指定请求的服务器的域名和端口号Host: www.zcmhi.com
If-Match只有请求内容与实体相匹配才有效If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为EtagIf-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since只在实体在指定时间之后未被修改才请求成功If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards限制信息通过代理和网关传送的时间Max-Forwards: 10
Pragma用来包含实现特定的指令Pragma: no-cache
Proxy-Authorization连接到代理的授权证书Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range只请求实体的一部分,指定范围Range: bytes=500-999
Referer先前网页的地址,当前请求网页紧随其后,即来路Referer: http://www.zcmhi.com/archives/71.html
TE客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息TE: trailers,deflate;q=0.5
Upgrade向服务器指定某种传输协议以便服务器进行转换(如果支持)Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-AgentUser-Agent的内容包含发出请求的用户信息User-Agent: Mozilla/5.0 (Linux; X11)
Via通知中间网关或代理服务器地址,通信协议Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning关于消息实体的警告信息Warn: 199 Miscellaneous warning
三、响应头
Accept-Ranges表明服务器是否支持指定范围请求及哪种类型的分段请求Accept-Ranges: bytes
Age从原始服务器到代理缓存形成的估算时间(以秒计,非负)Age: 12
Allow对某网络资源的有效的请求行为,不允许则返回405Allow: GET, HEAD
Cache-Control告诉所有的缓存机制是否可以缓存及哪种类型Cache-Control: no-cache
Content-Encodingweb服务器支持的返回内容压缩编码类型。Content-Encoding: gzip
Content-Language响应体的语言Content-Language: en,zh
Content-Length响应体的长度Content-Length: 348
Content-Location请求资源可替代的备用的另一地址Content-Location: /index.htm
Content-MD5返回资源的MD5校验值Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range在整个返回体中本部分的字节位置Content-Range: bytes 21010-47021/47022
Content-Type返回内容的MIME类型Content-Type: text/html; charset=utf-8
Date原始服务器消息发出的时间Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag请求变量的实体标签的当前值ETag: “737060cd8c284d8af7ad3082f209582d”
Expires响应过期的日期和时间Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified请求资源的最后修改时间Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location用来重定向接收方到非请求URL的位置来完成请求或标识新的资源Location: http://www.zcmhi.com/archives/94.html
Pragma包括实现特定的指令,它可应用到响应链上的任何接收方Pragma: no-cache
Proxy-Authenticate它指出认证方案和可应用到代理的该URL上的参数Proxy-Authenticate: Basic
refresh应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)Refresh: 5; url=http://www.zcmhi.com/archives/94.html
Retry-After如果实体暂时不可取,通知客户端在指定时间之后再次尝试Retry-After: 120
Serverweb服务器软件名称Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie设置Http CookieSet-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer指出头域在分块传输编码的尾部存在Trailer: Max-Forwards
Transfer-Encoding文件传输编码Transfer-Encoding:chunked
Vary告诉下游代理是使用缓存响应还是从原始服务器请求Vary: *
Via告知代理客户端响应是通过哪里发送的Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning警告实体可能存在的问题Warning: 199 Miscellaneous warning
WWW-Authenticate表明客户端请求实体应该使用的授权方案WWW-Authenticate: Basic
四、响应码
一、1xx(临时响应)

100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。

二、2xx (成功)

200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。
201 (已创建) 请求成功并且服务器创建了新的资源。
202 (已接受) 服务器已接受请求,但尚未处理。
203 (非授权信息) 服务器已成功处理了请求,但返回的信息可能来自另一来源。
204 (无内容) 服务器成功处理了请求,但没有返回任何内容。
205 (重置内容) 服务器成功处理了请求,但没有返回任何内容。
206 (部分内容) 服务器成功处理了部分 GET 请求。

三、3xx (重定向)

300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

四、4xx(请求错误)

400 (错误请求) 服务器不理解请求的语法。
401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403 (禁止) 服务器拒绝请求。
404 (未找到) 服务器找不到请求的网页。
405 (方法禁用) 禁用请求中指定的方法。
406 (不接受) 无法使用请求的内容特性响应请求的网页。
407 (需要代理授权) 此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
408 (请求超时) 服务器等候请求时发生超时。
409 (冲突) 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
410 (已删除) 如果请求的资源已永久删除,服务器就会返回此响应。
411 (需要有效长度) 服务器不接受不含有效内容长度标头字段的请求。
412 (未满足前提条件) 服务器未满足请求者在请求中设置的其中一个前提条件。
413 (请求实体过大) 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
414 (请求的 URI 过长) 请求的 URI(通常为网址)过长,服务器无法处理。
415 (不支持的媒体类型) 请求的格式不受请求页面的支持。
416 (请求范围不符合要求) 如果页面无法提供请求的范围,则服务器会返回此状态代码。
417 (未满足期望值) 服务器未满足"期望"请求标头字段的要求。

五、5xx(服务器错误)

500 (服务器内部错误) 服务器遇到错误,无法完成请求。
501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。

二、Servlet介绍

  1. 接口类Servlet
  2. 抽象类GenericServlet(继承接口类Servlet)
  3. 实现类HttpServlet(继承抽象类GenericServlet),专门用于创建HTTP协议的Servlet

三、实现方式

  • 新建Maven项目,在pom.xml中加上<packaging>war</packaging>,打开项目结构,找到Facets,选中项目后,在其中的Web资源目录点击加号生成webapp目录,再其中的部署描述器点击加号生成WEB-INF和在其里面的web.xml,移动WEB-INF至webapp即可。

  • 目录结构
        src	
        	main|
        		|java
        		|webapp|
        			   |WEB-INF|
        					   |web.xml
        pom.xml
    
  • 		<!-- 1.Servlet、FilterListenerJSPJavaBeanEL表达式-->
      		<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
            <dependency>
                <groupId>jakarta.servlet</groupId>
                <artifactId>jakarta.servlet-api</artifactId>
                <version>6.0.0</version>
                <scope>provided</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp/jakarta.servlet.jsp-api -->
            <dependency>
                <groupId>jakarta.servlet.jsp</groupId>
                <artifactId>jakarta.servlet.jsp-api</artifactId>
                <version>3.1.0</version>
                <scope>provided</scope>
            </dependency>
      
            <!-- 2.jstl -->
            <!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api -->
            <dependency>
                <groupId>jakarta.servlet.jsp.jstl</groupId>
                <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
                <version>3.0.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.glassfish.web/jakarta.servlet.jsp.jstl -->
            <dependency>
                <groupId>org.glassfish.web</groupId>
                <artifactId>jakarta.servlet.jsp.jstl</artifactId>
                <version>2.0.0</version>
            </dependency>
                
            <!-- 3.mysql -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.30</version>
            </dependency>
    

一、 注解

一、Servlet
  1. 定义一个普通类实现接口类jakarta.servlet.Servlet,并重写五个抽象方法
  2. 使用@WebServlet注解,配置访问路径@WebServlet(“/demo1”)
  3. 访问http://localhost:8080/demo1
二、HttpServlet
  1. 定义一个普通类继承实现类jakarta.servlet.http.HttpServlet,按需重写doGet和doPost方法,还有其他的
  2. 使用@WebServlet注解,配置访问路径@WebServlet(“/demo2”)
  3. doGet()和doPost()逻辑差不多,可以将doPost()处理个别Post独有逻辑然后转去doGet()
  4. 访问http://localhost:8080/demo2

二、XML

一、Servlet
  1. 定义一个普通类实现接口类jakarta.servlet.Servlet,重写所有方法

  2. 在web.xml中填写<servlet></servlet><servlet-mapping></servlet-mapping>标签

  3. <servlet>
        <servlet-name>demo4</servlet-name>  <!-- 别名 -->
        <servlet-class>com.miao.Web.Servlet.ServletDemo4</servlet-class>  <!-- 全类名 -->
    </servlet>
    
    <servlet-mapping>
        <servlet-name>demo4</servlet-name>  <!-- 先前设置的别名 -->
        <url-pattern>/demo4</url-pattern>  <!-- 路径 -->
    </servlet-mapping>
    
二、HttpServlet
  1. 定义一个普通类继承实现类jakarta.servlet.http.HttpServlet,重写doGet和doPost方法

  2. 在web.xml中填写<servlet></servlet><servlet-mapping></servlet-mapping>标签

  3. <servlet>
        <servlet-name>demo4</servlet-name>  <!-- 别名 -->
        <servlet-class>com.miao.Web.Servlet.ServletDemo4</servlet-class>  <!-- 全类名 -->
    </servlet>
    
    <servlet-mapping>
        <servlet-name>demo4</servlet-name>  <!-- 先前设置的别名 -->
        <url-pattern>/demo4</url-pattern>  <!-- 路径 -->
    </servlet-mapping>
    

四、Servlet生命周期

  • 自上而下调用
  1. 加载和实例化Serlvet对象,只调用一次
  2. init初始化:初始化,加载配置文件、连接。默认是第一次访问该url时才调用且只调用一次;loadOnStartup为0或者正整数时,服务器创建时就调用且只有一次:@WebServlet(urlpatterns = “/demo1”, loadOnStartup = 1)
  3. getServletConfig:获取ServletConfig对象()
  4. service:处理请求,可调用多次
  5. getServletInfo:获取Servlet信息(作者、版本和版权等,不常用)
  6. destroy:释放资源,只调用一次。内存释放/服务器关闭时调用且只有一次

五、配置urlpatterns

1. 多个目录匹配

  1. @WebServlet(urlPatterns = {“/demo1”, “/demo2”}),XML中则是直接写出多个<servlet-mapping></servlet-mapping>

2. 精确匹配

  1. @WebServlet(“/user/list”),优先级更高

3. 目录匹配

  1. @WebServlet(“/user/*”)

4. 扩展名匹配

  1. @WebServlet(“*.html”),前面不能加’/’

5. 任意匹配(不建议使用)

  1. @WebServlet(“/”);@WebServlet(“/*”),使用前者则会覆盖tomcat自带的DefaultServlet(用于静态资源访问!将访问不到html文件!)

六、ServletConfig和ServletContext

<servlet>
    <servlet-name>xxx</servlet-name>  <!-- 别名 -->
    <servlet-class>xxx</servlet-class>  <!-- 全类名 -->
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</servlet>

ServletConfig config = this.getSerlvetConfig();
String value = config.getInitParameter("encoding")  // UTF-8。获取参数名为encoding的参数值
<context-param>
    <param-name>encoding</param-name>
    <param-value>UTF-8</param-value>
</context-param>

SerlvetContext context = this.getServletContext();
Enumeration<String> values = context.getInitParameterNames();  // 获取所有参数名
while (values.hasMoreElements) {
    String name = values.nextElement();  // 只有一个encoding
    String value = context.getInitParameter(name);  // UTF-8。获取参数名为encoding的参数值
    }

二、Request&Response

一、Request

  • 接口类ServletRequest
  • 接口类HttpServletRequest(继承接口类ServletRequest)
  • 实现类RequestFacade(实现接口类HttpServletRequest)

一、获取请求报文数据

一、 请求行
  1. // Get
    String method = req.getMethod();  // 请求方法
    String contextPath = req.getContextPath();  // 虚拟目录,即 http://localhost:8080后的路径
    StringBuffer url = req.getRequestURL();  // URL路径 http://localhost:8080/Reqdemo1
    String uri = req.getRequestURI();  // URI路径 /ReqDemo1
    String queryString = req.getQueryString();  // 获取Get请求的query传参参数
    
二、请求头
  1. String header = req.getHeader("User-Agent");  // 根据请求头名称获取其值
    
三、空行
四、请求体
  1. // Post
    ServletInputStream servletInputStream = req.getInputStream();  // 字节输入流
    BufferedReader bufferedReader = req.getReader();  // 字符输入流
    

二、获取请求参数

  • 适用于Get和Post
  1.         // 1.getParameterMap获取全部参数的映射
            Map<String, String[]> map = req.getParameterMap();
            for (String key : map.keySet()) {
                String[] values = map.get(key);
                for (String value : values) {
                    System.out.println(value + "");
                }
            }
    
  2.         // 2.getParameterValues获取指定参数,返回数组
            String[] values = req.getParameterValues("a");
            for (String v : values) {
                System.out.println(v);
            }
    
  3.         // 3.getParameter获取单个参数
            String username = req.getParameter("username");
            System.out.println(username);
    

三、解决请求参数乱码

一、针对GET请求
// 输入中文,无论Get还是Post都会乱码(Tomcat8-9Get不会乱码,Tomcat10不存在乱码)
// 由于Tomcat获取请求参数时默认是ISO8859-1编码后输出到控制台,但是控制台一般为GBK/UTF-8解码,故重新编码即可,但是tomcat7以后GET请求默认编码是UTF-8了
String bname = request.getParameter("bname"); 
bname = new String(bname .getBytes("iso8859-1"),"utf-8"); 
二、针对POST请求
// 输入中文,无论Get还是Post都会乱码(Tomcat8-9Get不会乱码,Tomcat10不存在乱码)
// 设置字符输入流的编码即可
req.setCharacterEncoding("UTF-8");
System.out.println(req.getParameter("username"));

四、请求转发(forward)

        // 必须在同一台服务器才可以完成以下操作!!!
		// 共享数据和请求转发(地址栏不变)
        // 1.存储数据
        req.setAttribute("msg", "Hello World!");
        // 2.请求转发,转发到静态资源或者接口
        // req.getRequestDispatcher("/he.html").forward(req, resp);
        req.getRequestDispatcher("/ReqDemo3").forward(req, resp);
        // 3.获取数据
        req.getAttribute("msg");
        // 4.删除数据
        req.removeAttribute("msg");

二、Response

  • 接口类ServletResponse
  • 接口类HttpServletResponset(继承接口类ServletResponse)
  • 实现类ResponseFacade(实现接口类HttpServletResponse)

一、设置响应报文数据

一、响应行
// 1.设置响应行-响应状态码
resp.setStatus(302);
二、响应头
// 2.设置响应头
resp.setHeader("Content-type", "application/json;charset=UTF-8");
三、空行
四、响应体
  1.         // 字符输出流,输出流不需要关闭,响应结束会自动销毁
            // 1.先设置响应头,即流的编码,必须在前面!!!
            // resp.setHeader("Content-Type", "charset=UTF-8");
            resp.setContentType("text/html;charset=UTF-8");
            // 2.获取字符输出流
            PrintWriter writer = resp.getWriter();
            // 3.输出数据
            writer.write("<h1>你好!</h1>");
    
  2.         // 字节输出流,输出流不需要关闭,响应结束会自动销毁
            // 1.读取文件
            FileInputStream inputStream = new FileInputStream("G:\\壁纸头像\\1.jpg");
            // 2.获取字节输出流
            ServletOutputStream outputStream = resp.getOutputStream();
            // 3.输出数据
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            inputStream.close();
    

二、解决响应数据乱码

 response.setCharacterEncoding("UTF-8");  // tomcat7及之前默认ISO8859-1编码,而目前主流浏览器用UTF-8解码

三、路径问题

  1. 浏览器使用:要加虚拟目录(http://localhost:8080/虚拟目录名称/Demo1),重定向(sendRedirect)、a标签、form标签
  2. 服务器使用:不要加虚拟目录(http://localhost:8080/Demo1),请求转发(getRequestDispatcher)

四、请求重定向(redirect)

// 任意位置都可以重定向,服务器/外部
// 重定向,地址栏改变
// 1.设置响应行-响应状态码
resp.setStatus(302);
// 2.设置响应头
resp.setHeader("Location", "/he.html");
// 3.发送重定向
resp.sendRedirect("/he.html");

三、Cookie&Session

一、Cookie

  • 存储在浏览器

一、存储数据

// 创建Cookie
// 1.创建Cookie对象
Cookie cookie = new Cookie("username", "张三");
// 2.设置Cookie存活时间,正数为存活时间,负数(默认)为关闭浏览器销毁,0则表示删除此Cookie
// 存活一周,7天
cookie.setMaxAge(60*60*24*7);
// 3.发送Cookie
resp.addCookie(cookie);

二、获取数据

// 获取Cookie
// 1.获取Cookie数组
Cookie[] cookies = req.getCookies();
// 2.遍历数组
for (Cookie cookie : cookies) {
    // 3.获取数据
    String name = cookie.getName();
    if ("username".equals(name)) {
        String value = cookie.getValue();
        System.out.println(name + "-" + value);
        break;
    }
}

三、存活时间

cookie.setMaxAge(60*60*24*7);

二、Session

  • 存储在服务器

一、存储数据

// 存储Session
// 1.获取Session对象
HttpSession httpSession = req.getSession();
// 2.存储数据
httpSession.setAttribute("username", "王五");

二、获取数据

// 获取Session
// 1.获取Session对象
HttpSession httpSession = req.getSession();
// 2.获取数据
Object username = httpSession.getAttribute("username");
System.out.println(username);

三、删除数据

// 删除Session中的数据
HttpSession httpSession2 = req.getSession();
httpSession2.removeAttribute("username");

四、销毁

httpSession.invalidate();

五、存活时间

session.setMaxInactiveInterval(60);  // 此处单位是秒

<session-config>
    <session-timeout>100</session-timeout>  // 单位是分钟 0或者-1则是永不失效。
</session-config>

四、Filter&Listener

一、Filter

一、实现方式

一、注解
  1. 创建普通类实现接口类jakarta.servlet.Filter,并重写所有方法
  2. 使用**@WebFilter**注解,配置拦截目录@WebFilter(“/*”)
@WebFilter("/lohin")
public class test implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // FilterConfig用法与ServletConfig类似
    }

    @Override
    public void destroy() {
        // 释放被Filter对象打开的资源
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 1.自定义逻辑,若请求是UTF-8编码,则放行
        if ("UTF-8".equals(servletRequest.getCharacterEncoding())) {
            // 2.放行,后面的Filter进行拦截
            filterChain.doFilter(servletRequest, servletResponse);
        }
        // 3.访问资源
        String contentType = servletRequest.getContentType();
        // 4.放行后处理
        servletResponse.getWriter().write("your ContentType is" + contentType);
    }
}

二、XML
  1. 创建普通类实现接口类jakarta.servlet.Filter,并重写所有方法
  2. 使用 <filter></filter>和<filter-mapping></filter-mapping>
public class test implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
    <filter>
        <filter-name>test</filter-name>
        <filter-class>全类名</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>test</filter-name>
        <url-pattern>/login</url-pattern>
    </filter-mapping>

二、流程

放行前放行访问资源放行后

三、过滤请求路径

一、具体资源过滤
  1. @WebFilter(“/hello.jsp”)
二、目录过滤
  1. @WebFilter(“/user/*”)
三、后缀名过滤
  1. @WebFilter(“*.jsp”)
四、全部过滤
  1. @WebFilter(“/*”)

四、过滤请求方式

一、REQUEST
  • 仅当用户请求页面时有效,RequestDispatcher的include()或者forward()访问无效
  1. <filter-mapping></filter-mapping>标签中使用<dispatcher>REQUEST</dispatcher>
二、INCLUDE
  • 仅当RequestDispatcher的include()访问有效
  1. <filter-mapping></filter-mapping>标签中使用<dispatcher>INCLUDE</dispatcher>
三、FORWARD
  • 仅当RequestDispatcher的forward()访问有效
  1. <filter-mapping></filter-mapping>标签中使用<dispatcher>FORWARD</dispatcher>
四、ERROR
  • 仅当声明式异常处理机制调用时访问有效
  1. <filter-mapping></filter-mapping>标签中使用<dispatcher>ERROR</dispatcher>

五、过滤器链

  • 优先级按照字符串顺序,以下假设有两个过滤器
  1. 过滤器一放行前过滤器一放行

  2. 过滤器二放行前过滤器二放行

  3. 访问资源

  4. 过滤器二放行后

  5. 过滤器一放行后

六、FilterConfig

  • 作用同ServletConfig

二、Listener

一、实现方式

一、注解
  1. 创建一个普通类实现监听器的接口类,并重写所有方法
  2. 使用**@WebListener**注解
@WebListener
public class ListenerDemo1 implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // 1.加载资源
        System.out.println("加载资源。。。");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 2.释放资源
        System.out.println("释放资源。。。");
    }
}
二、XML
<listener>
    <listener-class>全类名</listener-class>
</listener>

二、八个监听器接口

一、 ServletContextListener
  • Servlet的上下文监听,它主要实现监听ServletContext的创建和删除。该接口提供了两种方法

    1.contextInitialized(ServletContextEvent event);   通知正在收听的对象,应用程序已经被加载和初始化。
    
    2.contextDestroyed(ServletCotextEvent event);   通知正在收听的对象,应用程序已经被载出,即关闭。
    
二、ServletContextAttributeListener
  • 主要实现监听ServletContext属性的增加,删除和修改。该接口提供了一下3个方法

    1.attributeAdded(ServletContextAttributeEvent event);   
    

    当有对象加入Application的范围时,通知正在收听的对象

    2.attributeReplaced(ServletContextAttributeEvent event);
    

    当在application的范围有对象取代另一个对象的时,通知正在收听的对象

    3.attributeRemoved(ServletContextAttributeEvent event); 
    

    当有对象从application的范围移除时,通知正在收听的对象

三、HttpSessionListener
  • HTTP会话监听,该接口实现监听HTTP会话创建、销毁。该接口提供了一下两种方法

    1.sessionCreated(HttpSessionEvent event);       
    

    通知正在收听的对象,session已经被加载及初始化

    2. sessionDestoryed(HttpSessionEvent event)l        
    

    通知正在收听的对象,session已经被载出(HttpSessionEvent类的主要方法是getSession(),可以使用该方法回传一个session对象)

四、HttpSessionAttributeListener
  • 该接口实现监听HTTP会话中属性的设置请求。该接口提供了以下两个方法。

    1.sessionDidActivate(HttpSessionEvent event);          
    

    通知正在收听的对象,它的session已经变为有效状态。

    2.sessionWillPassivate(HttpSessionEvent event);          
    

    通知正在收听的对象,它的session已经变为无效状态

五、HttpSessionBindingListener
  • 接口实现监听HTTP会话中对象的绑定信息。它是唯一不需要在web.xml中设定Listener的。该接口提供了以下2个方法

    1.valueBound(HttpSessionBindingEvent event);                      
    

    当有对象加入session的范围时会被自动调用

    2.valueUnBound(HttpSessionBindingEvent event);                    
    

    当有对象从session的范围内移除时会被自动调用

六、HttpSessionActivationListener
  • 该接口实现监听HTTP会话active和passivate。 该接口提供了一下3个方法

    1.attributeAdded(HttpSessionBindingEvent event);       
    

    当有对象加入session的范围时,通知正在收听的对象

    2.attributeReplaced(HttpSessionBindingEvent event);    
    

    当在session的范围有对象取代另一个对象时,通知正在收听的对象。

    3.attributeRemoved(HttpSessionBindingEvent event);          
    

    当有对象从session的范围有对象取代另一个对象时,通知正在收听的对象 其中HttpSessionBindingEvent类主要有三个方法:getName()、getSession()和getValue()

七、ServletRequestListener
  • 该接口提供了以下两个方法。

    1.requestInitalized(ServletRequestEvent event)             
    

    通知正在收听的对象,ServletRequest已经被加载及初始化

    2.requestDestroyed(ServletRequestEvent event)         
    

    通知正在收听的对象,ServletRequest已经被载出,即关闭

八、ServletRequestAttributeListener
  • 该接口提供了一下三种方法

    1.attributeAdded(ServletRequestAttributeEvent event);     
    

    当有对象加入request的范围时,通知正在收听的对象

    2.attributeReplaced(ServletRequestAttributeEvent event);        
    

    当在request的范围内有对象取代两一个对象时,通知正在收听的对象

    3.attributeRemoved(ServletRequestAttributeEvent event);    
    

    当有对象从request的范围移除时,通知正在收听的对象

五、JSP

一、JavaBean

  • 必须具有一个公共的无参构造方法(默认的无参构造方法即可)。
  • 提供getter和setter方法。
// 这是一个JavaBean
public class Student {
    private String name;
    private int age;
    private boolean married;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setMarried(boolean married) {
        this.married = married;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public boolean isMarried() {
        return married;
    }
}

二、基本JSP

一、JSP Scriptlets

  • <% content %>,用写复杂逻辑,被编译在_jspService()方法中,该方法可以理解为Servlet中的Service()方法。
<%-- 将代码写在一起 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <% 
    	int number = 1;
    
    	if (number == 1) {
        	out.println("yes");  // 控制台输出yes
    	} else { 
            out.println("no");  // 控制台输出no
   		}
    %>
</body>
</html>
<%-- 也可以将java代码拆开写 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    int number = 1;
    
    if (number == 1) {
        out.println("yes");
    } else {
%>
<%
        out.println("no");
    }
%>
</body>
</html>

二、JSP声明语句

  • <%! content %>,用来定义变量或者方法,被编译在_jspService()方法之外。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%!
    	int number = 1;
    %>
    <%!
    	public String show() {
			return "Hello World!";
        }
    %>
    
    <%
    	out.println(number);  <%--控制台输出1--%>
    	out.println(show());  <%--控制台输出Hello World!--%>
    %>
</body>
</html>

三、JSP表达式

  • <%= content %>,用来输出变量或者表达式的值。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%! 
    	int number = 1;
    %>
    <%=  number %>  <%--JSP注释--%>
</body>
</html>

四、JSP注释

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <!--HTML注释-->
    <%--JSP注释--%>
</body>
</html>

五、JSP指令

一、page指令
  • <%@ page 属性名1="值1" 属性名2="值2" ...%>,用来指定该jsp页面的特性。
  • 只有import属性可以出现多次。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>  <%-- 该页面为HTML,UTF-8编码,解释该jsp为java语言,默认是java,并且只能填java --%>
<%@ page import="com.mysql.cj.jdbc.Driver"%>  <%-- 导包 --%>
<%@ page session="true"%>  <%-- true则说明该jsp有内置session对象,可以直接使用,默认为true --%>
<%@ page pageEncoding="UTF-8"%>  <%-- 指定页面编码格式为UTF-8 --%>
<%@ page isErrorPage="true"%>  <%-- 指定该jsp为错误处理页面,内置exception对象,默认为false则没有该对象 --%>
<%@ page errorPage="/error.jsp"%>  <%-- 如果该jsp抛出未捕获的异常,则转到指定的error.jsp(该页面的isErrorPage要先被设置为true) --%>
<%@ page buffer="0kb"%>  <%-- 设置内置对象out的缓冲区大小为0kb,让其能直接输出到页面 --%>
二、include指令
  • 先合成源代码再编译。

  • <%@ include file="./date.jsp",用于包含某个资源文件,即将该文件合并。

  • 被引入的元素必须遵循JSP语法。

<%-- 被包含文件time.jsp,提供当前时间 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%=new Date().toLocaleString()%>
</body>
</html>
<%-- index.jsp,包含time.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<% out.println("hello World!"); %>
<%@ include file="./time.jsp"%>  <%-- 访问后,显示当前时间 --%>
</body>
</html>

上述文件合并本质上是

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <% out.println("hello World!"); %>
    <%=new Date().toLocaleString()%>
</body>
</html>

六、JSP内置对象

一、out
  • 输出步骤:out.println(“Hello World!”)->response.getWriter().println(“Hello World!”)->页面显示Hello World!
  • 若out.println()和response.getWriter().println()同时调用,则优先显示后者的结果(共一步),因为前者的作用是将数据写入缓冲区,最后调用后者来输出(共两步),若想要前者达到与后者同样的效果,需要设置buffer为0kb,使其不写入缓冲区而直接调用后者输出。
<%
	out.println("first");
	response.getWriter().println("second");
	<%--先显示second,后显示first--%>
%>
<%@ page buffer="0kb"%>  <%-- 设置out缓存区为0kb,即直接调用response.getWriter().println() --%>
<%
	out.println("first");
	response.getWriter().println("second");
	<%--先显示first,后显示second--%>
%>
二、request&response
  • 作用见Request&Response
三、config&application
  • 作用见ServletConfig&ServletContext
四、session
  • 作用见HttpSession
五、page
  • 当前jsp转换成Servlet的实例对象
六、exception
  • 用在错误处理页面中
<%-- index.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page errorPage="./error.jsp" %>  <%-- 指定错误页面 --%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        out.print(3 / 0);  // 出异常,会重定向至error.jsp
    %>
</body>
</html>
<%-- error.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isErrorPage="true" %>  <%-- 表示该页面为错误处理页面 --%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    System.out.println(exception.getMessage());  // 控制台输出 / by zero
%>
</body>
</html>
七、pageContext
  • 能获取以上六种内置对象
  • 能共享、获取、删除、查询Attribute
PageContext四个作用域
public static final int PAGE_SCOPE = 1;  // 页面范围
public static final int REQUEST_SCOPE = 2;  // 请求范围
public static final int SESSION_SCOPE = 3;  // 会话范围
public static final int APPLICATION_SCOPE = 4;  // Web应用程序范围
<%
    pageContext.setAttribute("str", "hello");  // 不设置范围,默认是PAGE_SCOPE
    pageContext.setAttribute("str1", "hello1", PageContext.PAGE_SCOPE);
    pageContext.setAttribute("str2", "hello2", PageContext.REQUEST_SCOPE);
    pageContext.setAttribute("str3", "hello3", PageContext.SESSION_SCOPE);
    pageContext.setAttribute("str4", "hello4", PageContext.APPLICATION_SCOPE);
    <%--等价,只不过上面是将属性都设置到了pageContext中,而下面是将属性设置到对应对象中--%>
	pageContext.setAttribute("str", "hello");
    pageContext.setAttribute("str1", "hello1");
    request.setAttribute("str2", "hello2");
    session.setAttribute("str3", "hello3");
    application.setAttribute("str4", "hello4");

    System.out.println(pageContext.getAttribute("str"));  // hello;获取默认范围的属性值
    System.out.println(pageContext.getAttribute("str1", PageContext.PAGE_SCOPE));  // hello1
    System.out.println(pageContext.getAttribute("str2", PageContext.REQUEST_SCOPE));  // hello2
    System.out.println(pageContext.getAttribute("str3", PageContext.SESSION_SCOPE));  // hello3
    System.out.println(pageContext.getAttribute("str4", PageContext.APPLICATION_SCOPE));  // hello4
%>

七、JSP动作元素

一、<jsp:include/>
  • <jsp:include page="xxx.jsp" flush="false"/>,用于包含指定页面。

  • 先编译各自的代码,再合并结果。

  • 与include指令不同的是,被引入的资源必须单个也能执行。

  • flush默认为false,即同时输出本页面和被包含页面的结果,若为 true,则先输出本页面的结果,再输出被包含页面的结果。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>included!</h1>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>index!</h1>
    <jsp:include page="./included.jsp" flush="false"/>
</body>
</html>
二、<jsp:forward/>
  • <jsp:forward page="xxx.jsp"></jsp:forward>,用于请求转发至指定页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<jsp:forward page="./forward.jsp"></jsp:forward>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>forward!</h1>
</body>
</html>
三、<jsp:useBean/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="student" class="com.miao.dao.entity.Student" scope="page"></jsp:useBean>
<%-- id:变量名,class:全类名,scope:默认是page,作用范围(page | request | session | application) --%>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        student.setName("jack");
        student.setAge(18);
        student.setMarried(true);
        System.out.println(student.getName() + student.getAge() + student.isMarried());  // jack18true
    %>
</body>
</html>

三、EL表达式

  • 用于获取四个作用域或者JavaBean的属性值:

  • ${表达式}

  • ${username},会按照page、request、session、application的顺序查找该属性的值。

一、运算符
  1. .运算符

  2. []运算符

  3. 算术运算符

  4. 比较运算符

  5. 逻辑运算符

  6. empty运算符

    • ${empty obj},若obj为不存在或者为null或者为数组时但没元素,则返回true。
  7. 条件运算符

  8. ()运算符

点运算符:${s.sname}
方括号运算符:${s["sname"]}
算术运算符:${s.sage - 10}
比较运算符:${s.sage > 10}
逻辑运算符:${true && false}
empty运算符:${empty s}
条件运算符:${("张飞".equals(s.sname)) ? "hello" : "world!"}
()运算符:${2 * (3+2)}
二、内置对象
  • pageContext

  • pageScope

  • requestScope

  • sessionScope

  • applicationScope

  • param

  • paramValues

  • header

  • headerValues

  • cookie

  • initParam

四、JSTL标签

一、<c:out>
<c:out value="优先显示" default="不能与标签体一起使用">
    次之
</c:out>
二、<c:if>
<c:if test="${1 == 1}">
    c:if
</c:if>
三、<c:choose>
<c:choose>
    <c:when test="${param.num1 == 1}">
        1
    </c:when>
    <c:when test="${param.num2 == 2}">
        2
    </c:when>
    <c:otherwise>
        3
    </c:otherwise>
</c:choose>
四、<c:forEach>
<c:forEach var="user" items="<%=userMap%>" begin="0" end="4" step="1">
    ${user.key}---${user.value}
</c:forEach>
五、<c:param>
  • <c:url>一起使用
六、<c:url>
<c:url var="myUrl" value="http://localhost:8080/hello.jsp">
    <c:param name="username" value="张三"/>
</c:url>
<a href="${myUrl}">地址</a>  <!-- href="http://localhost:8080/hello.jsp?username=张三" -->

六、JDBC

一、JDBC入门

  • # 在resources目录下,jdbc.properties
    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?useUnicode=ture&charset=UTF-8
    username=root
    password=123456
    

一、Statement

  • 不能防止SQL注入
package com.miao.DataSource.JDBC.MySQL;

import java.sql.*;
import java.util.ResourceBundle;

public class JDBC_statement {
    public static void main(String[] args) {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc");
        String driver = resourceBundle.getString("driver");
        String url = resourceBundle.getString("url");
        String username = resourceBundle.getString("username");
        String password = resourceBundle.getString("password");
        Connection conn = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            // 注册驱动
            Class.forName(driver);
            // 获取连接
            conn = DriverManager.getConnection(url, username, password);
            // 获得操作对象
            statement = conn.createStatement();

            String sql = "SELECT * FROM l1;";
            resultSet = statement.executeQuery(sql);

            while (resultSet.next()){
                System.out.println(resultSet.getString("name"));
                System.out.println(resultSet.getInt("age"));
            }

        } catch (ClassNotFoundException | SQLException e){
            e.printStackTrace();
        } finally {
            if (resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
            }
            if (statement != null){
                try {
                    statement.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
            }
        }

    }
}

二、PreparedStatement

  • 能防止SQL注入
package com.miao.DataSource.JDBC.MySQL;

import java.sql.*;
import java.util.ResourceBundle;

public class JDBC_prestatement {
    public static void main(String[] args) {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc");
        String driver = resourceBundle.getString("driver");
        String url = resourceBundle.getString("url");
        String username = resourceBundle.getString("username");
        String password = resourceBundle.getString("password");
        Connection conn = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            // 注册驱动
            Class.forName(driver);
            // 获取连接
            conn = DriverManager.getConnection(url, username, password);
            // 获得操作对象
            String sql = "SELECT * FROM l1 WHERE age=?;";
            preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setInt(1, 18);
            resultSet = preparedStatement.executeQuery();

            while (resultSet.next()){
                System.out.println(resultSet.getString("name"));
                System.out.println(resultSet.getInt("age"));
            }

        } catch (ClassNotFoundException | SQLException e){
            e.printStackTrace();
        } finally {
            if (resultSet != null){
                try {
                    resultSet.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null){
                try {
                    preparedStatement.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
            }
        }
    }
}

二、DBUtils

  • Apache Commons DbUtils

一、QueryRunner类

  • query(String sql, ResultSetHandler tsh, Object… params)
  • update(String sql, Object… params)
  • update(String sql)

二、ResultSetHandler接口

  • 自定义实现该接口,并实现handler()即可。

三、ResultSetHandler实现类

一、BeanHandler
  • 将结果集中第1行数据封装到对应的JavaBean。
  • query(sql, new BeanHandler(User.class), new Object[] {id}),第三个参数可以是任意类型的值,如1,“string”。
二、BeanListHandler
  • 将结果集中每一行数据封装到对应的JavaBean。
  • query(sql, new BeanListHandler)
三、ScalarHandler
  • 将结果集中某一条记录的其中某一列数据存储成Object对象。
  • query(sql, new ScalarHandler(User.class), new Object[] {id}),第三个参数可以是任意类型的值,如1,“string”。

七、JSP开发模型

  • JSP Model2,实际上就是MVC开发模式,三层架构。

一、三层架构

一、Controller

  • 如处理请求的接口,即Servlet
  1. 取得表单数据
  2. 调用业务逻辑
  3. 转向指定的页面

二、Model

  • 如各种实体类及服务逻辑,Student、User
  1. 业务逻辑
  2. 保存数据的状态

三、View

  • 前端页面,login.jsp
  1. 显示页面

二、目录结构

目录结构
    src	
    	main|
    		|java|
				 |controller|
							|HelloController.java|  // Controller层,调用Model层和View层
				 |service|
						 |LoginService.java|  // Model层,业务逻辑
				 |dao|
						|User.java|  // Model层,实体类
						|util|
							 |JdbcUtils.java| Model层,接触数据库
    		|webapp|
    			   |WEB-INF|
    					   |web.xml|
						   |index.jsp|  // View层
    pom.xml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cs4m

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值