Java Web从入门到实践

Java Web从入门到实践

1. 基本概念

1.1 前言

web开发:

  • web 网页
  • 静态web html、css 提供给所有人看的数据,始终不会发生变化
  • 动态web 提供给所有人看的数据,会发生变化 每个人在不同时间 不同地点看到的信息不同 技术栈:Servlet/JSP/ ASP

在Java中,动态web资源开发技术统称为Java Web

1.2 web应用程序

可以提供浏览器访问的程序

  • a.html、b.html…多个web资源,这些web资源可以被外界访问,对外界提供服务
  • URL
  • 这些所有的web资源都会被放在同一个文件夹下,web应用程序->Tomcat服务器
  • 一个web应用由多部分组成
    • html、css、js
    • jsp、servlet
    • java程序
    • jar包
    • 配置文件

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

1.3 静态web

  • *.html 如果服务器上存在这些东西,就可以直接读取
  • 存在缺点:1.web页面无法动态更新,所有用户看到的都是同一个页面 2.无法和数据库交互
    在这里插入图片描述

1.4 动态web

页面会动态展示
在这里插入图片描述

缺点:假如服务器动态资源出现错误,就需要重新编写后台程序
优点:1.可以动态更新,所有用户看到的都不是同一个页面 2.可以于数据库交互(数据持久化)

2. web服务器

ASP:微软 在html中嵌入了VB的脚本
JSP/Servlet:SUN公司主推的B/S架构,基于JAVA语言的 可以承载三高问题
PHP:开发速度快,功能强大,跨平台,代码简单 但是无法承载大访问量

服务器是一种被动操作,用来处理用户的一些请求和给用户一些响应信息
IIS:微软的 ASP程序 windows自带
Tomcat:运行JSP和Servlet

3. Tomcat

3.1 安装Tomcat

1.访问官网

https://tomcat.apache.org/index.html

2.选择相应版本
在这里插入图片描述

3.下载压缩包 解压

3.2 Tomcat启动

文件夹内容:
在这里插入图片描述

启动Tomcat
打开startup.bat文件,可以访问http://localhost:8080/
打开shutdown.bat文件,关闭

3.3 Tomcat配置

核心配置文件:
在这里插入图片描述

可以配置启动的主机:默认主机为localhost->127.0.0.1 默认存放网站的位置为webapps

 <Host name="localhost"  appBase="webapps"
                  unpackWARs="true" autoDeploy="true">

配置启动的端口号:默认为8080

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

高难度面试题
请你谈谈网站是如何进行访问的?
1.输入一个域名,点击回车
2.检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名的映射
3.如果有,直接返回对应的IP地址 没有的话去DNS(管理全部的域名)服务器上找

3.5 发布一个web网站

将自己的网站放到服务器(Tomcat)指定的web应用的文件夹(webapps)下
使用http://localhost:8080/manager就可以访问具体的
在这里插入图片描述

4. Http

4.1什么是Http

超文本传输协议是一个简单的请求和相应协议,通常运行在TCP上。
超文本:图片、音乐、视频…
端口:80
Https:端口:443 安全的

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/?tn=48021271_8_hao_pg //请求地址
Request Method:GET  //请求方法 get/post
Status Code:200 OK   // 状态码 200
Remote Address:182.61.200.7:443 //远程地址
Accept:text/html
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9
Cache-Control:max-age=0
Connection:keep-alive

请求行

  • 请求行中的请求方式:GET
  • 请求方式:GET、POST、HEAD、DELETE、PUT…
    • get:请求携带的参数较少,大小会限制,会在URL中显示内容,不安全但高效
    • post:请求携带的参数无限制,不会在URL中显示内容,安全但不高效

消息头

Accept:告诉浏览器支持的数据类型
Accept-Encoding:支持那种编码格式 GBK UTF-8  GB2312
Accept-Language:告诉浏览器 它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成时是断开还是连接

4.4 Http响应

服务器->响应->客户端
以百度响应为例:

Cache-Control:private   //缓存控制
Connection:keep-alive  //连接  
Content-Encoding:gzip //编码
Content-Type:text/html;charset=utf-8 //类型

响应体

Accept:告诉浏览器支持的数据类型
Accept-Encoding:支持那种编码格式 GBK UTF-8  GB2312
Accept-Language:告诉浏览器 它的语言环境
Cache-Control:缓存控制
Connection:告诉浏览器,请求完成时是断开还是连接

响应状态码
200:响应成功 200
3××:重定向
4××:资源不存在 404
5××:服务器代码错误 500 502(网关错误)

5. Maven

在JavaWeb开发中,需要使用大量的jar包,需要手动导入

5.1 Maven项目架构管理工具

用来方便导入jar包
核心思想:约定>配置
Maven会规定如何编写Java代码

5.2 下载安装Maven

官网:>https://maven.apache.org/
在这里插入图片描述

下载完后解压

5.3 配置环境变量

配置如下:

  • 1.在环境变量中添加 M2_HOME 变量值为maven目录下的bin目录

  • 2.在环境变量中添加 MAVEN_HOME 变量值为maven的主目录
    在这里插入图片描述

  • 3.在path中添加 %MAVEN_HOME%\bin
    在这里插入图片描述

  • 4.测试 在cmd中 mvn -version
    在这里插入图片描述

5.4 阿里云镜像

  • 镜像(mirrors):加速下载
<mirror>    
    <id>alimaven</id>    
    <mirrorOf>*</mirrorOf>    
    <name>aliyun maven</name>    
    <url>https://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>

在这里插入图片描述

5.5 本地仓库

在这里插入图片描述

5.6 IEDA使用Maven

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.7 普通Maven项目

在这里插入图片描述

这个是干净的
在这里插入图片描述

这个只有web应用才有
在这里插入图片描述

5.8 标记文件夹

在这里插入图片描述

在这里插入图片描述

5.9 在IDEA中配置Tomcat

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

解决警告问题 为什么会有该问题? 我们访问一个网站需要指定一个文件夹名字
在这里插入图片描述

在这里插入图片描述

5.10 pom文件

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

<?xml version="1.0" encoding="UTF-8"?>
<!--Maven版本和头文件-->
<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>

  <!-- 配置的GAV-->
  <groupId>org.example</groupId>
  <artifactId>Maven</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>
    <!-- Package:项目的打包方式
    jar:java应用
    war:JavaWeb应用
    -->

  <name>Maven Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

<!--  配置-->
  <properties>
    <!--项目的默认构建编码-->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!--编码版本-->
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <!--项目依赖-->
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
 <!--项目构建用的东西-->
  <build>
    <finalName>Maven</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

maven由于他的约定大于配置,有时会遇到自己写的配置文件无法导出或者生效的问题,解决方案:

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

6. Servlet

6.1 Servlet简介

Servlet是Sun公司开发动态web的一门技术
Sun在这些API提供一个接口:Servlet,如果开发一个Servlet程序,只需完成以下两步:

  • 编写一个类,实现Servlet接口
  • 把开发好的java类部署到web服务器中

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

6.2 HelloServlet

  1. 构建一个maven的普通项目,删除src,之后建立模块,这个空的工程就是Maven主工程
  2. 关于Maven父子工程的理解:
    在父项目中增加一个
<modules>    
    <module>Servlet-01</module>
</modules>

父项目的jar包子项目可以使用 继承关系
3. Maven环境优化
将子模块的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"
         metadata-complete="true">
</web-app>
  1. 编写一个Servlet程序
  • 编写一个普通类
  • 实现Servlet接口,Sun公司将Servlet有两个实现类(Servlet->GenericServlet->Http) 这里继承HttpServlet
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 HelloServlet extends HttpServlet {
    // 由于get/post只是请求实现的方式不同,可以相互调用,业务逻辑一样
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();//响应流
        writer.println("hello,Servlet");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
    }
}
  1. 编写Servlet的映射

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

在web.xml中编写

 	<!-- 注册Servlet-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  1. 配置Tomcat
    注:配置项目发布的路径

  2. 测试

http://localhost:8080/s1/hello

6.3 Servlet原理

Servlet由web服务器,web服务器收到浏览器请求之后,
在这里插入图片描述

6.4 Mapping问题

  1. 一个Servlet可以指定一个映射路径
	<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  1. 一个Servlet可以指定多个映射路径
	<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello3</url-pattern>
    </servlet-mapping>
  1. 一个Servlet可以指定通用映射路径
	<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
  1. 默认请求路径 跳过主页,直接访问该路径
	<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
  1. 自定义后缀 使用http://localhost:8080/index/12246546.abc 访问
	<servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.abc</url-pattern>
    </servlet-mapping>
  1. 优先级问题
    指定了固定的映射路径优先级最高,如果找不到就会走默认的处理请求
    http://localhost:8080/index/hello 输入后会进入hello页面而不是404页面
 <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>error</servlet-name>
        <servlet-class>ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>error</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

6.5 ServletContext

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

  • 1.共享数据
    在这里插入图片描述

放数据

 ServletContext context = this.getServletContext();
 String username = "张三";
 context.setAttribute("username",username);

取数据

 ServletContext context = this.getServletContext();
 String username = (String)context.getAttribute("username");
 resp.setContentType("text/html");
 resp.setCharacterEncoding("utf-8");
 resp.getWriter().print("你好:"+username);
  • 2.获取初始化参数
    在web.xml中设置初始化参数
<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql:localhost:3305/MyBatis</param-value>
</context-param>

获取

ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
  • 3.实现请求转发 路径没变
  ServletContext context = this.getServletContext();
  RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gc"); //转发的请求路径
  requestDispatcher.forward(req,resp);  //调用forward实现请求转发
  • 4.读取properties文件
    Properties
  • 在java目录下新建properties
  • 在resources目录下新建properties

发现都被打包到了同一个路径下:classes,通常称为类路径(classpath)

db.properties

username=root
password=root

获取代码

InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(is);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
resp.getWriter().print(username+":"+password);

在这里插入图片描述

6.6 HttpServletResponse

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

负责向浏览器发送数据的方法:

ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;

负责向浏览器发送响应头的方法:

void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);

常见应用:
1.向浏览器输出消息
2.下载文件

  • 下载路径
  • 文件名
  • 设置浏览器支持下载我们需要的东西
  • 获取下载文件的输入流
  • 创建缓冲区
  • 获取OutputStream
  • 将FileOutputStream流写入buffer缓冲区
  • 使用OutputStream将缓冲区中的数据输出到客户端
        String s = "D:\\java代码\\Maven\\ServletDemo\\Response\\src\\main\\resources\\头像.jpg";
        String fileName = s.substring(s.lastIndexOf("\\") + 1);
        resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode
        (fileName,"utf-8"));          
        FileInputStream fis = new FileInputStream(s);
        int len = 0;
        byte[] buffer = new byte[1024];
        ServletOutputStream os = resp.getOutputStream();
        while((len=fis.read(buffer))!=-1){
            os.write(buffer,0,len);
        }
        os.close();
        fis.close();

3.验证码功能

  • 前端实现:
  • 后端实现:java图片类
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //让浏览器三秒刷新一次
        resp.setHeader("refresh","3");
        //在内存中创建一个图片
        BufferedImage image = new BufferedImage(80,20, BufferedImage.TYPE_INT_RGB);
        //得到图片
        Graphics2D g = (Graphics2D)image.getGraphics(); //笔
        //设置图片背景颜色
        g.setColor(Color.WHITE);
        g.fillRect(0,0,80,20);
        //给图片写数据
        g.setColor(Color.GRAY);
        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(image,"jpg",resp.getOutputStream());

    }
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999)+"";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7-num.length(); i++) {
            sb.append("0");
        }
        num = sb+num;
        return num;
    }

4.实现重定向
一个web资源收到客户端请求后,告诉客户端去访问另一个web资源

void sendRedirect(String var1) throws IOException;

resp.sendRedirect("image");

面试题:
重定向与转发的区别:
相同点:页面都会跳转
不同点:重定向会改变url 转发不会

<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login" method="get">
    <span>用户名:</span><input type="text" name="username"><br>
    <span>密码:</span><input type="password" name="password"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //处理请求
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username+":"+password);
        resp.sendRedirect("/index/Success.jsp");
    }

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

6.7 HttpServletRequest

获取前端参数,并请求转发
在这里插入图片描述

        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobbies");
        System.out.println(username);
        System.out.println(password);
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
        req.getRequestDispatcher("/success.jsp").forward(req,resp); //请求转发 不需要加虚拟路径  /r
//        resp.sendRedirect("/r/success.jsp");   //重定向需要写

7. Cookie、Session

7.1 会话

用户打开浏览器,点击了很多链接,访问了多个web资源,关闭浏览器,这个过程称之为会话
1.服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了 cookie
2.服务器登记来过了,下次来的时候匹配

7.2 保存会话的两种技术

cookie:

  • 客户端技术(请求和响应)

session:

  • 服务器技术,利用这个技术可以保存用户的访问信息
    常见场景:登录网站后,之后就可以不用输账号密码 就直接登录了

7.3 Cookie

1.从请求中拿到Cookie信息
2.服务器响应给客户端Cookie

Cookie[] cookies = req.getCookies(); //获得cookie
cookies[i].getName()// 获得cookie的key
cookies[i].getValue()// 获得cookie的value
new Cookie("LastLoginTime",System.currentTimeMillis()+"") //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
cookie.setMaxAge(0); //注销cookie
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        PrintWriter out = resp.getWriter();
        Cookie[] cookies = req.getCookies();
        if(cookies!=null){
            out.write("您最后一次访问的时间为:");
            for (int i = 0; i < cookies.length; i++) {
                if(cookies[i].getName().equals("LastLoginTime")){
                    String value = cookies[i].getValue();
                    long l = Long.parseLong(value);
                    Date date = new Date(l);
                    out.write(date.toLocaleString());
                }
            }
        }
        Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
        resp.addCookie(cookie);

可以解决乱码问题

URLEncoder.encode("张三","utf-8")  //编码
String decode = URLDecoder.decode(name, "utf-8"); //解码

删除cookie

  • 不设置有效期,关闭浏览器(所有页面全部关掉)自动失效
  • 设置有效期时间为0

7.4 Session(重点)

  • 服务器会给每一个用户创建一个Session对象
  • 一个session独占一个浏览器,只要浏览器不关闭,这个session就存在
  • 用户登录之后,整个网站都可访问->保存用户的信息
          req.setCharacterEncoding("utf-8");
          resp.setCharacterEncoding("utf-8");
          resp.setContentType("text/html;charset=utf-8");

          HttpSession session = req.getSession();
          session.setAttribute("name", "李四");
          String sessionId = session.getId();
          if(session.isNew()){
              resp.getWriter().write("该sessionID是新创建的,ID="+sessionId);
          }else{
              resp.getWriter().write("服务器中已存在该sessionID,ID="+sessionId);
          }
          //只要浏览器打开后就会创建Session,关闭浏览器会消失
        // Session在创建的时候发生了什么
        // 1. 创建一个名JSESSIONID 值为SessionID的cookie
        // 2. 将该cookie响应回去
        // Cookie cookie = new Cookie("");
        // resp.addCookie(cookie);

在这里插入图片描述

存储、取出session的值

//session存储对象
HttpSession session = req.getSession();
Student s1 = new Student(101,"张三",12); //session可以存对象
session.setAttribute("student", s1);
//从session中取出对象
HttpSession session = req.getSession();
Student s1 = (Student)session.getAttribute("name");
resp.getWriter().write("您好:"+s1.toString());

注销session
1.关闭服务器
2.手动注销

HttpSession session = req.getSession();
session.removeAttribute("student");
//手动注销session
session.invalidate();

3.自动注销 在web.xml中设置

<!--设置Session的自动失效-->
<session-config>    
    <!--设置session 15分钟后失效-->    
    <session-timeout>15</session-timeout>
</session-config>

Session和Cookie的区别:
1.cookie是创建于服务器端,保存在浏览器端,通过cookie.setMaxAge(2000)来设置存活时间,如果没有设置,浏览器关闭的时候就消亡了,可以被多个同类型的浏览器共享
2.session创建于服务器端,保存在服务器端,但是sessionid作为一个cookie存放在浏览器端,一个session对象为一个用户浏览器服务

8. JSP

8.1 JSP简介

java server pages: java服务器端页面,跟servlet一样,用于开发动态web
jsp就像是html
区别:

  • html只提供静态数据
  • jsp可嵌入java代码,提供动态数据

8.2 JSP原理

浏览器向服务器发送请求,不管访问什么资源,其实还是在访问Servlet
JSP最终也变会转换为一个Java类

C:\Users\yonghuming\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\ff4cf2a1-32e4-4c9a-8d89-ae9d47eeeeac\work\Catalina\localhost\Session_war\org\apache\jsp

在这里插入图片描述

JSP本质就是一个Servlet
index_jsp.java文件中有以下实现
在这里插入图片描述

public void _jspInit() { //初始化
  }
  public void _jspDestroy() { //销毁
  }
  public void _jspService(HttpServletRequest request,HttpServletResponse response) // JSPService
  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>\n");

这样的格式,输出到前端

8.3 JSP基础语法

需要的依赖

<dependencies>
<!--        servlet 依赖-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
<!--        JSP依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
<!--        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>
    </dependencies>

任何语言都有自己的语法,jsp作为java技术的一种应用,拥有一些自己的扩充语法(了解,知道即可

JSP表达式
<%= 变量或者表达式%>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--JSP表达式   
用来将程序的输出,输出到客户端
--%>
<%= new java.util.Date()%>
</body>
</html>

JSP脚本片段
<% java代码 %>

<%
    int sum = 0;
    for (int i = 1; i <=100 ; i++) {
       sum+=i;
    }
    out.print("<h1>sum="+sum+"</h1>");
  %>
<%--  在代码中嵌入html语句--%>
<%
         for (int i = 0; i < 10; i++) {
%>
        <h1>Hello JSP <%= i%></h1>
<%
         }
%>

JSP声明
<%! %>

<%!
    static {
      System.out.println("JSP");
    }
    private int num = 0;
%>

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

<%%>
<%=%>
<%!%>
<%--JSP注释--%>

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

8.4 JSP指令

在这里插入图片描述

page指令
定制错误页面
1.在可能发生错误的jsp头部添加以下语句

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

2.修改web.xml文件,添加以下语句

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

include指令

<%--  @include会将三个页面合成一个--%>
          <%@include file="common/header.jsp"%>
          <h1>这里是主体</h1>
          <%@include file="common/footer.jsp"%>

<%--          jsp标签
          jsp:include会拼接页面,本质还是三个
--%>
          <jsp:include page="common/header.jsp"/>
          <h1>这里是主体</h1>
          <jsp:include page="common/footer.jsp"/>

8.5 内置对象

  • PageContext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application 存东西
  • config
  • out
  • page
<%--内置对象--%>
<%
    pageContext.setAttribute("name1","张三");  //保存的数据只在一个页面中有效
    request.setAttribute("name2","李四");  //保存的数据只在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name3","王五");  //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    application.setAttribute("name4","陈一"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%
    // 一般是对象取值 pageContext用pageContext取,request用request取....
    // 从底层到高层(作用域):page->request->session->application
    String name1 = (String) pageContext.findAttribute("name1");
    String name2 = (String) pageContext.findAttribute("name2");
    String name3 = (String) pageContext.findAttribute("name3");
    String name4 = (String) pageContext.findAttribute("name4");
    String name5 = (String) pageContext.findAttribute("name5");
%>
<%--使用el表达式取值--%>
取得值为:
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>  <%--el表达式自动过滤空值--%>
<h3><%=name5%></h3>   <%--显示为null--%>

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 page=""></jsp:include>
页面转发
<jsp:forward page="/index.jsp"></jsp:forward>

<jsp:forward page="/JSPTag1.jsp">
    <jsp:param name="username" value="zhangsan"/>
    <jsp:param name="password" value="123"/>
</jsp:forward>


另一个页面取
用户名:<%=request.getParameter("username")%>
密码:<%=request.getParameter("password")%>

JSTL表达式
JSTL标签库就是为了弥补HTML标签的不足,自定义了许多标签,标签功能与java代码一样
核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:

<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>

在这里插入图片描述

JSTL标签库使用步骤:
1.引用对应的taglib
2.使用其中的方法
3.在Tomcat中也需要引入jstl和standard的包,否则会报错

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="JSTL.jsp" >
<%--
    EL表达式获取表单中的数据
    ${param.参数名}
--%>
    用户名:<input type="text" name="username" value="${param.username}">
    <input type="submit" value="提交">
</form>
<c:if test="${param.username=='admin'}" var="isAdmin">
    <c:out value="管理员欢迎您"></c:out>
</c:if>
<c:out value="${isAdmin}"></c:out>   <!--isadmin的值为true或者false-->
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<c:set var="score" value="60"></c:set>
<c:choose>
    <c:when test="${score>=90}">
        你的成绩为优秀
    </c:when>
    <c:when test="${score>=80}">
        你的成绩为良好
    </c:when>
    <c:when test="${score>=70}">
        你的成绩为中等
    </c:when>
    <c:when test="${score>=60}">
        你的成绩为及格
    </c:when>
</c:choose>
</body>
</html>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("张三");
    arrayList.add("李四");
    arrayList.add("王五");
    arrayList.add("赵六");
    arrayList.add("田七");
    request.setAttribute("people",arrayList);
%>

<c:forEach var="name" items="${people}">
    <c:out value="${name}"></c:out><br/>
</c:forEach>
<hr>
<c:forEach  var="name" items="${people}" begin="1" end="3" step="1">
    <c:out value="${name}"></c:out><br/>
</c:forEach>
</body>
</html>

在这里插入图片描述

9. JavaBean

实体类
特定的写法:

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

一般与数据库的字段做映射 ORM
ORM 对象关系映射 表->类 字段->属性 行记录->对象

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.hua.pojo.People" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<jsp:useBean id="people" class="com.hua.pojo.People" scope="page"></jsp:useBean>
<jsp:setProperty name="people" property="id" value="101"></jsp:setProperty>
<jsp:setProperty name="people" property="name" value="张三"></jsp:setProperty>
<jsp:setProperty name="people" property="age" value="18"></jsp:setProperty>
<jsp:setProperty name="people" property="address" value="济南"></jsp:setProperty>

ID:<jsp:getProperty name="people" property="id"/><br/>
姓名:<jsp:getProperty name="people" property="name"/><br/>
年龄:<jsp:getProperty name="people" property="age"/><br/>
地址:<jsp:getProperty name="people" property="address"/><br/>
</body>
</html>

10. MVC三层架构

Model View Controller 模型、视图、控制器

10.1 早期

在这里插入图片描述

用户直接访问控制层,控制层可以直接操作数据库
Servlet——>CRUD——>数据库
弊端:程序十分臃肿,不利于维护
Servlet代码:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码…
架构:没有什么是加一层解决不了

10.2 MVC三层架构

在这里插入图片描述

Model

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

View

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

Controller(Servlet)

  • 接受用户请求:(req请求参数、Session信息)
  • 交给业务层处理对应的代码
  • 控制试图的跳转

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

11. Filter过滤器(重点)

用来过滤网站的数据
在这里插入图片描述

步骤:
1.导包

 <dependencies>
        <!--        servlet 依赖-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.3</version>
            <scope>provided</scope>
        </dependency>
        <!--        JSP依赖-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <!--        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>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
    </dependencies>

2.实现接口Filter 注意是javax.servlet 下的 重写三个方法

package FilterDemo;

import javax.servlet.*;
import java.io.IOException;

public class FilterTest implements Filter {
    //初始化:web服务器启动,就已经初始化了
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }
    //chain:
    //1. 过滤器的所有代码,在过滤特定请求(需要在web.xml配置)的时候会执行
    //2. 必须让过滤器通行
    @Override
    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");
                // 让请求继续,可能会有多个过滤器 ,如果不写,程序到此会被拦截
                chain.doFilter(request,response);
    }
    //销毁:web服务器关闭的时候,过滤会被销毁
    @Override
    public void destroy() {
        System.out.println("CharacterEncodingFilter已销毁");
    }
}

3.在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"
         metadata-complete="true">

    <servlet>
        <servlet-name>testDemo</servlet-name>
        <servlet-class>test</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>testDemo</servlet-name>
        <url-pattern>/Servlet/show</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>testDemo1</servlet-name>
        <servlet-class>test</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>testDemo1</servlet-name>
        <url-pattern>/show</url-pattern>
    </servlet-mapping>


    <filter>
        <filter-name>Filter</filter-name>
        <filter-class>FilterDemo.FilterTest</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Filter</filter-name>
        <url-pattern>/Servlet/*</url-pattern>
    </filter-mapping>
</web-app>

例子:实现登录拦截 用户登录之后才能进入主页,用户注销之后就不能进入主页
Login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username"><br/>
    <br/>
    密码:<input type="password" name="password"><br/>
    <br/>
    <input type="submit" value="提交">
</form>
</body>
</html>

sys文件夹下的Success.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
欢迎您:
<%= request.getSession().getAttribute("user_session")%>
<a href="/loginOut" style="text-decoration: none">注销</a>
</body>
</html>

LoginServlet

package Servlet;

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

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //获取前端请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username.equals("admin")){
            HttpSession session = req.getSession();
            session.setAttribute("user_session",session.getId());
            resp.sendRedirect("/sys/Success.jsp");
        }else{
            resp.sendRedirect("/Error.jsp");
        }
    }

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

LoginOutServlet

package Servlet;

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

public class LoginOutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        Object user_session = session.getAttribute("user_session");
        if(user_session!=null){
            session.removeAttribute("user_session");
            resp.sendRedirect("/Login.jsp");
        }else{
            resp.sendRedirect("/Login.jsp");
        }
    }

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

LoginFilter

package FilterDemo;

import com.sun.deploy.net.HttpRequest;
import com.sun.deploy.net.HttpResponse;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        HttpSession session = request.getSession();
        Object user_session = session.getAttribute("user_session");
        if(user_session==null){
            response.sendRedirect("/Login.jsp");
        }
        chain.doFilter(req,resp);
    }

    @Override
    public void destroy() {

    }
}

12. 监听器

1.实现一个监听器的接口

package listener;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class OnLineListener implements HttpSessionListener {
    //创建session监听  一旦创建一个session就会触发这个事件
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext sc = se.getSession().getServletContext();
        Integer olineCount = (Integer) sc.getAttribute("count");
        if(olineCount==null){
             olineCount =new Integer(1);
        }else{
            olineCount =new Integer(olineCount+1);
        }
        sc.setAttribute("count",olineCount);
    }

    // 销毁session监听,一旦销毁session就会触发一次这个事件
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext sc = se.getSession().getServletContext();
        Integer olineCount = (Integer) sc.getAttribute("count");
        if(olineCount==null){
            olineCount =new Integer(0);
        }else{
            olineCount =new Integer(olineCount-1);
        }
        sc.setAttribute("count",olineCount);
    }
}

2.在web.xml中配置监听器

<listener>    
    <listener-class>listener.OnLineListener</listener-class>
</listener>
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java入门到精通需要学习的内容很多,包括Java基础知识,数据结构,算法,Java集合框架,Java8新特性,操作系统,网络原理,Java多线程及并发编程,Java的IO模型及网络编程,JVM,Mysql,JavaWeb等等。建议按照以下步骤学习Java: 1. 从Java基础知识开始学习,包括语法、变量、运算符、控制流等等。可以通过教材、在线教程或者视频课程学习。 2. 掌握数据结构和算法,这是编程的基础。了解常见的数据结构如数组、链表、栈、队列、树等,以及常见的算法如排序、查找、递归等。 3. 学习Java集合框架,包括List、Set、Map等常用的数据结构。了解它们的特点、用法和性能。 4. 深入学习Java的高级特性,如Java8新特性、Lambda表达式、函数式编程等。这些特性可以提高代码的简洁性和可读性。 5. 学习操作系统和网络原理,了解计算机系统的运行原理和网络通信的基本知识。 6. 掌握Java多线程和并发编程,这是开发高性能应用的基础。 7. 学习Java的IO模型和网络编程,掌握如何进行文件读写和网络通信。 8. 深入了解JVM,包括内存管理、垃圾回收等。这对于优化性能和解决内存泄漏问题非常重要。 9. 学习数据库Mysql,了解数据库的基本概念、SQL语言和常见的数据库操作。 10. 学习JavaWeb开发,包括Servlet、JSP、MVC框架等。掌握常见的Web开发技术和框架。 11. 可以通过阅读书籍、参加培训班、实践项目等方式加深对Java的理解和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值