java学习之javaWeb

参考资料
尚硅谷javaweb2022版教程

1.CS和BS的异同点

CS:客户端服务器架构模式
优点:一部分安全要求不改的计算任务和存储任务放在客户端进行,不需要把所有的计算和存储都在服务器执行,从而能够减轻服务器的压力,充分利用客户端机器的资源,也能减轻网络负担
缺点:需要安装,升级维护成本较高
BS:浏览器服务器架构模式
优点:客户端不需要安装,维护成本较低
缺点:所有的计算和存储任务都是放在服务器端的,服务器的负荷较重,在服务端计算完成之后把结果再传输给客户端,所以服务端和客户端会进行频繁的通信,从而网络负荷较重。

2.Tomcat

2.1新建项目-部署-运行-访问(底层原理)

下载地址
tomcat下载,解压时路径不要出现中文!

目录结构说明
bin 可执行文件目录
conf 配置文件目录
lib 存放依赖的目录
losg 存放日志的目录
webapps 项目部署的目录
work 工作目录
temp 临时目录
配置环境变量
在系统变量下新建JAVA_HOME
在这里插入图片描述
访问localhost
浏览器输入localhost:8080
在这里插入图片描述

新建项目
在webapps中新建一个文件夹(名字随意 )
在该文件夹中新建一个WEB-INF文件夹(名字不能错!)
访问项目
浏览器输入:
http://localhost:8080/新建的文件名/html文件

2.2在IDEA下新建javaWeb项目

注:社区版不支持web项目,在校学生可以申请学生免费,详情见这位大佬的文章
idea申请学生免费方法

首先,先新建一个项目,右键添加新的框架支持
在这里插入图片描述
添加如图文件
在这里插入图片描述
在web中即可新建html文件
在这里插入图片描述
配置Tomcat,点击Add configuration,
在这里插入图片描述
选择Tomcat的本地路径,后apply
在这里插入图片描述
部署项目,同样的步骤点击deployment点击加号点击第一个
在这里插入图片描述
点第一个serve,如图设置,url后面是点击运行后默认打开的网址
在这里插入图片描述

3.Servlet

3.1Servlet获取参数

首先,我们需要先添加一个依赖
点击:File->Project Structure->Moudles->选择要添加的模块->添加
在这里插入图片描述
编写一个html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="add" method="post">
    名称:<input type="text" name="fname"><br/>
    价格:<input type="text" name="price"><br/>
    库存:<input type="text" name="fcount"><br/>
    备注:<input type="text" name="remark"><br/>
    <input type="submit" value="添加">
</form>
</body>
</html>

编写一个AddServelt用于获取参数

import Dao.FruitDao;
import Dao.FruitDaoImpl;
import bean.fruit;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.dbutils.DbUtils;
import utils.JDBCutils;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

public class AddServelt extends HttpServlet {
    //相应post请求

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //post方式下,设置编码,防止中文乱码
        request.setCharacterEncoding("UTF-8");
        String fname = request.getParameter("fname");
        String priceStr=request.getParameter("price");
        Integer price = Integer.parseInt(priceStr);
        String fcountStr = request.getParameter("fcount");
        Integer fcount = Integer.parseInt(fcountStr);
        String remark = request.getParameter("remark");

        //添加至数据库中的操作,代码书写方式见JDBC笔记
        Connection conn = null;
        FruitDao fruitDao = new FruitDaoImpl();
        try {
             conn = JDBCutils.getConnection();
             fruitDao.addFruit(conn,new fruit(0,fname,price,fcount,remark));
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                DbUtils.close(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

在web.xml中添加刚刚写的Servlet

    <servlet>
     
        <servlet-name>AddServlet</servlet-name>
        <servlet-class>servlets.AddServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AddServlet</servlet-name>
        <url-pattern>/add</url-pattern>
    </servlet-mapping>
    <!--
    1.用户发请求,action=add
    2.项目中,找到url-pattern =/add
    3.找servlet-name=AddServlet
    4.找和ervlet-mapping中servlet-name一致的Servlet
    5.最终找到servlets.AddServlet
    6.用户发送的是post,所以会执行AddServlet中的doPost
    -->

以上流程的图示
在这里插入图片描述
小小的回顾一下

  1. 新建项目-新建模块
  2. 在项目中添加web
  3. 现有artifact,后来才添加的jar包,此时这个jar包并没有添加到部署中,那么在projectSettings中有一个Problems中会有提示的,我们点击fix添加即可,

3.2Servlet继承关系以及生命周期

继承关系

javax.servelt.Servelt接口
javax.servelt.GenericServelt抽象类
javax.servelt.http.HttpServelt抽象子类

相关方法-重点为服务方法
javax.servlet.Servlet接口

void init(config) - 初始化方法
void servlet(request,response) - 服务方法(自动响应请求)
void destroy() - 销毁方法

javax.servelt.GenericServelt抽象类

void servlet(request,response) - 仍为抽象方法

javax.servlet.http.HttpServlet抽象子类

void servlet(request,response) - 不是抽象方法
1.String method = req.getMethod() - 获取请求的方式
2.各种if判断,根据请求方式的不同,决定去调用不同的do方法
3.需要根据请求的方式,重写相应的do方法,不然会报405

servlet的生命周期

生命周期:从创建到销毁,对应init(),service(),destroy()

测试代码

//演示servlet的声明周期
public class Demo02SerVlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("正在初始化");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("正在服务");
    }

    @Override
    public void destroy() {
        System.out.println("正在销毁");
    }
}

启动服务后:
在这里插入图片描述
一直刷新网页
在这里插入图片描述
点击停止后:
在这里插入图片描述

默认情况下:
从第一次请求开始,这个servlet会实例化,初始化,然后服务
从第二次请求开始,每一次都是服务
关闭容器后,其中所有的servlet都会销毁
servlet实例tomcat只会创建一个,所有的请求都是这个实例去响应

3.3HTTP协议

介绍

HTTP:超文本传输协议,最大的作用是确定了请求和响应数据的格式。浏览器发个服务器的数据:请求报文(request)。服务器给浏览器的:响应请求(response)。

请求的三个部分
请求头

展现当前请求的基本信息(请求的方式,请求的URL,请求的协议)

请求消息头

包含了很多客户端需要告诉服务器的消息

名称功能
Host服务器的主机地址
Accept声明当前能够接受的媒体类型
Referer当前请求来源页面的地址
Contene-Length请求体内容的长度
Content-type请求体的内容类型,这一项的具体值是媒体类型中的某一种
Cookie浏览器访问服务器时携带的Cookie数据

请求主体

三种情况:
get方式,没有请求体
post方式,有请求体,form data
json格式,request payload

响应的三个部分

响应行:包含:协议,响应状态码,响应状态
响应头:包含了服务器的信息,服务器发给浏览器的信息(内容的媒体类型,编码,内容长度等)
响应体:响应的实际内容

3.4会话(session)

HTTP的无状态

HTTP是无状态的(服务器无法判断不同的请求是否来自于同一个客户端)
-通过会话跟踪技术来解决无状态的问题

图解会话

在这里插入图片描述

会话跟踪技术

  1. 客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的,然后响应给客户端
  2. 下次客户端给服务器法请求时,会把sessionID带给服务器,那么服务器就能企分开客户端了

常用的API

  1. request.getSession()->获取当前的会话,没有就创建一个新的
  2. request.getSeeeion(true)->效果和不带参数相同
  3. request.getSeeeion(false)->获取当前会话,没有返回null,不会创建新的
  4. session.getID()->获取sessionID
  5. session.isNew()->判断当前session是否为新的
  6. session.getMaxInactiveInterval()->session的非激活间隔时长,默认为半小时
  7. session.invalidate()->让会话立即失效

session的保存作用域

session保存作用域是和具体的某一个session对应的
同一个客户端可以访问其保存的数据
不同的客户端不能访问其他客户端的数据

在这里插入图片描述
上图中第二个空白黑框代表另一个服务器,其无法访问第一个服务器保存的数据。

常用API

-session.setAttribute(k,v)
-Object session.getAttribute(k)
-void removeAttribute(k)

服务器内部转发以及客户端重定向

-服务器内部转发:request.getRequestDispatcher(“…”).forward(request,response);
-客户端重定向:
response.sendRedirect(“…”);

内部转发:
一次响应的过程,客户端是不知道内部经过多少次转发的
在这里插入图片描述
客户端重定向:
两次响应的过程,客户端直到请求URL有变化
在这里插入图片描述

3.5thymeleaf(视图模板技术)

1.添加thymeleaf的jar包
2.在web.xml中添加配置
3.新建一个ViewBaseServlet(复制黏贴即可)

首先新建一个ViewBaseServlet类,直接赋值黏贴即可,这段代码学了框架之后会被代替

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
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 ViewBaseServlet extends HttpServlet {

    private TemplateEngine templateEngine;

    @Override
    public void init() throws ServletException {

        // 1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        // 2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);

        // 3.给解析器对象设置参数
        // ①HTML是默认模式,明确设置是为了代码更容易理解
        templateResolver.setTemplateMode(TemplateMode.HTML);

        // ②设置前缀
        String viewPrefix = servletContext.getInitParameter("view-prefix");

        templateResolver.setPrefix(viewPrefix);

        // ③设置后缀
        String viewSuffix = servletContext.getInitParameter("view-suffix");

        templateResolver.setSuffix(viewSuffix);

        // ④设置缓存过期时间(毫秒)
        templateResolver.setCacheTTLMs(60000L);

        // ⑤设置是否缓存
        templateResolver.setCacheable(true);

        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");

        // 4.创建模板引擎对象
        templateEngine = new TemplateEngine();

        // 5.给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);

    }

    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");

        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, getServletContext());

        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}

并在web.xml中加入如下配置文件

    <!-- 在上下文参数中配置视图前缀和视图后缀 -->
    <context-param>
        <param-name>view-prefix</param-name>
        <param-value>/</param-value>
    </context-param>
    <context-param>
        <param-name>view-suffix</param-name>
        <param-value>.html</param-value>
    </context-param>

实现页面的跳转
这段代码的功能是运行后会跳转到/index.html页面

import Dao.FruitDao;
import Dao.FruitDaoImpl;
import bean.fruit;

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

//servlet从3.0开始支持注解方式的注册
@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        FruitDao fruitDao = new FruitDaoImpl();
        List<fruit> list= fruitDao.getFruitList();
        //保存到session作用域
        HttpSession session = req.getSession();
        session.setAttribute("fruitList",list);

        //此处的视图名称是 index
        //那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
        //逻辑视图名称 :   index
        //物理视图名称 :   view-prefix + 逻辑视图名称 + view-suffix
        //所以真实的视图名称是:      /       index       .html
        //所以最终跳转的页面是 /index.html
        super.processTemplate("index",req,resp);
    }
}

渲染页面
thymeleaf标签

th:if:判断
th:unless:除非
th:each:相当于foreach
th:text:文本

html代码:

<html xmlns:th="http://www.thymeleaf.org">
<head>
    <link rel="stylesheet" href="CSS/Demo.css">
</head>
<body>
<div id="div_container">
    <div id="div_fruit_list">
        <p class="center f30">欢迎使用水果库存后台管理系统</p>
        <table id="tb1_fruit">
            <tr>
                <th class="w20">名称</th>
                <th class="w20">单价</th>
                <th class="w20">库存</th>
                <th>操作</th>
            </tr>
            <tr th:if="${#lists.isEmpty(session.fruitList)}">
                <td colspan="4">对不起,库存为空!</td>
            </tr>
            <tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit :${session.fruitList}">
                <td th:text="${fruit.fname}">苹果</td>
                <td th:text="${fruit.price}">5</td>
                <td th:text="${fruit.fcount}">20</td>
                <td><img src="imgs/del.jpg" width=20px height=20px/></td>
            </tr>
            </table>
    </div>
</div>
</body>
</html>

效果:数据库中的两条数据都被加载到页面上了
在这里插入图片描述

3.6servlet保存作用域

原始情况下:保存作用域可认为有四个:page(页面级别,现在几乎不用),request(一次请求响应范围),session(一次会话范围),application(整个会话范围)

request

若使用客户端重定向,则demo02无法读出lili(相当于超出了一次响应范围)
若使用内部转发,则可以读出lili

在这里插入图片描述
session

与上图类似,在session作用域保存获取数据的代码:
req.getSession().setAttribute(“uname”,“lili”);
Object obj = req.getSession().getAttribute(“uname”);

          session作用域通过重定向与转发均可获取,只要不创建新会话

application

在application作用域保存数据:
ServletContext application = req.getServletContext();
application.setAttribute(“uname”,“lili”);
在application作用域中读取数据
ServletContext application = req.getServletContext();
Object obj = application.getAttribute(“uname”);

在application中保存的数据,只要tomcat服务没用停止,数据就是公共的,所有客户端均可访问。

3.7servlet路径问题

一张关于路径的图:

红色为相对路径
蓝色为绝对路径

在这里插入图片描述

3.8Servlet Api

初始化
如果我们想要在Servlet初始化时做一些准备工作,那么我们可以重写init方法

下面是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-name>Demo01Servlet</servlet-name>
        <servlet-class>servlet.Demo01Servlet</servlet-class>
        <init-param>
            <param-name>hello</param-name>
            <param-value>world</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>Demo01Servlet</servlet-name>
        <url-pattern>/demo01</url-pattern>
    </servlet-mapping>
</web-app>
public class Demo01Servlet extends HttpServlet {
   /* 我们可以通过如下步骤去获取初始化设置的数据
   - 获取config对象:ServletConfig config = getServletConfig();
   - 获取初始化参数值: config.getInitParameter(key);*/
    @Override
    public void init() throws ServletException {
        ServletConfig config = getServletConfig();
        String initValue = config.getInitParameter("hello");
        System.out.println(initValue);
    }
}

也可以通过注解的方式

@WebServlet(urlPatterns = {"/demo01"},
        initParams = {
                @WebInitParam(name="hello",value="world")
        }
)

Servlet中的ServletContext和<context-param>

  1. 获取ServletContext,有很多方法
    在初始化方法中: ServletContxt servletContext = getServletContext();
    在服务方法中也可以通过request对象获取,也可以通过session获取:
    request.getServletContext(); session.getServletContext()
    2) 获取初始化值:
    servletContext.getInitParameter();

业务层

MVC : Model(模型)、View(视图)、Controller(控制器)
视图层:用于做数据展示以及和用户交互的一个界面
控制层:能够接受客户端的请求,具体的业务功能还是需要借助于模型组件来完成
模型层:模型分为很多种:有比较简单的pojo/vo(value object),有业务模型组件,有数据访问层组件
    1) pojo/vo : 值对象
    2) DAO : 数据访问对象
    3) BO : 业务对象

过滤器filter

  1. Filter也属于Servlet规范
  2. Filter开发步骤:新建类实现Filter接口,然后实现其中的三个方法:init、doFilter、destroy
    配置Filter,可以用注解@WebFilter,也可以使用xml文件
  3. Filter在配置时,和servlet一样,也可以配置通配符,例如 @WebFilter(“*.do”)表示拦截所有以.do结尾的请求
  4. 过滤器链
    1)如果采取的是注解的方式进行配置,那么过滤器链的拦截顺序是按照全类名的先后顺序排序的(字母顺序)
    2)如果采取的是xml的方式进行配置,那么按照配置的先后顺序进行排序

事物
之前在DAO层里处理事物的缺点:
在这里插入图片描述
通过过滤器来解决上述问题
在这里插入图片描述
Listener(了解)
1) ServletContextListener - 监听ServletContext对象的创建和销毁的过程
2) HttpSessionListener - 监听HttpSession对象的创建和销毁的过程
3) ServletRequestListener - 监听ServletRequest对象的创建和销毁的过程

4) ServletContextAttributeListener - 监听ServletContext的保存作用域的改动(add,remove,replace)
5) HttpSessionAttributeListener - 监听HttpSession的保存作用域的改动(add,remove,replace)
6) ServletRequestAttributeListener - 监听ServletRequest的保存作用域的改动(add,remove,replace)

7) HttpSessionBindingListener - 监听某个对象在Session域中的创建与移除
8) HttpSessionActivationListener - 监听某个对象在Session域中的序列化和反序列化

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值