javaweb

基本概念

在java中,动态资源开发的技术称为javaweb

web开发

  • web是网页的意思
  • 静态web
    • html css
    • 提供给所有人看的数据一样
  • 动态web
    • 淘宝,几乎所有的网站
    • 提供所有人看的数据始终会发生变化,每个人在不同时间,不同地点看的信息各不相同
    • 技术栈:Servlet/JSP ASP PHP

web应用程序

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

  • a.html b.html ....多个web资源,这些web资源可以被外界访问,对外界提供服务
  • URL
  • 一个web应用由多部分组成(静态web,动态web)
    • html css
    • jsp servlet
    • java程序
    • jar包
    • 配置文件(properties)
  • web应用程序编写完毕,若想提供给外界访问,需要一个服务器来统一管理

Tomcat

安装

安装tomcat,之前需要先安装一下jdk,用java -version检查

官网目前已经更新到tomcat10了,但是tomcat10和idea一起使用还是存在问题,所以推荐使用tomcat9

image-20200801215346895

下载压缩包之后,直接解压

启动

如果你直接点击bin目录下的startup.bat,可能会出现界面一闪而过,如果没有一闪而过就可以跳过下面的办法了

你需要在控制台中输入

image-20200801220158691

之后在网页上输入localhost:8080,就会显示

但是,运行结果可能会出现乱码

image-20200801220709545

修改conf目录下的logging.properties文件

将文件中原有的配置修改

#原有
java.util.logging.ConsoleHandler.encoding = UTF-8
#修改成GBK,因为windows默认是gbk
java.util.logging.ConsoleHandler.encoding = GBK

访问测试:localhost:8080

乱码的本质:读取二进制的时候采用的编码和最初将字符转换成二进制时的编码不一致

将"我们是中国人"以UTF-8编码转换成byte数组(byte数组其实就相当于二进制序列了,此过程即编码),再以GBK编码和byte数组创建新的字符串(此过程即以GBK编码去解码byte数组,得到字符串),就产生乱码了

文件夹对应作用

image-20200815183735144

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

HTTP

什么是HTTP

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

  • 文本:html,字符串

  • 超文本:图片,音乐,视频,地图,定位...

  • 80端口

Https:安全的

  • 443端口

HTTP请求

  • 客户端——发请求(Request)——服务器

百度的例子

Request URL: https://www.baidu.com/?tn=78040160_14_pg&ch=8 请求地址
Request Method: GET	get/post
Status Code: 200 OK	状态码:200
Remote Address: 163.177.151.110:443 远程地址
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
  • 请求行
    • 请求方式:GET,POST
      • get:请求能携带的参数比较少,大小有限制,不安全但高效
      • post:请求能携带的参数没有限制,大小没有限制,安全但不高效
  • 请求头
Accept:  告诉浏览器,它支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK,UTF-8,GB312 ..
Accept-Language: 告诉浏览器,他的语言环境
Cache-Control: no-cache	缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST:主机

HTTP响应

  • 服务器——响应——客户端

百度的例子

Cache-Control: private 缓存控制
Connection: keep-alive	连接
Content-Type: text/html;charset=utf-8
  • 响应体
Accept:  告诉浏览器,它支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK,UTF-8,GB312 ..
Accept-Language: 告诉浏览器,他的语言环境
Cache-Control: no-cache	缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST:主机
Refrush:告诉客户端,多久刷新一次
Location让网页重新定位
  • 响应状态码
响应状态码 描述
200 请求成功
3** 请求重定向
4** 找不到
5** 服务器错误
502 网关错误

面试题

当你的浏览器中输入地址并回车的一瞬间到页面能够展示回来,经历了什么

链接

Maven

为什么学习Maven?

在javaWeb开发中,需要大量的jar包,我们需要导入。Maven就是为了方便导入jar包

安装Maven

官网

image-20200811074029645

下载完成后解压

配置环境变量

在我们系统环境变量

配置如下环境变量

名称 具体含义
M2_HOME maven目录下的bin目录
MAVEN_HOME maven目录
在系统变量PATH中配置MAVEN_HOME %MAVEM_HOME%\bin

测试Maven 是否安装成功mvn -version

image-20200811074634340

修改setting.xml

路径:D:\Environment\maven\apache-maven-3.5.4\conf\settings.xml

在setting.xml中配置镜像(为了下载依赖的速度变快)和本地仓库(设置依赖的下载位置)

阿里云镜像

 <mirror>
	<id>nexus-aliyun</id>
	<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
	<name>Nexus aliyun</name>
	<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>

本地仓库

配置好之后,在本地需要新建一个文件夹soft(文件夹名可以自己设定。比如repo,repository)

<!-- 本地仓库位置 -->
<localRepository>D:/Environment/maven/soft</localRepository>

在Maven中创建一个带模板项目

在IDEA中启用使用Maven

创建项目

image-20200811075848800

image-20200811080102213

image-20200811080231222

在项目创建成功后,检查一下是否正确(看一眼,万一依赖下载到C盘要炸,越来越多后面电子会“炸”)

image-20200811232328681

标记文件夹

补充文件夹java和resources,标记文件夹功能

  • java ——>Sources Root
  • resources——>Resources Root
    • resources文件夹是给java文件读取的

image-20200811233121704

修改web.xml

使用模板新建的项目,web.xml太旧了

image-20200812075515411

使用下载的tomcat中的中D:\Environment\apache-tomcat-9.0.37\webapps\ROOT\WEB-INF\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>

在Maven中创建一个普通项目

在New Project中不选择模板,直接点击Next

image-20200811232706548

image-20200811232926496

image-20200813212321470

WEB-INF用户不可见的,所以,如果你将jquery的包放在WEB-INF中,html中是拿不到的

pom.xml

maven由于他的约定大于配置,我们之后可能遇到的问题,无法导入或者生效xml、properties文件的问题

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

Maven手动导入jar

下载jar包

image-20200815073827912

Apache Commons IO » 2.4

导入jar

image-20200815131019491

Add as Library

右键lib文件夹

image-20200815074243289

碰到的问题

  • Maven 3.6.2(无法导入maven项目)

image-20200812074838920

解决方法:降级为3.6.1

  • iDEA中每次都要重复配置Maven

解决方法:在IDEA中全局默认配置去配置

image-20200821084822603

image-20200821084922284

在IDEA中配置Tomcat

配置Tomcat

image-20200811233642239

image-20200811233811032

image-20200811235431844

没有配置Deployment,会碰到如下警告

image-20200811235725339

image-20200811235559454

image-20200811234446348

碰到的问题

参考链接

启动tomcat

image-20200812000049930

image-20200812000018899

Servlet

Servlet简介

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

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

HelloServlet

第一个Servlet程序

  • 构建一个普通的Maven项目后删除里面的src目录,以后就在这个项目中建立一个Moudel,这个空的工程就是Maven的主工程

  • Maven父子工程的理解

    父项目中会有

    <modules>
        <module>servlet-01</module>
    </modules>
    

    子项目会有(如果没有的话下面这段,自己加一个)

    比如我创建的一个Moudle就没有自动生成,就需要自己写,还有删除一些自带的

    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>javaweb-servlet-01</artifactId>
        <groupId>com.study</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>servlet01</artifactId>
    <packaging>war</packaging>
    

    优点:父项目中的jar包可以在子项目中使用

  • maven工程添加servlet依赖

  • Maven环境优化

  • 修改web.xml为最新的

  • 将Maven的结构搭建 java resource

  • 编写一个Servlet程序

    • 编写一个普通类
    • 实现Servlet接口,直接继承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);
    }
}

  • 编写Servlet的映射
    • 为什么需要映射:因为我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的servlet,还需要给他一个能够访问的路径
<!--    注册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>
  • 配置tomcat并启动
  • 启动测试,OK!

Mapping

一般是用一个servlet可以指定一个映射路径

  • 一个servlet可以指定一个映射路径
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  • 一个servlet可以指定多个映射路径
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
  • 一个servlet可以指定通用映射路径
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
</servlet-mapping>
  • 指定一些后缀或者前缀(但是*前不加/)
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

ServletContext上下文

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

共享数据

我们在HelloServlet中保存数据,可以在另外一个servlet中拿到

但是尽量不要用ServletContext来共享数据,数据一多会炸,可以使用session

public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String) context.getAttribute("username");
        System.out.println(username);
        resp.setContentType("text/html");
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().print("名字:"+username);
    }

}

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello");
        ServletContext context =  this.getServletContext();

        String username = "DJ";
        context.setAttribute("username",username);//将一个数据保存在servletContext中
    }

}

读取资源文件

ProPerties

  • 在java目录下新建properties
  • 在resources目录下新建propertites

发现都被打包到同一个路径下:classes,我们俗称这个路径是classpath

public class ServletDemo03 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        //这个路径主要是针对target生成的
        InputStream is= context.getResourceAsStream("/WEB-INF/classes/db.properties");

        Properties prop = new Properties();
        prop.load(is);
        String username = prop.getProperty("username");
        String password = prop.getProperty("password");
        System.out.println(username+" "+ password);
    }

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

HttpServletResponse

使用例子

向浏览器输出消息

(上面一直提到)

下载文件

  1. 要获取下载的文件的路径
  2. 设置下载的文件名
  3. 设置想办法让浏览器能够支持下载我们需要的东西
  4. 获取下载文件的输入流
  5. 创建缓冲区
  6. 获取OutputStream对象
  7. 获取OutputStream流写入到buffer缓冲区
  8. 使用OutputStream将缓冲区中的数据输出到客户端
package com.study.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1. 要获取下载的文件的路径
        String realPath="D:\\Project\\javawebservlet01\\response\\target\\classes\\图片.png";
        System.out.println("下载文件的路径"+realPath);
//        2. 设置下载的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
        System.out.println("文件名"+fileName);
//        3. 设置想办法让浏览器能够支持下载我们需要的东西
        //web下载文件的头信息 URLEncoder.encode 处理文件名乱码
        resp.setHeader("Content-disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
//        4. 获取下载文件的输入流
        FileInputStream in = new FileInputStream(realPath);
//        5. 创建缓冲区
        int length=0;
        byte[] buffer = new byte[1024];
//        6. 获取OutputStream对象
        ServletOutputStream out =  resp.getOutputStream();
//        7. 获取OutputStream流写入到buffer缓冲区 使用OutputStream将缓冲区中的数据输出到客户端
        while((length=in.read(buffer))>0){
            out.write(buffer,0,length);
        }
        in.close();
        out.close();

    }

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

定时刷新验证码

采用的其实是刷新整个页面

package com.study.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //让浏览器3s自动刷新一次
        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.green);
        g.setFont(new Font(null,Font.BOLD,20));
        String num = makeNum();
        System.out.println(num);
        g.drawString(num,0,20);
        //告诉浏览器,这个请求用图片的方式打开
        resp.setContentType("image/jpeg");
        //把图片写到浏览器 jpg表示文件格式名
        ImageIO.write(image,"jpg",resp.getOutputStream());
    }
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(1000000)+"";//[0,100000)
        StringBuffer stringBuffer = new StringBuffer();
        for(int i = 0;i<6-num.length();i++){
            stringBuffer.append("0");
        }
        return num;

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

重定向

URL会发生变化

image-20200813074631411

一个web资源收到客户端A请求后,B通知客户端A去访问另外一个web资源C,这个过程叫重定向

void sendRedirect(String var1) throws IOException;

常见的例子:登录状态

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //设置后台传给前台的数据不是乱码
    resp.setCharacterEncoding("UTF-8");//不然页面显示会乱码
    resp.sendRedirect("/response_war/img");
}
<form action="${pageContext.request.contextPath}/redi" method="get">
    username:<input type="text" name="username" /><br/>
    password:<input type="text" name="password" /><br/>
    <input type="submit">
</form>

面试题:重定向和请求转发的区别

  • 相同点
    • 页面都会发生跳转
  • 不同点
    • 请求转发的时候URL不会发生变化 307
    • 重定向的时候,URL发生后变化 302

image-20200813075516958

HttpServletRequest

请求转发

req.getRequestDispatcher("/success.jsp").forward(req,resp);
//常用方法
//1. 获得前台的参数
//设置前台传给后台的数据不是乱码
req.setCharacterEncoding("UTF-8");
req.getParameter("username");
req.getParameterValues("hobbys");
//2. 通过请求转发 
// /success.jsp /代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);

Cookie,Session

会话

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

有状态会话:

一个网站,怎么证明你来过?

客户端 服务端

  1. 服务端给客户端一个信件,客户端下次访问服务端就带上一个信件就可以了 cookie
  2. 服务器登记你来过了,下次你来的时候我来匹配你:session

保存会话的两种技术

cookie:一般会保存在本地的用户目录下 appdata

//从请求中拿到cookie拿到cookie的信息
//服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得cookie
cookie.getName();//获得cookie的key
cookie.getValue();//获得cookie的value
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");//新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期,若没有设置,关闭浏览器cookie就失效
package com.study.servlet;

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

//保存用户上一次访问的时间
public class CookieDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //服务器 告诉你 你来的时间, 把这个时间封装成一个信件,你下次带来,我就知道了
        //解决中文乱码
        req.setCharacterEncoding("utf-8");

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf-8");
        PrintWriter out = resp.getWriter();
        //Cookie 服务器从客户端获取
        Cookie[] cookies = req.getCookies();

        if(cookies!=null){
            //如果存在,遍历数组
            out.write("你上一次访问的时间是");
            for(Cookie cookie:cookies){
                if("lastLoginTime".equals(cookie.getName())){
                    //获取cookie的值
                    System.out.println(cookie.getValue());//String
                    long lastLoginTime = Long.parseLong(cookie.getValue());
                    Date date = new Date(lastLoginTime);
                    out.write(date.toLocaleString());
                }
            }
        }else{
            out.write("这是第一次访问本站");
            System.out.println("这是第一次访问本站");
        }
        //服务器给客户端响应一个cookie
        Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
        //有效期为一天 s
        cookie.setMaxAge(24*60*60);
        resp.addCookie(cookie);
    }

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

Session(重点)

什么是Session

  • 服务器会给每一个用户(浏览器)创建一个Session对象
  • 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就一直存在
  • 用户登录之后,整个网站都可访问
//创建session 并且给属性赋值,也是可以存放一个对象的
package com.study.servlet;

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

public class CookieDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码
        req.setCharacterEncoding("utf-8");

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf-8");
        //得到session
        HttpSession session = req.getSession();
        //给Session中存在东西
        session.setAttribute("name","张三");
        //获得session的ID
        String id = session.getId();
        //判断Session 是不是新创建的
        if(session.isNew()){
            resp.getWriter().write("session创建成功ID"+id);
        }else{
            resp.getWriter().write("session已经创建成功ID"+id);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
//取出session的值
package com.study.servlet;

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

public class CookieDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决中文乱码
        req.setCharacterEncoding("utf-8");

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf-8");
        //得到session
        HttpSession session = req.getSession();
        //取Session中存在东西
        resp.getWriter().write(session.getAttribute("name"));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
设置session的失效时间
在web.xml
<!--  设置session的失效时间 单位:分钟-->
<session-config>
	<session-timeout>1</session-timeout>
</session-config>
在代码中
session.removeAttribute("name");
session.invalidate();

Session和Cookie的区别

  • session存储在服务器端,cookie保存在浏览器。
  • session比较安全,cookie用某些手段可以修改,不安全。
  • cookie的存储量有限、只允许存入4KB,而session是无限量的
  • image-20200813142213120

image-20200813142250640

使用场景:

  • 保存一个登录用户的信息
  • 购物车信息
  • 在整个网站中经常使用的数据,将他保存在session

JSP

什么是jsp

java server pages :java服务器页面,也和servlet一样,用户动态web技术

最大的特点

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

JSP原理

思路 JSP是怎么执行的

  • 代码层面没有任何问题,和html代码很像
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
  • 服务器内部工作

tomcat 中有一个work目录

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

D:\Environment\apache-tomcat-9.0.37\work\Catalina\localhost\ROOT\org\apache\jsp

image-20200813144454542

发现页面变成了java程序,jsp最终会被转换成一个java类

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

image-20200813144729176

image-20200813172109605

  • JSP本质上就是一个servlet
final javax.servlet.jsp.PageContext pageContext;//页面上下文
javax.servlet.http.Httpsession session=null;//Session
final javax.servlet.Servletcontext application;//application
final javax.servlet.ServletConfig config;//config
javax.servlet.jsp.JspWriter out=null;//out
final java.lang.Object page = this;//pag	e当前页
HttpServletRequest  request;//请求
HttpServletReponse  reponse ;//响应    

在JSP页面中

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

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

out.writer("<html>\r\n")

JSP基础语法

jsp表达式

<%=new java.util.Date()%>

jsp脚本片段

<%for(int i = 0;i<10;i++){%>
    <p>123</p>
<%}%>

jsp声明

<%!
static {
         system. out. println(" Loading Servlet! ");
}

private int globalvar =0;

public void f(){
         system. out printIn("进入了方法 ");
}
%>

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

<!--我是Html注释->
<%--我是JSP注释--%>
jsp的注释不会在客户端显示,html的注释可以看到

九大内置对象

  • PageContext 存东西
  • Request 存东西
  • Response
  • Session 存东西
  • Application【ServeltContext】存东西
  • config【ServletConfig】
  • out
  • page 不用了解
  • exception

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

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

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

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--http://localhost:8080/jsp01_war_exploded/pageContextDemo01.jsp--%>
<%--内置对象--%>
<%
    pageContext.setAttribute("name1","张三");// 保存的数据只在一个页面中有效,在另外一个页面就请求不到了
    request.setAttribute("name2","李四");//保存的数据只有在一次请求中有效,请求转发会携带这个数据
    session.setAttribute("name3","王五");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
    application.setAttribute("name4","小李");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%
//    通过pageContext取出我们保存的值
//pageContext取出,我们通过寻找的方式来
    //从底层到高层(作用域)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");
    //pageContext.forward("/pageContextDemo02.jsp"); 测试request请求转发的作用域
%>

<%--使用EL表达式输出 ${}--%>
<%--一般取值就用EL表达式,比%=好,因为会自动过滤null的值--%>
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>

</body>
</html>

JSTL标签、EL表达式(${})

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

核心标签

标签 描述
<c:out> 用于在JSP中显示数据,就像<%= ... >
<c:set> 用于保存数据
<c:remove> 用于删除数据
<c:if> 与我们在一般程序中用的if一样
<c;choose> 本身只当做<c:when>和<c:otherwise>的父标签
<c:when> <c:choose>的子标签,用来判断条件是否成立
<c:otherwise> <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行
<cLforeach> 基础迭代标签,接受多种集合类型
<c:url> 使用可选的查询参数来创造一个URL

JSTL标签使用步骤

  • 引入对应的taglib
  • 使用其中的方法
  • 在Tomcat也需要引入jstl的包,否则会出现500
    • lib目录下D:\Environment\apache-tomcat-9.0.37\lib

image-20200813231040262

<%@ 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>

<h4>if测试</h4>
<form action="coreif.jsp" method="get">
<%--    EL表达式获取表单中数据--%>
    <input type="text" name="username" value="${param.username}">
    <input type="submit" value="登录">
</form>

<%--判断如果提交的是用户名是admin就登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
    <c:out value="管理员欢迎你"/>
</c:if>
<c:out value="${isAdmin}"/>
</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="55" />
<c:choose>
    <c:when test="${score>=90}">
        优秀
    </c:when>
    <c:when test="${score>=80}">
        良好
    </c:when>
    <c:when test="${score>=60}">
        合格
    </c:when>
    <c:otherwise >
        不及格
    </c:otherwise>
</c:choose>
</body>
</html>

JavaBean

javaBean有特定的写法

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

一般和数据库的字段做映射

ORM 对象关系映射

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

注意:一定要每一个字段都和实体类的属性对应

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--stu = new Test();--%>
<jsp:useBean id="test" class="com.jmu.vo.Test" scope="page"/>
<jsp:setProperty name="test" property="id" value="1018" />
<jsp:setProperty name="test" property="name" value="大东" />

<jsp:getProperty name="test" property="id"/>
<jsp:getProperty name="test" property="name"/>

</body>
</html>

MVC三层结构

Filter

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

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

Filter开发步骤:

  • 导包

  • 编写过滤器

    • 导入不要错import javax.servlet.*;
package com.jmu.fiter;

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

public class CharacterEncodingFilter implements Filter {
    //初始化:web服务器启动,就一起初始化,随时等待过滤对象出现
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化");

    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        System.out.println("执行前");
        filterChain.doFilter(servletRequest,servletResponse);//让我们的请求继续走,如果不行,程序执行到这里就被拦截
        System.out.println("执行后");
    }
    //销毁 web服务器关闭的时候,过滤会销毁
    public void destroy() {
        System.out.println("销毁");
    }
}
  • 在web.xml中配置filter
<filter>
	<filter-name>CharacterEncoding</filter-name>
	<filter-class>com.jmu.fiter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>CharacterEncoding</filter-name>
<!--        只要是/filter/*的任何请求就执行过滤器-->
	<url-pattern>/filter/*</url-pattern>
</filter-mapping>

例子

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

  1. 用户登录之后,向session放入用户的数据,并且重定向到主页
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");//重定向
  1. 注销
if(req.getSession().getAttribute("USER_SESSION")!=null){
    req.getSession().removeAttribute("USER_SESSION");
}
resp.sendRedirect("/login.jsp");
  1. 将主页放在sys文件夹中,当session("USER_SESSION")为空的时候,就跳转到登录页面
package com.jmu.fiter;

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

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //如果没有强转 ServletRequest没有getSession方法
        HttpServletRequest req = (HttpServletRequest)servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        if((req.getSession().getAttribute("USER_SESSION"))==null){
            resp.sendRedirect("/login.jsp");
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void destroy() {

    }
}

xml

<filter>
    <filter-name>sysFilter</filter-name>
    <filter-class>com.jmu.fiter.SysFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>sysFilter</filter-name>
    <url-pattern>/sys/*</url-pattern>
</filter-mapping>

练习登录

项目搭建

  1. 搭建一个maven web项目
  2. 配置tomcat
  3. 修改web.xml
  4. 测试项目是否能够跑起来(localhost:8080/)He
  5. 导入项目中会遇到的jar
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
  </dependency>
  <!--        Servlet依赖-->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
  </dependency>
  <!--        JSP依赖-->
  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.3</version>
    <scope>provided</scope>
  </dependency>
  <!--        jstl表达式的依赖-->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <!--        standar标签库-->
  <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>
  1. 创建项目结构 java main(com.jmu.dao/filter/vo/servlet/service/util) resources

    1. dao层用来和数据库交互并返回结果
    2. service业务层(判断用户是否登录成功)
    3. servlet调用控制层
    4. filter过滤器
    5. util工具类
    6. image-20200814192445303
  2. 编写实体类vo

  3. 编写基础公共类

    1. resources中db.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/demo?serverTimezone=GMT&useUnicode=true&characterEncoding=utf8&useSSL=true
username = root
password = 123456
  1. 编写数据库工具类

  2. 编写字符编码过滤器filter(上面有写过的)

  3. 在webapp导入静态资源css js image等等 在webapp下新建static再放

登录功能实现

  1. 登录页面(在jsp文件夹下新建一个主页home.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--login.jsp--%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login.do" method="post">
    用户名 <input type="text" name="username"/><br/>
    密码 <input type="password" name="password"/><br/>
    <input type="submit" value="登录" />

</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--home.jsp--%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>主页</h1>
<a href="${pageContext.request.contextPath}/logout.do">注销</a>
</body>
</html>
  1. 在web.xml中将登录页面设为首页,不是index.jsp
<welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
</welcome-file-list>
  1. 编写接口UserDao
package com.jmu.dao;

import com.jmu.vo.User;

public interface UserDao {
    //通过username得到登录的用户
    public User getLoginUser(String username);
}

  1. 编写接口UserDao的实现类UserDaoImpl
package com.jmu.dao;

import com.jmu.util.JdbcUtil;
import com.jmu.vo.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDaoImpl implements UserDao{

    @Override
    public User getLoginUser(String username) {
        Connection conn = null;
        PreparedStatement pst =null;
        User user = null;
        try {
            conn  = JdbcUtil.getConnection();
            String sql = "select * from user where username = ?";
            pst = conn.prepareStatement(sql);//预编译
            //传递参数
            Object[] params = {username};
            for(int i = 0;i<params.length;i++){
                pst.setObject(i+1,params[i]);
            }
            ResultSet rs = pst.executeQuery();
            while(rs.next()){
                int auto_id=rs.getInt("auto_id");
                String password=rs.getString("password");
                int age=rs.getInt("age");
                user = new User(auto_id,username,password,age);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtil.release(conn,pst,null);
        }
        return user;
    }
}

  1. 编写业务层接口UserService
package com.jmu.service;

import com.jmu.vo.User;

public interface UserService {
    //用户登录
    public User login(String username, String password);
}
  1. 业务层实现类UserServiceImpl
package com.jmu.service;

import com.jmu.dao.UserDao;
import com.jmu.dao.UserDaoImpl;
import com.jmu.vo.User;
import org.junit.Test;

public class UserServiceImpl implements UserService {
    //业务层都会调用dao层,所以我们要引入Dao层
    private UserDao userDao;
    public UserServiceImpl(){
        userDao = new UserDaoImpl();
    }
    @Override
    public User login(String username, String password) {
        User user = null;
        user = userDao.getLoginUser(username);
        //对比密码
        if(user!=null&&user.getPassword().equals(password)){
            return user;
        }else{
            return null;
        }

    }

    @Test
    public void test(){
        System.out.println(new UserServiceImpl().login("user02","122").toString());
    }
}
  1. 编写servlet

登录servlet

package com.jmu.servlet;

import com.jmu.service.UserService;
import com.jmu.service.UserServiceImpl;
import com.jmu.util.Constants;
import com.jmu.vo.User;

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 LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        //和数据库中的密码进行对比 调用业务层
        UserService userService=new UserServiceImpl();
        User user =userService.login(username,password);
        if(user!=null){
            //将用户信息保存到session里面
            req.getSession().setAttribute(Constants.USER_SESSION,user);
            //跳转到主页
            resp.sendRedirect(req.getContextPath()+"/jsp/home.jsp");
        }else{
            //跳转到ERROR
            resp.sendRedirect(req.getContextPath()+"/error.jsp");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  1. 注册servlet
<servlet>
    <servlet-name>login</servlet-name>
    <servlet-class>com.jmu.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>login</servlet-name>
    <url-pattern>/login.do</url-pattern>
</servlet-mapping>
  1. 运行测试
posted @ 2020-08-21 09:32  DJ同学  阅读(4049)  评论(0编辑  收藏  举报