JavaWeb学习笔记


JavaWeb.

1.基本概念.

1.1 前言.

Web开发:

  • Web、网页的意思, www.baidu.com
  • 静态Web
    • html,CSS
    • 提供给所有人看的数据始终不会改变
  • 动态Web
    • 淘宝,几乎所有的网站
    • 提供给所有人看的数据始终会变化,每个人在不同时间,不同的地点看到的信息不相同
    • 技术栈:Servlet/JSP, ASP ,PHP

在java中,动态Web资源开发的技术成为javaWeb

1.2 Web应用程序.

web应用程序:可以提供浏览器访问的程序

  • a.html, b.html, 多个web资源,这些web资源可以被外界访问,对外界提供服务
  • 你们能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上
  • URL
  • 这个统一的Web资源会放在同一个文件夹下,Web应用程序 –> toomcat服务器
  • 一个web应用由多部分组成(动态 静态)
    • HTML
    • JSP,Servlet
    • jar包
    • 配置文件(Poperties)

web应用程序编写完毕后,若想提供给外界访问,需要一个服务器来统一管理

1.3 静态Web.

  • .htm 、\.html 这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取

  • 静态web存在的缺点
    • Web页面无法动态更新,所有用户看到都是同一个页面
      • 轮播图,点击特效:伪动态
      • JavaScript
      • VBScript
    • 它无法和数据库交互(数据无法 持久化,用户无法交互)

1.4 动态Web.

页面会动态展示:“Web的页面展示的效果 因人而异”;

缺点

  • 假如服务器的动态Web资源出现了错误,我们需要重新编写我们的后台程序,重新发布(停机维护)

优点

  • Web页面可以动态更新,所有用户看到都不是同一个页面
  • 它可以和数据库交互(数据持久化:注册,商品信息,用户信息……)

2.Web服务器.

2.1 技术讲解.

ASP:

  • 微软:国内最早流行的就是ASP

  • 在HTML 中嵌入了VB的脚本,ASP+COM;

  • 在ASP开发中,基本一个页面都有几千行的业务代码,页面及其混乱

  • C#

  • IIS(Internet Information Services)

PHP

  • PHP开发速度很快、功能很强大,跨平台,代码很简单(70% wordPress)
  • 无法承载大访问量的情况(局限性)

JSP/Servlet

B/S: 浏览器和服务器

C/S:客户端和服务器

  • sum公司主推的B/S架构
  • 基于java语言的(所有的大公司,或者一些开源的组件都是用java写的)
  • 可以承载三高(高并发,高可用,高性能)带来的问题
  • 语法像ASP, ASP –> JSP, 加强市场强度;

2.2 Web服务器.

服务器是一种被动的操作,用来处理用户的一些请求和用户一些响应信息;

IIS

微软的:ASP… Windows中自带

Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个java初学Web的人来说,它是最佳的选择

Tomcat 实际上运行JSP 页面和Servlet。目前Tomcat最新版本为9.0.36

工作3-5年之后,可以尝试手写Tomcat服务器;

下载tomcat:

​ 1.安装 or 解压

​ 2.了解配置文件及目录结构

​ 3.这个东西的作用

3. Tomcat.

3.1 安装tomcat.

Tomcat官网:https://tomcat.apache.org/download-90.cgi

下载完解压

文件夹作用

3.2 Tomcat启动和配置.

启动,关闭tomcat

访问: localhost:8080

可能遇到的问题

​ 1.Java环境变量没有设置

​ 2.闪退问题:需要配置兼容性

​ 3.乱码问题:配置文件中的设置

3.3 配置.

可以配置主机的端口号

默认端口:8080

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

可以配置主机名

  • 默认主机名:localhost -> 127.0.0.1
  • 默认网站存放的位置为:webapps
<Host name="tc.test.com"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

==高难度面试题:==.

请你谈谈网站如何进行访问的?

​ 1.输入一个域名;回车

​ 2.检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名的配置映射

​ 1.有:直接返回对应的IP地址,在这个地址中有我们需要访问的web程序,可以直接访问

​ 2.没有,去DNS服务器找,找到的话就返回,找不到就走丢了

.

可以配置一下环境变量(可选)

3.4 发布一个Web网页.

不会就模仿

  • 将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹写,就可以访问了

网站应该有这样的结构

--webapps :Tomcat服务器的web目录
    -ROOT
    -your website :网站的目录名
        - WEB-INF
            -classes : java程序
            -lib:web应用所依赖的jar包
            -web.xml :网站配置文件
        - index.html 默认的首页
        - static 
            -css
                -style.css
            -js
            -img
         -.....

4. HTTP.

4.1 什么是HTTP.

http(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上。

  • 文本: HTML,字符串, …
  • 超文本:图片、音乐、视频、定位、地图、…

HTTPS: 安全的

==4.2 两个时代==.

  • http1.0
    • HTTP/1.0:客户端可以与web服务器连接后,只能获得一个Web资源(第一次请求,然后断开连接,只有再次请求,才能获得新资源)(耗流量)
  • http2.0
    • HTTP/1.1:客户端可以与web服务器连接后,只能获得多个Web资源

4.3 HTTP请求.

  • 客户端发请求到服务器

    百度为例

Request URL: https://www.baidu.com/  请求地址
Request Method: GET   get方法/post方法
Status Code: 200 OK        状态码
Remote Address: 182.61.200.7:443   远程地址
Referrer Policy: no-referrer-when-downgrade

​ Request Header

Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9    语言
Cache-Control: max-age=0
Connection: keep-alive
1.请求行.

  • 请求行中的请求方式: GET

  • 请求方式:GET ,POST ,HEAD ,DELETE ,PUT ,TRACT …

    • get : 请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但是高效
    • post:请求能够携带的参数没有限制,大小没有有限制,不会在浏览器的URL地址栏显示数据内容,安全,但是不高效
2.消息头.
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.

4.4 HTTP响应.

  • 服务器响应客户端

    Response Header(部分信息分析)

Cache-Control: private    缓存控制
Connection: keep-alive    连接:保持连接
Content-Encoding: gzip    编码
Content-Type: text/html;charset=utf-8    类型
1.响应体.
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持哪种编码格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告诉浏览器,它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成是断开还是保持连接
HOST:主机..../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;
2.响应状态码(看后面).

200:请求响应成功

3**:请求重定向

4**:找不到页面

5**:服务器代码错误

  • 502:网关错误

5. Maven.

官网;https://maven.apache.org/

我们为什么要学习这个技术?

  1. 在JavaWeb开发中,需要使用大量的jar包,我们手动去导入

  2. 如何能够让一个东西自动帮我导入和配置这个jar包

    由此,Maven诞生了

5.1 Maven 项目架构管理工具.

我们目前用来就是方便导入jar包的

Maven的核心思想: 约定大于配置

  • 有约束,不要去违反

Maven会规定好你该如何编写好我们的java代码,必须要按照这个规范来

配置镜像.
conf 中配置setting.xml 在mirrors中修改.
<!--aliyun镜像-->
<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>        
</mirror>

这个不配也可以 享受:snail:的感觉

配置环境变量.
  • M2_HOME maven目录下的bin目录
  • MAVEN_HOME maven的目录
  • 在系统的path中配置 %MAVEN_HOME%\bin
# 查看是否配置成功
mvn -version
建立本地仓库.

还是 setting文件

在IDEA中使用Maven.

1.启动IDEA

2.创建一个maven项目

3.创建建议一个简单maven javaweb项目

4.IDEA中的Maven设置

注意:IDEA项目创建成功后要看一下配置

5.到这里,Maven在IDEA中配置结束了

创建一个普通的Maven项目.

就是选模板什么也不选

pom文件.

pom.xml是Maven的核心配置文件

maven资源文件导出问题.

https://www.cnblogs.com/pixy/p/4798089.html

<!--在build中配置resources,来防止我们资源导出失败问题-->
<build>
      <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
             </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>
maven web项目中servlet配置.
<web-app>
<!--  添加一个servlet-->
  <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>HelloServlet</servlet-class>
  </servlet>
<!--  一个servlet对应一个Mapping-->
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/servlet</url-pattern>
  </servlet-mapping> 
</web-app>

6.servlet.

6.1 Servlet简介.

  • Servlet就是sun公司开发动态的一门技术
  • Sun在这些API中提供了一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤
    • 编写一个类,实现Servlet接口
    • 把开发好的Java类部署到web服务器中

把实现了Servlet接口的java程序叫做,Servlet

6.2 HelloServlet.

  • Serlet接口Sun公司有两个默认的实现类:HttpServlet、GenericServlet

​ 1. 构建一个普通Maven项目,删掉里面的src目录,以后就在这个项目中建立module,这个空的Project 就是主工程

  1. 关于Maven父子进程的理解:

    1. 父项目中会有

      <modules>
          <module></module>
      </modules>
      2. 子项目会有
      <parent>
          <artifactId></artifactId>
          <groupId></groupId>
          <version></version>
      </parent>
      父项目中的java子项目可以直接使用.

      son extends father

      3. Maven环境优化
      
      1. 修改web.xml版本为最新
      <?xml version="1.0" encoding="UTF-8"?>
      
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                            http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
               version="4.0">
          <!--在这里面增加 servlet 和 servlet-mapping-->
      </web-app>
    2.将maven的结构搭建完整





        4. 编写一个Servlet程序

    1. 编写一个普通的类
    2. 继承一个HttpServlet类

    ```java
    @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html");
            response.setCharacterEncoding("utf-8");
            PrintWriter out = response.getWriter();
            out.println("<html>");
            out.println("<head>");
            out.println("<title>刘民锴</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>刘民锴</h1>");
            out.println("<h1>Hello World!</h1>");
            out.println("<h1>Hello World!</h1>");
            out.println("<h1>Hello World!</h1>");
            out.println("</body>");
            out.println("</html>");
        }

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



        5. 编写Servlet映射

        1. 为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径

        ```xml
        <web-app>
        <!--  添加一个servlet-->
          <servlet>
            <servlet-name>helloServlet</servlet-name>
            <servlet-class>HelloServlet</servlet-class>
          </servlet>
        <!--  一个servlet对应一个Mapping-->
          <servlet-mapping>
            <servlet-name>helloServlet</servlet-name>
            <url-pattern>/hello</url-pattern>
          </servlet-mapping>

        ```



6. 配置Tomcat

1. 注意配置项目发布的路径就可以了

        7. 启动测试

6.3 Servlet原理.

Servlet是由Web服务器调用,web服务器在收到请求之后,会:

6.4 Mapping问题.

  1. 一个Servlet可以指定一个映射路径
<servlet-mapping>
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
  1. 一个Servlet可以指定多个映射路径
<servlet-mapping>
    <!-- hello1 -->
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello1</url-pattern>
    <!-- hello2 -->
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello2</url-pattern>
    <!-- hello3 -->
    <servlet-name>helloServlet</servlet-name>
    <url-pattern>/hello3</url-pattern>
  </servlet-mapping>
  1. 一个Servlet可以指定通用

    <!-- hello/* -->
    <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <url-pattern>/hello/*</url-pattern>
     </servlet-mapping>

    注意 : 不能 写成 /* ,因为 /* 包含 / ,他会把主页面干掉

  2. 自定义后缀或前缀实现请求映射

   <!-- hello/* -->
   <servlet-mapping>
       <servlet-name>helloServlet</servlet-name>
       <url-pattern>*.hello</url-pattern>
    </servlet-mapping>

注意:在 * 的前面不能加 /

只要是 以 .hello 结尾的都可以访问

6.5 ServletContext(管理web应用).

Web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用

共享数据.
  • 我在这个Servlet中保存的数据,可以在另一个Servlet中访问到
@WebServlet("/this")
public class test02_this extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//        this.getInitParameter(); 初始化参数
//        this.getServletConfig();  Servlet配置信息
//        this.getServletContext(); Servlet上下文
//        this.getServletInfo();
//        this.getServletName();

        //重点 上下文
        ServletContext context = this.getServletContext();
        String name = "刘民锴";
        context.setAttribute("name",name);

    }
@WebServlet("/this1")
public class test02_this1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        Object name = context.getAttribute("name");
        System.out.println(name);
    }
}

看控制台

获取初始化参数.
@WebServlet("/test2")
public class test02_this2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //
        System.out.println("从web.xml中获得的初始化参数 url = "+context.getInitParameter("url"));

    }
}
<!--Web.xml web-app中添加-->
  <!--配置 一些Web应用初始化参数-->
<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306/message</param-value>
    <!--      可以使用上下文ServletContext-->
    <!--      context.getInitParameter()-->
    <!--      this.getInitParameter()-->
</context-param>
请求转发(Request Dispatcher).
  • 转发路径不会变

@WebServlet("/context2")
public class text03_context2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        // 转发到 /servlet01/404
        context.getRequestDispatcher("/404").forward(req,resp);
    }
}
@WebServlet("/404")
public class ErrorServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");

        PrintWriter out = resp.getWriter();
        out.print("<h1>404</h1>");
    }
}

重定向

读取资源文件.

Properties

  • 在java目录下新建properties
  • 在resource目录下新建properties

发现:都被打包到同一路径下:classes,我们俗称类路径(classpath)

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        InputStream in = context.getResourceAsStream("WEB-INF/classes/db.properties");
        Properties p = new Properties();
        p.load(in);
        String name = p.getProperty("username");

        resp.getWriter().println("从Resources中获取 name :"+name);
    }

6.6 HttpServletResponse.

web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应一个HttpServletResponse;

  • 如果要获取客户端请求过来的参数:找HttpServletRequest
  • 如果要给客户端响应一些信息:HttpServletResponse
1.简单分类.
1.负责向浏览器送数据的方法.
public ServletOutputStream getOutputStream() throws IOException; // 平常的流(字节)

public PrintWriter getWriter() throws IOException; // 写一些中文字符
2.负责向浏览器发送响应头的方法.
//ServletResponse
public void setCharacterEncoding(String charset);

public void setContentLength(int len);

public void setContentLengthLong(long len);

public void setContentType(String type);

//HttpServletResponse
public void addDateHeader(String name, long date);

public void setHeader(String name, String value);

public void addHeader(String name, String value);

public void setIntHeader(String name, int value);

public void addIntHeader(String name, int value);
3.响应的状态码常量.
//响应的状态码常量
/*
     * Server status codes; see RFC 2068.
     */

    /**
     * Status code (100) indicating the client can continue.
     指示客户端可以继续
     */
    public static final int SC_CONTINUE = 100;

    /**
     * Status code (101) indicating the server is switching protocols
     according to Upgrade header.

     服务器正在交换协议
     */
    public static final int SC_SWITCHING_PROTOCOLS = 101;

    /**
     * Status code (200) indicating the request succeeded normally.
     指示请求正常成功
     */
    public static final int SC_OK = 200;

    /**
     * Status code (201) indicating the request succeeded and created
     指示请求成功并创建服务器上的新资源
     * a new resource on the server.
     */
    public static final int SC_CREATED = 201;

    /**
     * Status code (202) indicating that a request was accepted for
      processing, but was not completed.
      状态码(202)表示一个请求被接受
处理,但未完成
     */
    public static final int SC_ACCEPTED = 202;

    /**
     * Status code (203) indicating that the meta information presented
      by the client did not originate from the server.
      状态代码(203)表明元信息被呈现
由客户端不起源于服务器
     */
    public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;

    /**
     * Status code (204) indicating that the request succeeded but that
     there was no new information to return.
     状态码(204),指示请求成功,但不能
没有新的信息可以返回。
     */
    public static final int SC_NO_CONTENT = 204;

    /**
     * Status code (205) indicating that the agent <em>SHOULD</em> reset
      the document view which caused the request to be sent.
      状态码(205),指示代理应重置
导致请求被发送的文档视图
     */
    public static final int SC_RESET_CONTENT = 205;

    /**
     * Status code (206) indicating that the server has fulfilled
     the partial GET request for the resource.
     状态码(206),指示服务器已经完成
对资源的部分GET请求。
     */
    public static final int SC_PARTIAL_CONTENT = 206;

    /**
     * Status code (300) indicating that the requested resource
     corresponds to any one of a set of representations, each with
    its own specific location.
    状态码(300)表示所请求的资源
对应于一组表示中的任何一个,每一个都具有
它自己的特定位置。
     */
    public static final int SC_MULTIPLE_CHOICES = 300;

    /**
     * Status code (301) indicating that the resource has permanently
      moved to a new location, and that future references should use a
      new URI with their requests.
      状态码(301)指示资源已永久
移到一个新的位置,并且以后的引用应该使用
新URI及其请求。
     */
    public static final int SC_MOVED_PERMANENTLY = 301;

    /**
     * Status code (302) indicating that the resource has temporarily
     moved to another location, but that future references should
     still use the original URI to access the resource.

     This definition is being retained for backwards compatibility.
     SC_FOUND is now the preferred definition.
     状态码(302),指示资源有临时
移到另一个位置,但是以后的引用应该
仍然使用原始URI访问资源。
保留这个定义是为了向后兼容。
SC_FOUND现在是首选定义。
     */
    public static final int SC_MOVED_TEMPORARILY = 302;

    /**
    * Status code (302) indicating that the resource reside
temporarily under a different URI. Since the redirection might
 be altered on occasion, the client should continue to use the
 Request-URI for future requests.(HTTP/1.1) To represent the
 status code (302), it is recommended to use this variable.
 状态代码(302),指示资源临时驻留在不同的URI下。因为重定向可能
如有更改,客户端应继续使用
用于将来请求的请求uri
状态码(302),建议使用此变量
    */
    public static final int SC_FOUND = 302;

    /**
     * Status code (303) indicating that the response to the request
     * can be found under a different URI.
     */
    public static final int SC_SEE_OTHER = 303;

    /**
     * Status code (304) indicating that a conditional GET operation
     * found that the resource was available and not modified.
     */
    public static final int SC_NOT_MODIFIED = 304;

    /**
     * Status code (305) indicating that the requested resource
     * <em>MUST</em> be accessed through the proxy given by the
     * <code><em>Location</em></code> field.
     */
    public static final int SC_USE_PROXY = 305;

     /**
     * Status code (307) indicating that the requested resource 
     * resides temporarily under a different URI. The temporary URI
     * <em>SHOULD</em> be given by the <code><em>Location</em></code> 
     * field in the response.
     */
    public static final int SC_TEMPORARY_REDIRECT = 307;

    /**
     * Status code (400) indicating the request sent by the client was
     * syntactically incorrect.
     */
    public static final int SC_BAD_REQUEST = 400;

    /**
     * Status code (401) indicating that the request requires HTTP
     * authentication.
     */
    public static final int SC_UNAUTHORIZED = 401;

    /**
     * Status code (402) reserved for future use.
     */
    public static final int SC_PAYMENT_REQUIRED = 402;

    /**
     * Status code (403) indicating the server understood the request
     * but refused to fulfill it.
     */
    public static final int SC_FORBIDDEN = 403;

    /**
     * Status code (404) indicating that the requested resource is not
     * available.
     */
    public static final int SC_NOT_FOUND = 404;

    /**
     * Status code (405) indicating that the method specified in the
     * <code><em>Request-Line</em></code> is not allowed for the resource
     * identified by the <code><em>Request-URI</em></code>.
     */
    public static final int SC_METHOD_NOT_ALLOWED = 405;

    /**
     * Status code (406) indicating that the resource identified by the
     * request is only capable of generating response entities which have
     * content characteristics not acceptable according to the accept
     * headers sent in the request.
     */
    public static final int SC_NOT_ACCEPTABLE = 406;

    /**
     * Status code (407) indicating that the client <em>MUST</em> first
     * authenticate itself with the proxy.
     */
    public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;

    /**
     * Status code (408) indicating that the client did not produce a
     * request within the time that the server was prepared to wait.
     */
    public static final int SC_REQUEST_TIMEOUT = 408;

    /**
     * Status code (409) indicating that the request could not be
     * completed due to a conflict with the current state of the
     * resource.
     */
    public static final int SC_CONFLICT = 409;

    /**
     * Status code (410) indicating that the resource is no longer
     * available at the server and no forwarding address is known.
     * This condition <em>SHOULD</em> be considered permanent.
     */
    public static final int SC_GONE = 410;

    /**
     * Status code (411) indicating that the request cannot be handled
     * without a defined <code><em>Content-Length</em></code>.
     */
    public static final int SC_LENGTH_REQUIRED = 411;

    /**
     * Status code (412) indicating that the precondition given in one
     * or more of the request-header fields evaluated to false when it
     * was tested on the server.
     */
    public static final int SC_PRECONDITION_FAILED = 412;

    /**
     * Status code (413) indicating that the server is refusing to process
     * the request because the request entity is larger than the server is
     * willing or able to process.
     */
    public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;

    /**
     * Status code (414) indicating that the server is refusing to service
     * the request because the <code><em>Request-URI</em></code> is longer
     * than the server is willing to interpret.
     */
    public static final int SC_REQUEST_URI_TOO_LONG = 414;

    /**
     * Status code (415) indicating that the server is refusing to service
     * the request because the entity of the request is in a format not
     * supported by the requested resource for the requested method.
     */
    public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;

    /**
     * Status code (416) indicating that the server cannot serve the
     * requested byte range.
     */
    public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;

    /**
     * Status code (417) indicating that the server could not meet the
     * expectation given in the Expect request header.
     */
    public static final int SC_EXPECTATION_FAILED = 417;

    /**
     * Status code (500) indicating an error inside the HTTP server
     * which prevented it from fulfilling the request.
     */
    public static final int SC_INTERNAL_SERVER_ERROR = 500;

    /**
     * Status code (501) indicating the HTTP server does not support
     * the functionality needed to fulfill the request.
     */
    public static final int SC_NOT_IMPLEMENTED = 501;

    /**
     * Status code (502) indicating that the HTTP server received an
     * invalid response from a server it consulted when acting as a
     * proxy or gateway.
     */
    public static final int SC_BAD_GATEWAY = 502;

    /**
     * Status code (503) indicating that the HTTP server is
     * temporarily overloaded, and unable to handle the request.
     */
    public static final int SC_SERVICE_UNAVAILABLE = 503;

    /**
     * Status code (504) indicating that the server did not receive
     * a timely response from the upstream server while acting as
     * a gateway or proxy.
     */
    public static final int SC_GATEWAY_TIMEOUT = 504;

    /**
     * Status code (505) indicating that the server does not support
     * or refuses to support the HTTP protocol version that was used
     * in the request message.
     */
    public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
2. 常见应用.
1.向浏览器输出消息(输出流,略).
2.下载文件(步骤).
  1. 要获取下载文件的路径
  2. 下载的文件名是啥
  3. 设置想办法让浏览器能够支持下载我们需要的东西
  4. 获取下载文件的输入流
  5. 创建缓冲区
  6. 获取OutputStream对象
  7. 将FileOutputStream流写入到buffer缓冲区
  8. 使用OutputStream将换缓冲区中的数据输出到客户端
@WebServlet("/download")
public class DownloadFile extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1. 要获取下载文件的路径
        String realPath = "C:\\Users\\14239\\Desktop\\新Hadoop\\pandownload\\JavaWebTest\\servlet01\\target\\classes\\db.properties";
        System.out.println("下载文件的路径:"+ realPath);
//        2. 下载的文件名是啥
        String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
//        3. 设置想办法让浏览器能够支持下载我们需要的东西 内容处理 附件
        resp.setHeader("Content-Disposition","attachment;fileName="+ URLEncoder.encode(fileName,"utf-8"));
//        4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
//        5. 创建缓冲区
        int len = 0;
        byte[] buf = new byte[2048];
//        6. 获取OutputStream对象
        ServletOutputStream out = resp.getOutputStream();
//        7. 将FileOutputStream流写入到buffer缓冲区
        while((len=in.read(buf)) != -1){
            out.write(buf,0,len);
        }
        out.close();
        in.close();
//        8. 使用OutputStream将换缓冲区中的数据输出到客户端

    }
}
3.验证码.

验证码怎么来的

  • 前端实现
  • 后端实现,需要用到java的图片类
@WebServlet("/verifycode")
public class VerifyCode extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //如何让浏览器5秒刷新一次
        resp.setHeader("refresh","3");

        //在内存中创建一个图片
        BufferedImage bufImage = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics2D g = (Graphics2D) bufImage.getGraphics(); //笔
        g.fillRect(0,0,80,20);
        //给图片写数据
        g.setColor(Color.red);
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(makeNum(),0,20);

        //告诉浏览器,这个请求用图片的方式打开
        resp.setContentType("image/jpeg");
        //网站存在缓冲,不让他缓冲
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //图片写到浏览器
        ImageIO.write(bufImage,"jpg",resp.getOutputStream());
    }

    // 生成随机数
    private String makeNum(){
        Random rand = new Random();
        String num = rand.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i=0; i < 7 - num.length(); i++){
            sb.append("0"); // 不足7位 0填充
        }
        num = sb.toString() + num;
        return num;
    }
}
4.实现重定向.
  • 一个Web资源收到客户端请求后,他会通知客户端去访问另一个web资源

public void sendRedirect(String location) throws IOException;
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        resp.setHeader("Location","/servlet01/verifycode");
//        resp.setStatus(302);
        resp.sendRedirect("http://www.baidu.com");
    }
}
面试题:请你聊聊重定向和转发的区别.

相同点

  • 页面都会跳转

不同点

  • 请求转发时,URL不会改变 307
  • 页面转发 –> 在当前服务器内部的行为,能够共享上一次请求的数据
  • 重定向时,URL会变化 302
  • 页面重定向 –> 发起了一次新的请求,可以请求到服务器外部资源,上一次请求数据会丢失

注意:转发不需要加项目路径,重定向需要加项目路径

6.7 HttpServletRequest.

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器;Http请求的所有信息会被封装到这个类里

1. 获取前端传递的参数.
public String getParameter(String name);
public String[] getParameterValues(String name);
2.请求转发.
public RequestDispatcher getRequestDispatcher(String path);

7.Cookie、Session.

7.1、 会话.

会话: 用户打开了一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程叫做会话

有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过,称之为有状态会话

7.2、保存会话的两种技术.

  • cookie
    • 客户端技术
  • session
    • 服务器技术,利用这个技术,可以保留用户的会话信息,可以把信息或者数据放在Session中

7.3、cookie.

  • 从请求中拿到cookie信息
  • 服务器响应给客户端
Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
//获取上一次登陆时间
@WebServlet("/lastLoginTime")
public class CookieDemo01  extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        // 获取请求中的数据
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //获取Cookies
        Cookie[] cookies = req.getCookies();
        //获取输出流
        PrintWriter out = resp.getWriter();
        if(cookies != null){
            for (int i=0; i < cookies.length; i++){
                if("userLoginTime".equals(cookies[i].getName())){
                    //获取上次登录时间
                    String value = cookies[i].getValue();
                    //字符串转为long
                    long time = Long.parseLong(value);
                    //long变成date
                    Date date = new Date(time);
                    //System.out.println("EEE MMM dd HH:mm:ss zzz yyyy");
                    //Tue Jun 30 21:57:00 CST 2020

                    //格式化
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String datetime = sdf.format(date);
                    out.println("上一次登录时间"+ datetime);
                    System.out.println("上一次登录时间"+ datetime);
                }
            }
        }else{
            out.write("你是第一次登录");
        }

        // 每次都刷新 cookie (本次登录时间)
        //new Cookie
        Cookie cookie = new Cookie("userLoginTime", String.valueOf(System.currentTimeMillis()));
        //存入cookie
        resp.addCookie(cookie);
    }
}
cookie:一般保存在本地的 用户目录下 appdata中.
一个网站cookie存在上限.
  • 一个cookie只能保存一个信息
  • 一个Web站点可以给浏览器发送多个cookie,最多存放20个cookie
  • 300个cookie浏览器上限
  • cookie大小有限制4kb
删除cookie.
  • 不设置有效期,关闭浏览器,自动失效
  • 设置有效期时间为0
编码解码.

URLEcoder.encode("","utf-8");
URLDecoder.decode("","utf-8");

7.4、Session.

什么是Session

  • 服务器会给每一个浏览器 构建一个 Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在
  • 用户登录之后,整个网站它都可以访问

Session注销.
HttpSession session = req.getSession();
//手动注销session
session.invalidate();

<!-- web.xml 设置Session默认的失效信息-->
<session-config>
    <!--1分钟后Session自动失效-->
    <session-timeout>1</session-timeout>
</session-config>
Session自动过期.
<!--设置Session默认的失效时间-->
<session-config>
    <!--15分钟后Session自动失效,以分钟为单位-->
    <session-timeout>15</session-timeout>
</session-config>
Session与Cookie的区别:.
  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session把用户的数据写到用户独占的Session中,服务端保存(保存重要的信息,减少服务资源的浪费)
  • Session对象由服务器创建
使用场景.
  • 保存一个登陆用户信息;
  • 购物车
  • 经常在整个项目中会使用的数据,我们将它保存在Session中

8. JSP.

8.1、什么是JSP.

java server page : Java服务端页面,和Servlet一样用于开发动态web

最大的特点:

  • 写JSP就像在写HTML
  • 区别:
    • HTML只给用户提供静态的数据
    • JSP页面中可以嵌入JAVA代码,为用户提供动态数据;

8.2 JSP原理.

思路:JSP到底怎么执行的!

  • 代码层面没有任何问题

  • 服务器内部工作

    IDEA中使用Tomcat的会在IDEA的tomcat中生产一个work目录

    • IDEA老版本:C:\Users\用户名\.IntelliJIdeaxxx\system\tomcat\项目名\work
    • IDEA新版本:C:\Users\用户名\AppData\Local\JetBrains\IntelliJIdeaxxx\tomcat\项目名\work

发现页面转变成了Java程序!

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!

JSP最终也会被转换成为一个Java类!

JSP 本质上就是一个Servlet

//初始化
  public void _jspInit() {

  }
//销毁
  public void _jspDestroy() {
  }
//JSPService
  public void _jspService(.HttpServletRequest request,HttpServletResponse response)
  1. 判断请求
  2. 内置一些对象
final javax.servlet.jsp.PageContext pageContext;  //页面上下文
javax.servlet.http.HttpSession session = null;    //session
final javax.servlet.ServletContext application;   //applicationContext
final javax.servlet.ServletConfig config;         //config
javax.servlet.jsp.JspWriter out = null;           //out
final java.lang.Object page = this;               //page:当前
HttpServletRequest request                        //请求
HttpServletResponse response                      //响应
  1. 输出页面前增加的代码
response.setContentType("text/html");       //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
                                          null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
  1. 以上的这些个对象我们可以在JSP页面中直接使用!

在JSP页面中;

只要是 JAVA代码就会原封不动的输出;

如果是HTML代码,就会被转换为:

out.write("<html>\r\n");

这样的格式,输出到前端!

8.3、JSP基础语法.

任何语言都有自己的语法,JAVA中有。 JSP 作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),Java所有语法都支持!

JSP表达式.

  <%--jsp表达式 作用:用来将程序的输出,输出到客户端 <%="变量或者表达式%">
  --%>
  <%= new java.util.date()%>

jsp脚本片段.


  <%--jsp脚本片段--%>
  <% int sum="0;" for (int i="1;" <="100" ; i++) { sum+="i;" } out.println("

Sum="+sum+""); %>

脚本片段的再实现

  <% int x="10;" out.println(x); %>
  

这是一个JSP文档

<% int y="2;" out.println(y); %>
<%--在代码嵌入html元素--%> <% for (int i="0;" < 5; i++) { %>

Hello,World <%=i%> .

<% } %>

JSP声明.

  <%! static { system.out.println("loading servlet!"); } private int globalvar="0;" public void kuang(){ system.out.println("进入了方法kuang!"); %>

JSP声明:会被编译到JSP生成Java的类中!其他的,就会被生成到_jspService方法中!

在JSP,嵌入Java代码即可!

<%%>
<%=%>
<%!%>

<%--注释--%>

JSP的注释,不会在客户端显示,HTML就会!

8.4、JSP指令.

<%@page args.... %>
<%@include file %>

<%--@include会将两个页面合二为一--%>

<%@include file="common/header.jsp" %>

网页主体.

<%@include file="common/footer.jsp" %>
<%--jsp标签 jsp:include:拼接页面,本质还是三个 --%>

网页主体.

@page isPageError=”true|false” 指定页面是否是错误页面

@page PageError=”../ddd” 错误页面

错误页面

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

</web-app>

or

<%@ page errorPage="./500.jsp" %>

8.5、9大内置对象.

  • PageContext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application 【SerlvetContext】 存东西
  • config 【SerlvetConfig】
  • out
  • page ,不用了解
  • exception
pageContext.setAttribute("name1","秦疆1号"); //保存的数据只在一个页面中有效
request.setAttribute("name2","秦疆2号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","秦疆3号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","秦疆4号");  //保存的数据只在服务器中有效,从打开服务器到关闭服务器

request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!

session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;

application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;

8.6、JSP标签、JSTL标签、EL表达式.

<!-- JSTL表达式的依赖 -->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<!-- standard标签库 -->
<dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
</dependency>

EL表达式: ${ }

  • 获取数据
  • 执行运算
  • 获取web开发的常用对象

JSP标签

<%--jsp:include--%>

<%-- http: localhost:8080 jsptag.jsp?name="kuangshen&age=12" --%>


    
    

JSTL表达式

JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可以供我们使用,标签的功能和Java代码一样!

格式化标签

SQL标签

XML 标签

核心标签 (掌握部分)

JSTL标签库使用步骤

  • 引入对应的 taglib
  • 使用其中的方法
  • 在Tomcat 也需要引入 jstl的包,否则会报错:JSTL解析错误

c:if


    Title





if测试.


<%-- el表达式获取表单中的数据 ${param.参数名} --%>
<%--判断如果提交的用户名是管理员,则登录成功--%> <%--自闭合标签--%>

c:choose c:when



<%--定义一个变量score,值为85--%>



    
        你的成绩为优秀
    
    
        你的成绩为一般
    
    
        你的成绩为良好
    
    
        你的成绩为不及格
    


c:forEach

<% arraylist people = new ArrayList<>();
    people.add(0,"张三");
    people.add(1,"李四");
    people.add(2,"王五");
    people.add(3,"赵六");
    people.add(4,"田六");
    request.setAttribute("list",people);
%>


<%-- var , 每一次遍历出来的变量 items, 要遍历的对象 begin, 哪里开始 end, 到哪里 step, 步长 --%>

     


9、JavaBean.

实体类

JavaBean有特定的写法:

  • 必须要有一个无参构造
  • 属性必须私有化
  • 必须有对应的get/set方法;

一般用来和数据库的字段做映射 ORM;

ORM :对象关系映射

  • 表—>类
  • 字段–>属性
  • 行记录—->对象

people表

id name age address
1 秦疆1号 3 西安
2 秦疆2号 18 西安
3 秦疆3号 100 西安
class People{
    private int id;
    private String name;
    private int id;
    private String address;
}

class A{
    new People(1,"秦疆1号",3"西安");
    new People(2,"秦疆2号",3"西安");
    new People(3,"秦疆3号",3"西安");
}

10、MVC三层架构.

什么是MVC: Model view Controller 模型、视图、控制器

10.1、早些年.

用户直接访问控制层,控制层就可以直接操作数据库;

servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护  
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码

架构:没有什么是加一层解决不了的!
程序猿调用
|
JDBC
|
Mysql Oracle SqlServer ....

10.2、MVC三层架构.

Model

  • 业务处理 :业务逻辑(Service)
  • 数据持久层:CRUD (Dao)

View

  • 展示数据
  • 提供链接发起Servlet请求 (a,form,img…)

Controller (Servlet)

  • 接收用户的请求 :(req:请求参数、Session信息….)

  • 交给业务层处理对应的代码

  • 控制视图的跳转

    登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)---->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确-->数据库

11、Filter (重点).

Filter:过滤器 ,用来过滤网站的数据;

  • 处理中文乱码
  • 登录验证….

Filter开发步骤:

  1. 导包

  2. 编写过滤器

    1. 导包不要错

      javax.servlet

      实现Filter接口,重写对应的方法即可

      public class CharacterEncodingFilter implements Filter {
      
          //初始化:web服务器启动,就以及初始化了,随时等待过滤对象出现!
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.println("CharacterEncodingFilter初始化");
          }
      
          //Chain : 链
          /*
          1. 过滤中的所有代码,在过滤特定请求的时候都会执行
          2. 必须要让过滤器继续同行
              chain.doFilter(request,response);
           */
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              request.setCharacterEncoding("utf-8");
              response.setCharacterEncoding("utf-8");
              response.setContentType("text/html;charset=UTF-8");
      
              System.out.println("CharacterEncodingFilter执行前....");
              chain.doFilter(request,response); //让我们的请求继续走,如果不写,程序到这里就被拦截停止!
              System.out.println("CharacterEncodingFilter执行后....");
          }
      
          //销毁:web服务器关闭的时候,过滤会销毁
          public void destroy() {
              System.out.println("CharacterEncodingFilter销毁");
          }
      }
      
  3. 在web.xml中配置 Filter

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <!--只要是 /servlet的任何请求,会经过这个过滤器-->
        <url-pattern>/servlet/*</url-pattern>
        <!--<url-pattern>/*</url-pattern>-->
    </filter-mapping>

12、监听器.

实现一个监听器的接口;(有N种)

  1. 编写一个监听器

    实现监听器的接口…

    //统计网站在线人数 : 统计session
    public class OnlineCountListener implements HttpSessionListener {
    
        //创建session监听: 看你的一举一动
        //一旦创建Session就会触发一次这个事件!
        public void sessionCreated(HttpSessionEvent se) {
            ServletContext ctx = se.getSession().getServletContext();
    
            System.out.println(se.getSession().getId());
    
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    
            if (onlineCount==null){
                onlineCount = new Integer(1);
            }else {
                int count = onlineCount.intValue();
                onlineCount = new Integer(count+1);
            }
    
            ctx.setAttribute("OnlineCount",onlineCount);
    
        }
    
        //销毁session监听
        //一旦销毁Session就会触发一次这个事件!
        public void sessionDestroyed(HttpSessionEvent se) {
            ServletContext ctx = se.getSession().getServletContext();
    
            Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
    
            if (onlineCount==null){
                onlineCount = new Integer(0);
            }else {
                int count = onlineCount.intValue();
                onlineCount = new Integer(count-1);
            }
    
            ctx.setAttribute("OnlineCount",onlineCount);
    
        }
    
    
   /*
   Session销毁:
   1. 手动销毁  getSession().invalidate();
   2. 自动销毁
    */

}


2. web.xml中注册监听器

   ```xml
   <!--注册监听器-->
   <listener>
       <listener-class>com.kuang.listener.OnlineCountListener</listener-class>
   </listener>
  1. 看情况是否使用!

13、过滤器、监听器常见应用.

监听器:GUI编程中经常使用;

public class TestPanel {
    public static void main(String[] args) {
        Frame frame = new Frame("中秋节快乐");  //新建一个窗体
        Panel panel = new Panel(null); //面板
        frame.setLayout(null); //设置窗体的布局

        frame.setBounds(300,300,500,500);
        frame.setBackground(new Color(0,0,255)); //设置背景颜色

        panel.setBounds(50,50,300,300);
        panel.setBackground(new Color(0,255,0)); //设置背景颜色

        frame.add(panel);

        frame.setVisible(true);

        //监听事件,监听关闭事件
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);
            }
        });
    }
}

用户登录之后才能进入主页!用户注销后就不能进入主页了!

  1. 用户登录之后,向Sesison中放入用户的数据

  2. 进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;
    
    if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
        response.sendRedirect("/error.jsp");
    }
    
    chain.doFilter(request,response);

14、JDBC.

什么是JDBC : Java连接数据库!

需要jar包的支持:

  • java.sql
  • javax.sql
  • mysql-conneter-java… 连接驱动(必须要导入)

实验环境搭建


CREATE TABLE users(
    id INT PRIMARY KEY,
    `name` VARCHAR(40),
    `password` VARCHAR(40),
    email VARCHAR(60),
    birthday DATE
);

INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');


SELECT    * FROM users;

导入数据库依赖

<!--mysql的驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

JDBC 固定步骤:

  1. 加载驱动
  2. 连接数据库,代表数据库
  3. 向数据库发送SQL的对象Statement : CRUD
  4. 编写SQL (根据业务,不同的SQL)
  5. 执行SQL
  6. 关闭连接
public class TestJdbc {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.向数据库发送SQL的对象Statement,PreparedStatement : CRUD
        Statement statement = connection.createStatement();

        //4.编写SQL
        String sql = "select * from users";

        //5.执行查询SQL,返回一个 ResultSet  : 结果集
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()){
            System.out.println("id="+rs.getObject("id"));
            System.out.println("name="+rs.getObject("name"));
            System.out.println("password="+rs.getObject("password"));
            System.out.println("email="+rs.getObject("email"));
            System.out.println("birthday="+rs.getObject("birthday"));
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        rs.close();
        statement.close();
        connection.close();
    }
}

预编译SQL

public class TestJDBC2 {
    public static void main(String[] args) throws Exception {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.连接数据库,代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        //3.编写SQL
        String sql = "insert into  users(id, name, password, email, birthday) values (?,?,?,?,?);";

        //4.预编译
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        preparedStatement.setInt(1,2);//给第一个占位符? 的值赋值为1;
        preparedStatement.setString(2,"狂神说Java");//给第二个占位符? 的值赋值为狂神说Java;
        preparedStatement.setString(3,"123456");//给第三个占位符? 的值赋值为123456;
        preparedStatement.setString(4,"24736743@qq.com");//给第四个占位符? 的值赋值为1;
        preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符? 的值赋值为new Date(new java.util.Date().getTime());

        //5.执行SQL
        int i = preparedStatement.executeUpdate();

        if (i>0){
            System.out.println("插入成功@");
        }

        //6.关闭连接,释放资源(一定要做) 先开后关
        preparedStatement.close();
        connection.close();
    }
}

事务

要么都成功,要么都失败!

ACID原则:保证数据的安全。

开启事务
事务提交  commit()
事务回滚  rollback()
关闭事务

转账:
A:1000
B:1000

A(900)   --100-->   B(1100) 

Junit单元测试

依赖

<!--单元测试-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

简单使用

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!

@Test
public void test(){
    System.out.println("Hello");
}

搭建一个环境

CREATE TABLE account(
   id INT PRIMARY KEY AUTO_INCREMENT,
   `name` VARCHAR(40),
   money FLOAT
);

INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);
    @Test
    public void test() {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";

        Connection connection = null;

        //1.加载驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2.连接数据库,代表数据库
             connection = DriverManager.getConnection(url, username, password);

            //3.通知数据库开启事务,false 开启
            connection.setAutoCommit(false);

            String sql = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();

            //制造错误
            //int i = 1/0;

            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();

            connection.commit();//以上两条SQL都执行成功了,就提交事务!
            System.out.println("success");
        } catch (Exception e) {
            try {
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

补充.

热部署.

https://blog.csdn.net/Troub_cy/article/details/90052283

如果子项目无法引用父项目.

查看父项目 pom.xml文件中 Modules中是否有子模块

查看子项目pom.xml文件中 Parent 里面有没有 GAV(组名,父项目名,版本)

控制台乱码问题.

把tomcat 目录下的 conf/logging.properties 中更改 字符编码为GBK

响应的状态码.

去看 前面 笔记 Servlet – HttpSerletResponse – 简单分类 – 响应的状态码

request.getRemoteAddr() 获取的值为0:0:0:0:0:0:0:1的原因及解决办法.

来自 https://www.cnblogs.com/bingya/articles/3135721.html

最近在进行web开发时,在jsp页面获取服务器ip时,遇到了request.getRemoteAddr()获取的值为0:0:0:0:0:0:0:1,这是为什么呢,照道理讲,应该是127.0.0.1才对,为什么这个获取的值变成了ipv6了呢,而且我发现这种情况只有在服务器和客户端都在同一台电脑上才会出现(例如用localhost访问的时候才会出现),后来上网查了查原因,原来是/etc/hosts这个东西作怪(在windows上应该是C:\Windows\System32\drivers\etc\hosts这个文件),只需要注释掉文件中的 # ::1 localhost 这一行即可解决问题。另外localhost这个文件很有用,这里你可以添加自己的条目,例如添加 192.168.0.212 myweb 这样子,在浏览器中原来只能使用192.168.0.212来访问的,并可以使用myweb来进行替换。

如果还不能解决,本机访问的时候用127.0.0.1或本机ip代替localhost即可解决

GET请求乱码解决.

reqiset.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");

https://www.cnblogs.com/zhuxiang1633/p/9707083.html

新建了子模块需要做什么(不是完整步骤,起提示作用).

1.把src文件补全

2.把pom.xml 和 web.xml 进行优化

3.在加入模块

4.生成Artifacts

5.tomcat配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>JavaWebTest</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>servlet01</module>
        <module>javaWeb</module>
    </modules>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>
</project>

如果你导入了jstl和standard的依懒,也添加了标签库声明,但是仍然报错.

那么可以把jar复制到tomcat的lib文件加下


文章作者: liuminkai
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 liuminkai !
评论
 上一篇
我的自定义IDEA快捷键-部分 我的自定义IDEA快捷键-部分
我的自定义IDEA快捷键. 我的快捷键 描述 Alt + ↑ 当前行向上移动 Alt + ↓ 当前行向下移动 Alt + ← 上一次编辑位置 Alt + → 下一次编辑位置 Alt + Shift + ↑ 光标位置
2020-06-14
下一篇 
关于更改my.ini client字符集仍然是GBK的问题-已解决 关于更改my.ini client字符集仍然是GBK的问题-已解决
关于更改my.ini client字符集,mysql cmd仍然是GBK的问题(windows)-已解决.状况说明.在练习JDBC操作数据库的时候,存入中文数据都成了 ’ ?‘ 这是由于数据库字符集不是utf8导致的(java工程utf8)
2020-06-11
  目录