JavaWeb入门笔记

前端

这个阶段主要是学习静态页面

HTML

客户端浏览器请求:Http Request -> 服务器响应:Http Response -> 客户端浏览器处理响应数据(字符串),渲染成页面。这些字符串就是HTML。HTML是超文本标记语言,决定页面显示的内容。

解释性语言,不缺分大小写

树形结构

  • html
    • head
      • meta
      • meta
    • body
1
2
3
4
5
6
7
<!DOCTYPE html> 
<html>
<head>
</head>
<body>
</body>
</html>

table

tr:行

th:表头行列

td:行列,和th功能一直,th内置了一些css

from表单

action:提交表单触发的动作

method:表单提交请求方式

radioi单选按钮,同name为一组。

checked复选框,可以不同name,但同组应为同name,以方便传参给后端处理。

select:下拉选择框

注意提交和重置表单按钮为submitreset

注意:当name=value时,可单写name,效果一致,如checked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<form action="ok.html" method="post">
<label for="123">456</label><br>
账号<input type="number" name=""><br>
密码<input type="password"><br>
在线状态
<input type="radio" name="gender" value="1">
<input type="radio" name="gender" value="2" checked><br>
爱好<br>
<input type="checkbox" name="hobby" value="1" checked>篮球<br>
<input type="checkbox" name="hobby" value="2">足球<br>
<input type="checkbox" name="hobby" value="3">乒乓球<br>

<select name="star" id="star">
<option value="1">白羊</option>
<option value="2" selected>天蝎</option>
<option value="3">巨蟹</option>
</select>
<textarea name="texts" id="texts" cols="30" rows="10" style="font-size: 18;"></textarea>
<br>
<input type="submit"></input>
<input type="reset"></input>
</form>

*frameset:

页面框架:多个页面拼凑成一个页面,代替body。已经淘汰,做个了解

*iframe:

在一个 正常页面嵌入另外一个页面

CSS

css决定页面上的内容(HTML)以何种形式显示出来,即决定页面上的美观程度美化页面

基本分类

单样式

标签样式、类样式、id样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* 标签样式 */
p{
color: red;
}
/* 类样式 */
.f20{
font-size: 25px;
}

/* ID样式 */
#p4{
font-style: normal;
font-size: 70px;
}

组合样式

1
2
3
4
/* 混合样式 */
div p{
font-family: 'Lucida Sans';
}

位置上的分类

css渲染时,采取就近原则

嵌入式样式表、内部样式表、

外部样式表

JavaScript

实现页面的特效

后端

BS/CS

Browser/Server、Client/Server

Tomcat

服务器程序的容器,体积小,免费

目录结构

  • Tomcat
    • bin:可执行文件目录
    • conf:配置文件的目录
    • lib:运行tomcat所需要的依赖文件库
    • logs:存放日志目录
    • temp:临时目录
    • webapps:项目部署目录
    • work:工作目录

配置

需要jre:即配置JAVA_HOME环境变量

访问

localhost:8080/context root/xxx.html:不同项目的contextroot不同

tomcat.xml下配置wellcome页是index,如果context后不接任何路径则默认访问该wellcome页

1
2
3
4
5
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

IDEA配置Tomcat

java项目添加web module:new->module->web

右键项目->add Frameword support->JavaEE->tomcat

Servelet

注解

Servlet3.0开始支持@WebServlet注解,通过注解方式配置一个Servlet

1
@WebServlet

Java Servelet是服务器应用程序,是客户端请求和服务器上的数据库或应用程序之间的中间层。

image-20220304003801554

自定义Servlet

新建servlet类

对于一个 Servlet 类,我们日常最常用的方法是继承自 HttpServlet 类,提供了 Http 相关的方法,HttpServlet 扩展了 GenericServlet 类,而 GenericServlet 类又实现了 Servlet 类和 ServletConfig 类。

web mudole中src下新建servlet类,继承自HttpServlet类,可根据需要重写doPost\doGet方法

1
2
3
4
5
6
7
8
9
10
11
public class addServlet extends HttpServlet {

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String age = req.getParameter("age");
System.out.println("name = " + name);
System.out.println("age = " + age);

}
}

配置servlet类映射http请求路径

web.xml配置映射路径

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>addPeople</servlet-name>
<servlet-class>com.ainexur.servlets.addServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>addPeople</servlet-name>
<url-pattern>/add</url-pattern>
</servlet-mapping>

这样一个servlet就配置完成,http请求contextroot/add就可以访问到该servlet中间件。

流程概述

  1. 用户点击提交表单,带着请求数据发起Http请求
  2. 项目中,从web.xml寻找到url
  3. 寻找url对应的servlet-name
  4. 寻找servlet-name对应的servlet-class
  5. 进入class,根据表单提交的方式进入该servlet类的doPost或者doGet方法,进行处理
  6. 处理结束,

生命周期

servlet生命周由容器(Tomcat)自动化管理。

默认情况下,第一次请求时,tomcat才会实例化,并且只会创建一个实例,所有的服务都通过这个实例处理请求。优势:提高系统启动速度,但第一次请求时耗时较长。如果需要提高响应速度,可以在配置文件设置load-on-startup的值来指定初始化时机。

1
2
3
4
5
<servlet>
<servlet-name>demo02Servlet</servlet-name>
<servlet-class>com.ainexur.io.Demo02Servlet</servlet-class>
<load-on-startup>1</load-on-startup> //指定servlet的启动时机、数字越小,启动越靠前
</servlet>

Servlet在容器中是单例的、线程不安全的,尽量不要在servlet中定义成员变量、不要根据成员变量的值来判断,做操作。

servlet生命周期定义为从创建直到毁灭的整个过程:

  1. Servlet初始化后调用init()函数
  2. Servlet调用service()函数处理客户端请求
  3. Servlet摧毁前调用destroy()方法
  4. 最后,Serlvet由JVM的垃圾回收器进行垃圾回收

部署

部署到tomcat的并非源代码,而是一个部署包-Artifacts:web应用程序压缩包(war包)的解压缩的包,

  1. 新建项目,新建web模块

  2. 创建artifact部署包

  3. lib-artifact:现有artifact,后面再添加的mysql.jar文件

  4. lib放在module里是module独用,lib放在项目里是所有module都可以用:

    设置lib为库->module引用该库。module引用新lib后,要更新部署包

继承关系

  1. javax.servlet.Servlet 接口

    • void init(config) 初始化方法
    • void service() 服务方法
    • void destroy() 销毁方法
  2. javax.servlet.ericServlet 抽象类

    • void service() 抽象方法
  3. javax.servlet.http.HttpServlet 抽象子类

    • void service():

      根据请求的的method判断,调用对应的方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
      {
      String method = req.getMethod(); //获取method
      long lastModified;
      if (method.equals("GET")) { //根据method,调用对应的方法
      lastModified = this.getLastModified(req);
      if (lastModified == -1L) {
      this.doGet(req, resp);
      } else {
      long ifModifiedSince;
      try {
      ifModifiedSince = req.getDateHeader("If-Modified-Since");
      } catch (IllegalArgumentException var9) {
      ifModifiedSince = -1L;
      }

      if (ifModifiedSince < lastModified / 1000L * 1000L) {
      this.maybeSetLastModified(resp, lastModified);
      this.doGet(req, resp);
      } else {
      resp.setStatus(304);
      }
      }
      } else if (method.equals("HEAD")) {
      lastModified = this.getLastModified(req);
      this.maybeSetLastModified(resp, lastModified);
      this.doHead(req, resp);
      } else if (method.equals("POST")) {
      this.doPost(req, resp);
      } else if (method.equals("PUT")) {
      this.doPut(req, resp);
      } else if (method.equals("DELETE")) {
      this.doDelete(req, resp);
      } else if (method.equals("OPTIONS")) {
      this.doOptions(req, resp);
      } else if (method.equals("TRACE")) {
      this.doTrace(req, resp);
      } else {
      String errMsg = lStrings.getString("http.method_not_implemented");
      Object[] errArgs = new Object[]{method};
      errMsg = MessageFormat.format(errMsg, errArgs);
      resp.sendError(501, errMsg);
      }

      }

      调用的方法类似:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      String msg = lStrings.getString("http.method_get_not_supported");
      this.sendMethodNotAllowed(req, resp, msg);
      }

      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      String msg = lStrings.getString("http.method_post_not_supported");
      this.sendMethodNotAllowed(req, resp, msg);
      }

      相关信息绑定在这里

      1
      private static final ResourceBundle lStrings  ResourceBundle.getBundle("javax.servlet.http.LocalStrings");

遇到问题

405:请求方法和servlet方法不匹配

未解决:new-module时,添加web不成功,为java项目

Http协议

  1. Http称之为超文本传输协议
  2. Http包含两个部分:请求和响应
    • 请求包含三个部分:
      • 请求行:展示当前请求的最基本信息,请求方式、请求URL、协议版本
      • 请求消息头:包含客户端要告诉服务器的很多信息,
      • 请求主体:get方式没有请求体,但有que’r’yString。post方式有请求体form data,json格式有请求体requst payload。
    • 响应包含三个部分:
      • 相应行:包括协议、响应状态码、响应状态
      • 响应头:包含服务器信息、服务器发给浏览器的信息(内容的媒体类型、编码、内容长度等)
      • 响应体:响应的实际内容(比如html页面、字符串…)

无状态

Http传输协议没有状态是说,服务端无法判断两个会话是来自同一个客户端还是不同客户端,因此引入session

session

保存作用域

服务器内部转发

服务器内部转发对客户端而言是不可见的,客户端不知道服务器内部转发是否进行,进行了几次。

1
req.getRequestDispatcher("demo07").forward(req,resp);

客户端重定向

客服端重定向,是客户端发出的多次请求,在客户端是可见的

1
resp.sendRedirect("demo07");

thymeleaf - 视图模板

在页面上展示java内存内数据的过程称为渲染(render)

保存作用域

四个级别保存作用域:

  • page :页面级别,淘汰不用
  • reqeust:一次请求,客户端重定向后失效、服务器内部转发有效
  • session:一次会话,session未失效前都有效
  • application:一次应用程序范围内有效

MVC优化的Servlet

增删改查各要给Servlet,当服务器内容很多时,会有各种各种的Servlet,繁多而杂乱,不仅开发难,维护也难。

MVC:

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

  • 视图层:用于数据展示、用户交互
  • 控制层:接受客户端的请求,具体的业务逻辑还要借助模型组件来完成
  • 模型层:模型分为很多种,有比较简单的pojo/vo(value object),有业务模型组件,有数据库访问组件
    1. pojo/vo:值对象
    2. DAO:数据访问对象
    3. BO:业务对象

区分业务对象和数据访问对象:

  1. DAO中的方法都是单精度方法:一个方法只考虑一个操作,比如添加、查询
  2. BO中的方法属于业务方法,也就是说注册这个方法属于业务方法,也就是说注册这个业务功能需要多个DAO的组合调用,从而完成注册功能

IOC

耦合/依赖

依赖指xxx离不开xxx

在软件系统中,层与层之间是存在依赖的,我们亦称之为耦合。

系统架构或者是设计的一个原则是:高内聚低耦合

层内部的组成应该是高度聚合的,而层与层之间的关系应该是低耦合的,最理想的情况是0耦合。

IOC:控制反转/ DI:依赖注入

Filter过滤器

在servlet前的一层可定义过滤器。可定义放行前代码、放行后代码。

可定义多个过滤器,注解过滤器顺序按照命名字典序执行,xml配置的过滤器按照配置前后执行顺序。

1
2
3
4
5
init();

doFilter();

destory();

事务(过滤器的一个典型应用)

假如事务管理的操作写在dao层,一个service对应多个dao,dao的部分成功和失败,无法作为service判断成功或者失败的依据。

service是一个整体:事务管理不能以DAO层的单精度方法为单位,而应该以业务层的方法为单位。

实现原理:

在过滤器中

1
2
3
4
5
try{
放行();
}catch(){
回滚;
}

实现难题:多个dao可能对应多个Connect,多个DAO应该用同一个Connect达到事务管理的目的。所以用ThreadLocal.set(conn), get(),获取同一个Connect,

ThreadLocal

注意:

DAO层catch Exception后,会导致service层获取不到错误,故DAO层不能catch,只能throw错误。

监听器

1)ServletContextListener: 监听ServletContext对象的创建和销毁过程


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!