JavaWeb入门学习

JavaWeb入门学习

此次总结 思路来源于黑马程序的JavaWeb

1.数据库

1.1 JDBC入门使用

基本流程

image-20211123095940223

驱动jar下载链接:

https://downloads.mysql.com/archives/c-j/

实验操作

代码部分

package com.itheima.jdbc;

/*
/ JDBC 入门学习
 */
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1. 注册驱动(可注释,因为在高版本中,mysql的jar包会自动导入)
        Class.forName("com.mysql.jdbc.Driver");

        //2. 获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/testdb";
        String username = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3. 定义sql语句
        String sql = "UPDATE userinfo set sex='男' WHERE name='张三'";

        //4. 获取执行sql的对象Statement
        Statement stmt = conn.createStatement();

        //5. 执行sql
        int count = stmt.executeUpdate(sql);

        //6. 处理结果
        System.out.println(count);

        //7. 释放资源
        stmt.close();
        conn.close();



    }
}

image-20211123100234944

初始时, 性别为男

image-20211123100322900

操作完数据库后变成了女

image-20211123100358766

1.2 Mybatis

Mybatis概念
  • MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发
  • MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github
  • 官网:https://mybatis.org/mybatis-3/zh/index.html
Mybatis 优化
  • 硬编码可以配置到配置文件
  • 操作繁琐的地方mybatis都自动完成

如图所示

image-20220303112008696

使用方法

image-20220303151715005

①导入依赖
<dependencies>
    <!--mybatis 依赖-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.5</version>
    </dependency>

    <!--mysql 驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.46</version>
    </dependency>
</dependencies>
②写入mybatis配置文件

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <typeAliases>
        <package name="com.mrfan.pojo"/>
    </typeAliases>
    
    <!--
    environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment
    -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库连接信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>

        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--数据库连接信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--加载sql映射文件-->
       <!-- <mapper resource="com/mrfan/mapper/UserMapper.xml"/>-->

        <!--Mapper代理方式-->
        <package name="com.mrfan.mapper"/>

    </mappers>


</configuration>
③编写接口方法

com.mrfan.mapper 包写创建名为 UserMapper 的接口。并在该接口中定义 List<Brand> selectAll() 方法。

package com.mrfan.mapper;
import com.mrfan.pojo.User;
import java.util.List;

public interface UserMapper {
    List<User> selectAll();
}
④编写 SQL 映射文件

编写 SQL 映射文件 --> 统一管理sql语句,解决硬编码问题

在模块的 resources 目录下创建映射配置文件 UserMapper.xml,内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    namespace:名称空间
-->

<mapper namespace="com.mrfan.mapper.UserMapper">
    <select id="selectAll" resultType="com.mrfan.pojo.User">
        select * from tb_user;
    </select>
</mapper>

注意: 在创建UserMapper.xml时,应与接口方法保持在同一个文件下

⑤编码

com.mrfan.pojo 包下创建 User类

package com.mrfan.pojo;


public class User {
    private Integer id;
    private String username;
    private String password;
    private String gender;
    private String addr;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", addr='" + addr + '\'' +
                '}';
    }
}

com.mrfan 包下编写 MybatisDemo 测试类

package com.mrfan;


import com.mrfan.mapper.UserMapper;
import com.mrfan.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MyBatisDemo {
    public static void main(String[] args) throws IOException {
        //1. 加载mybatis的核心配置文件,获取 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2. 获取SqlSession对象,用它来执行sql
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3. 执行sql
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.selectAll();
        
        //4. 释放资源
        sqlSession.close();
    }
}

小技巧
resultMap标签

image-20220303153256645

当数据库的列与Java命名的对象不同时,可以在SQL映射文件中定义 resultMap 标签

<resultMap id="brandResultMap" type="brand">
    <!--
            id:完成主键字段的映射
                column:表的列名
                property:实体类的属性名
            result:完成一般字段的映射
                column:表的列名
                property:实体类的属性名
        -->
    <result column="brand_name" property="brandName"/>
    <result column="company_name" property="companyName"/>
</resultMap>



<select id="selectAll" resultMap="brandResultMap">
    select *
    from tb_brand;
</select>
SQL注解

不想编写SQL配置文件 可以在Mapper.java文件中如下:

public interface BrandMapper {
    /*
    * 查询所有
     */
    @Select("select * from tb_brand")
//    @ResultMap("brandResultMap")
    List<Brand> selectAll();

    @Insert("insert into tb_brand values(null,#{brandName},#{companyName},#{ordered},#{description},#{status}")
    void add(Brand brand);
}

封装sqlSessionFactory对象

起到每次启用 只调用同一个对象 不会重复声明的作用

SqlSessionFactoryUtils.java

package com.mrfan.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionFactoryUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        //静态代码块会随着类的加载而自动执行,且只执行一次
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }
}

UserService.java

package com.mrfan.service;

import com.mrfan.mapper.UserMapper;
import com.mrfan.pojo.User;
import com.mrfan.util.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class UserService {
    SqlSessionFactory factory = SqlSessionFactoryUtils.getSqlSessionFactory();

    public List<User> selectAll() {
        //调用UserMapper.selectAll()

        //2. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //3. 获取BrandMapper
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        //4. 调用方法
        List<User> users = mapper.selectAll();

        sqlSession.close();

        return users;
    }

}

2.部署javaweb环境

Maven简介

Maven是专门用于管理和构建Java项目的工具,它的主要功能有:

  • 提供了一套标准化的项目结构
  • 提供了一套标准化的构建流程(编译,测试,打包,发布……)
  • 提供了一套依赖管理机制

Maven提供了一套标准化的项目结构,所有的IDE使用Maven构建的项目完全一样,所以IDE创建的Maven项目可以通用。如下图就是Maven构建的项目结构。

image-20220303111030171

2.1 JavaWeb项目结构

Web项目的结构分为:开发中的项目和开发完可以部署的Web项目,这两种项目的结构是不一样的,我们一个个来介绍下:

  • Maven Web项目结构: 开发中的项目

image-20220301153641219

  • 开发完成部署的Web项目

image-20220301153800214

  • 开发项目通过执行Maven打包命令package,可以获取到部署的Web项目目录
  • 编译后的Java字节码文件和resources的资源文件,会被放到WEB-INF下的classes目录下
  • pom.xml中依赖坐标对应的jar包,会被放入WEB-INF下的lib目录下

2.2 Maven创建Web项目

介绍完Maven Web的项目结构后,接下来使用Maven来创建Web项目

具体的步骤包含:

1.创建Maven项目

image-20220301154451150

2.选择使用Web项目骨架

image-20220301154537651

3.输入Maven项目坐标创建项目

image-20220301154726996

4.确认Maven相关的配置信息后,完成项目创建

image-20220301154816356

5.删除pom.xml中多余内容

只留下面的这些内容(结构大概一致即可),注意打包方式 jar和war的区别

image-20220301155029082

6.补齐Maven Web项目缺失的目录结构

image-20220301155231204

3.IDEA使用Tomcat

  • Maven Web项目创建成功后,通过Maven的package命令可以将项目打包成war包,将war文件拷贝到Tomcat的webapps目录下,启动Tomcat就可以将项目部署成功,然后通过浏览器进行访问即可。
  • 然而我们在开发的过程中,项目中的内容会经常发生变化,如果按照上面这种方式来部署测试,是非常不方便的
  • 如何在IDEA中能快速使用Tomcat呢?

在IDEA中集成使用Tomcat有两种方式,分别是集成本地TomcatTomcat Maven插件

3.1 集成本地Tomcat

目标: 将刚才本地安装好的Tomcat8集成到IDEA中,完成项目部署,具体的实现步骤

1.打开添加本地Tomcat的面板

image-20220301160223253

2.指定本地Tomcat的具体路径

image-20220301160408330

3.修改Tomcat的名称,此步骤可以不改,只是让名字看起来更有意义,HTTP port中的端口也可以进行修改

image-20220301160452852

4.将开发项目部署项目到Tomcat中

image-20220301160857800

扩展内容: xxx.war和 xxx.war exploded这两种部署项目模式的区别?

  • war模式是将WEB工程打成war包,把war包发布到Tomcat服务器上

  • war exploded模式是将WEB工程以当前文件夹的位置关系发布到Tomcat服务器上

  • war模式部署成功后,Tomcat的webapps目录下会有部署的项目内容

  • war exploded模式部署成功后,Tomcat的webapps目录下没有,而使用的是项目的target目录下的内容进行部署

  • 建议大家都选war模式进行部署,更符合项目部署的实际情况

5.部署成功后,就可以启动项目

image-20220301161054824

3.2Tomcat Maven插件

在IDEA中使用本地Tomcat进行项目部署,相对来说步骤比较繁琐,所以我们需要一种更简便的方式来替换它,那就是直接使用Maven中的Tomcat插件来部署项目,具体的实现步骤,只需要两步,分别是:

  1. 在pom.xml中添加Tomcat插件
<build>
    <plugins>
    	<!--Tomcat插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
        </plugin>
    </plugins>
</build>

image-20220301161415711

2.使用Maven Helper插件快速启动项目,选中项目,右键–>Run Maven --> tomcat7:run

image-20220301161439711

注意:

  • 如果选中项目并右键点击后,看不到Run Maven和Debug Maven,这个时候就需要在IDEA中下载Maven Helper插件,具体的操作方式为: File --> Settings --> Plugins --> Maven Helper —> Install,安装完后按照提示重启IDEA,就可以看到了。
  • Maven Tomcat插件目前只有Tomcat7版本,没有更高的版本可以使用
  • 使用Maven Tomcat插件,要想修改Tomcat的端口和访问路径,可以直接修改pom.xml
<build>
    <plugins>
    	<!--Tomcat插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
            	<port>80</port><!--访问端口号 -->
                <!--项目访问路径
					未配置访问路径: http://localhost:80/tomcat-demo2/a.html
					配置/后访问路径: http://localhost:80/a.html
					如果配置成 /hello,访问路径会变成什么?
						答案: http://localhost:80/hello/a.html
				-->
                <path>/</path>
            </configuration>
        </plugin>
    </plugins>
</build>

小结

通过这一节的学习,大家要掌握在IDEA中使用Tomcat的两种方式,集成本地Tomcat和使用Maven的Tomcat插件。后者更简单,推荐大家使用,但是如果对于Tomcat的版本有比较高的要求,要在Tomcat7以上,这个时候就只能用前者了。

4.url访问途径

①使用web.xml

在web.xml中写入语句如下:

<!--
    Servlet 全类名
  -->
  <servlet>
    <servlet-name>demo13</servlet-name>
    <servlet-class>com.itheima.web.ServletDemo13</servlet-class>
  </servlet>

  <!--
      Servlet 访问路劲
   -->
  <servlet-mapping>
    <servlet-name>demo13</servlet-name>
    <url-pattern>/demo13</url-pattern>
  </servlet-mapping>

url-pattern代表访问的url路径

image-20220110112434260

②使用注解

在继承HttpServlet或者实现Servlet的类前加上注解如下:

@WebServlet(urlPatterns={"/"})
/*
* 精确匹配 :
*   如 urlPatterns={"/user/select"}
 * 目录匹配 :
 *   如 urlPatterns={"/user/*"}
 * 扩展名匹配 :
 *   如 urlPatterns={"*.do"}
 * 任意匹配 :
 *   如 urlPatterns={"/"}
 * 任意匹配 :
 *   如 urlPatterns={"/*"}
 */

image-20220110112842657

5.JSP

JSP 本质上就是一个 Servlet。==接下来我们聊聊访问jsp时的流程

image-20220303162332011

  1. 浏览器第一次访问 hello.jsp 页面
  2. tomcat 会将 hello.jsp 转换为名为 hello_jsp.java 的一个 Servlet
  3. tomcat 再将转换的 servlet 编译成字节码文件 hello_jsp.class
  4. tomcat 会执行该字节码文件,向外提供服务

5.1 JSP 脚本分类

JSP 脚本有如下三个分类:

  • <%…%>:内容会直接放到_jspService()方法之中
  • <%=…%>:内容会放到out.print()中,作为out.print()的参数
  • <%!…%>:内容会放到_jspService()方法之外,被类直接包含

JSP导包方式如 List:

<%@ page import="java.util.List" %>

6. EL 表达式

6.1 概述

EL(全称Expression Language )表达式语言,用于简化 JSP 页面内的 Java 代码。

EL 表达式的主要作用是 获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。

而 EL 表达式的语法也比较简单,== e x p r e s s i o n = = 。例如: {expression}== 。例如: expression==。例如:{brands} 就是获取域中存储的 key 为 brands 的数据。

import com.mrfan.pojo.User;

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

@WebServlet("/mrfan")
public class ServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.读取数据
        User user = new User(1, "mrfan", "123", "男", "广东");

        //2. 存储到request域中
        req.setAttribute("user", user);

        //3. 转发到 el-demo.jsp
        req.getRequestDispatcher("/el-demo.jsp").forward(req,resp);
    }

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

el-demo.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <span>读取域中值<br>${user}</span>

</body>
</html>

image-20220303164256476

7. JSTL标签

我们只对两个最常用的标签进行讲解,<c:forEach> 标签和 <c:if> 标签。

JSTL 使用也是比较简单的,分为如下步骤:

  • 导入坐标

    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>taglibs</groupId>
        <artifactId>standard</artifactId>
        <version>1.1.2</version>
    </dependency>
    
  • 在JSP页面上引入JSTL标签库

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
    
  • 使用标签

7.1 if 标签

<c:if>:相当于 if 判断

  • 属性:test,用于定义条件表达式
<c:if test="${flag == 1}">
    男
</c:if>
<c:if test="${flag == 2}">
    女
</c:if>

代码演示:

通过值去变更性别的选择

jstl-f.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <c:if test="${status == 1}">
        <input type="radio" name="status" value="1" checked>男
        <input type="radio" name="status" value="0">女
    </c:if>
    <c:if test="${status == 0}">
        <input type="radio" name="status" value="1">男
        <input type="radio" name="status" value="0" checked>女
    </c:if>
</body>
</html>

ServletDemo2.java

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

@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //2. 存储到request域中
        req.setAttribute("status", 0);

        //3. 转发到 el-demo.jsp
        req.getRequestDispatcher("/jstl-if.jsp").forward(req,resp);
    }

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

image-20220303185631003

7.2 forEach 标签

<c:forEach>:相当于 for 循环。java中有增强for循环和普通for循环,JSTL 中的 <c:forEach> 也有两种用法

7.2.1 用法一

类似于 Java 中的增强for循环。涉及到的 <c:forEach> 中的属性如下

  • items:被遍历的容器

  • var:遍历产生的临时变量

  • varStatus:遍历状态对象

如下代码,是从域对象中获取名为 users 数据,该数据是一个集合;遍历遍历,并给该集合中的每一个元素起名为 user,是 Brand对象。在循环里面使用 EL表达式获取每一个User对象的属性值

jstl-f.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<table border="1" cellspacing="0" >
    <tr>
        <th>学号</th>
        <th>账号</th>
        <th>密码</th>
        <th>性别</th>
        <th>地区</th>
    </tr>
    <c:forEach items="${users}" var="user">
        <tr align="center">
            <td>${user.id}</td>
            <td>${user.username}</td>
            <td>${user.password}</td>
            <td>${user.gender}</td>
            <td>${user.addr}</td>
        </tr>
    </c:forEach>
</table>


</body>
</html>

ServletDemo3.java

import com.mrfan.pojo.User;

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

@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<User> users = new ArrayList<>();
        User u1 = new User(1, "mrfan1", "123", "男", "广东");
        User u2 = new User(2, "mrfan2", "1234", "男", "广东");
        User u3 = new User(3, "mrfan3", "1235", "男", "广东");
        users.add(u1);
        users.add(u2);
        users.add(u3);

        //2. 存储到request域中
        req.setAttribute("users", users);

        //3. 转发到 el-demo.jsp
        req.getRequestDispatcher("/jstl-if.jsp").forward(req,resp);
    }

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

image-20220303191020520

7.2.2 用法二

类似于 Java 中的普通for循环。涉及到的 <c:forEach> 中的属性如下

  • begin:开始数

  • end:结束数

  • step:步长

实例代码:

从0循环到10,变量名是 i ,每次自增1

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<c:forEach begin="0" end="10" step="1" var="i">
    ${i} <br>
</c:forEach>
</body>
</html>

image-20220303191338712

8. MVC模式和三层架构

MVC 模式和三层架构是一些理论的知识,将来我们使用了它们进行代码开发会让我们代码维护性和扩展性更好。

8.1 MVC模式

MVC 是一种分层开发的模式,其中:

  • M:Model,业务模型,处理业务

  • V:View,视图,界面展示

  • C:Controller,控制器,处理请求,调用模型和视图

image-20220303194022809

控制器(serlvlet)用来接收浏览器发送过来的请求,控制器调用模型(JavaBean)来获取数据,比如从数据库查询数据;控制器获取到数据后再交由视图(JSP)进行数据展示。

MVC 好处:

  • 职责单一,互不影响。每个角色做它自己的事,各司其职。

  • 有利于分工协作。

  • 有利于组件重用

8.2 三层架构

三层架构是将我们的项目分成了三个层面,分别是 表现层业务逻辑层数据访问层

image-20220303194141078

  • 数据访问层:对数据库的CRUD基本操作
  • 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如 注册业务功能 ,我们会先调用 数据访问层selectByName() 方法判断该用户名是否存在,如果不存在再调用 数据访问层insert() 方法进行数据的添加操作
  • 表现层:接收请求,封装数据,调用业务逻辑层,响应数据

而整个流程是,浏览器发送请求,表现层的Servlet接收请求并调用业务逻辑层的方法进行业务逻辑处理,而业务逻辑层方法调用数据访问层方法进行数据的操作,依次返回到serlvet,然后servlet将数据交由 JSP 进行展示。

三层架构的每一层都有特有的包名称:

  • 表现层: com.mrfan.controller 或者 com.mrfan.web
  • 业务逻辑层:com.mrfan.service
  • 数据访问层:com.mrfan.dao 或者 com.mrfan.mapper

后期我们还会学习一些框架,不同的框架是对不同层进行封装的

image-20220303194316966

8.3 MVC 和 三层架构

通过 MVC 和 三层架构 的学习,有些人肯定混淆了。那他们有什么区别和联系?

image-20220303194353419

如上图上半部分是 MVC 模式,上图下半部分是三层架构。 MVC 模式 中的 C(控制器)和 V(视图)就是 三层架构 中的表现层,而 MVC 模式 中的 M(模型)就是 三层架构 中的 业务逻辑层 和 数据访问层。

可以将 MVC 模式 理解成是一个大的概念,而 三层架构 是对 MVC 模式 实现架构的思想。 那么我们以后按照要求将不同层的代码写在不同的包下,每一层里功能职责做到单一,将来如果将表现层的技术换掉,而业务逻辑层和数据访问层的代码不需要发生变化。

9.Filter

9.1 Filter概述

Filter 表示过滤器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。Servlet 我们之前都已经学习过了,Filter和Listener 我们今天都会进行学习。

过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。

9.2 用法

进行 Filter 开发分成以下三步实现

  • 定义类,实现 Filter接口,并重写其所有方法

image-20220303195709423

  • 配置Filter拦截资源的路径:在类上定义 @WebFilter 注解。而注解的 value 属性值 /* 表示拦截所有的资源

image-20220303200508352

  • 在doFilter方法中输出一句话,并放行

    image-20220303200619502

​ 在进行拦截前先会执行doFilter()方法前的代码, 直到放行后,响应完毕后会继续执行doFilter()后面的代码

9.3 Filter拦截路径配置

拦截路径表示 Filter 会对请求的哪些资源进行拦截,使用 @WebFilter 注解进行配置。如:@WebFilter("拦截路径")

拦截路径有如下四种配置方式:

  • 拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截
  • 目录拦截:/user/*:访问/user下的所有资源,都会被拦截
  • 后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截
  • 拦截所有:/*:访问所有资源,都会被拦截

通过上面拦截路径的学习,大家会发现拦截路径的配置方式和 Servlet 的请求资源路径配置方式一样,但是表示的含义不同。

10. Listener

10.1 概述

  • Listener 表示监听器,是 JavaWeb 三大组件(Servlet、Filter、Listener)之一。

  • 监听器可以监听就是在 applicationsessionrequest 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。

    request 和 session 我们学习过。而 applicationServletContext 类型的对象。

    ServletContext 代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。

10.2 分类

JavaWeb 提供了8个监听器:

image-20220303201340184

这里面只有 ServletContextListener 这个监听器后期我们会接触到,ServletContextListener 是用来监听 ServletContext 对象的创建和销毁。

ServletContextListener 接口中有以下两个方法

  • void contextInitialized(ServletContextEvent sce)ServletContext 对象被创建了会自动执行的方法
  • void contextDestroyed(ServletContextEvent sce)ServletContext 对象被销毁时会自动执行的方法

10.3 代码演示

我们只演示一下 ServletContextListener 监听器

  • 定义一个类,实现ServletContextListener 接口
  • 重写所有的抽象方法
  • 使用 @WebListener 进行配置

代码如下:

@WebListener
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //加载资源
        System.out.println("ContextLoaderListener...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //释放资源
    }
}

启动服务器,就可以在启动的日志信息中看到 contextInitialized() 方法输出的内容,同时也说明了 ServletContext 对象在服务器启动的时候被创建了。

11. Ajax

11.1 概述

AJAX (Asynchronous JavaScript And XML):异步的 JavaScript 和 XML。

JavaScriptXMLJavaScript 表明该技术和前端相关;XML 是指以此进行数据交换。

11.1.1 作用

AJAX 作用有以下两方面:

  1. 与服务器进行数据交换:通过AJAX可以给服务器发送请求,服务器将数据直接响应回给浏览器。
  2. 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验,等等…
11.1.2 同步和异步

知道了局部刷新后,接下来我们再聊聊同步和异步:

  • 同步发送请求过程如下

image-20220305090227050

浏览器页面在发送请求给服务器,在服务器处理请求的过程中,浏览器页面不能做其他的操作。只能等到服务器响应结束后才能,浏览器页面才能继续做其他的操作。

  • 异步发送请求过程如下

image-20220305090243326

浏览器页面发送请求给服务器,在服务器处理请求的过程中,浏览器页面还可以做其他的操作。

11.2 代码演示

服务端

在部署的javaweb环境下添加一个servlet类

@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 响应数据
        response.getWriter().write("hello ajax!!!");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}
客户端

webapp 下创建名为 ajax.html 的页面,在该页面书写 ajax 代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script>
      var xhttp;
      if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
      } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
      }
      //建立连接
      xhttp.open("GET", "http://localhost/ajaxServlet");
      //发送请求
      xhttp.send();

      //3. 获取响应
      xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
              alert(this.responseText);
          }
      };
    </script>
</body>
</html>
ajax代码理解
  • 创建核心对象,不同的浏览器创建的对象是不同的
 var xhttp;
if (window.XMLHttpRequest) {
    xhttp = new XMLHttpRequest();
} else {
    // code for IE6, IE5
    xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
  • 发送请求
//建立连接
xhttp.open("GET", "http://localhost/ajaxServlet");
//发送请求
xhttp.send();
  • 获取响应
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        // 通过 this.responseText 可以获取到服务端响应的数据
        alert(this.responseText);
    }
};

image-20220305091324828

11.3 应用

演示一个注册页面 输入已注册过的账号出现提示

服务端

AjaxServlet.java

import com.mrfan.pojo.User;

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

@WebServlet("/ajaxServlet")
public class AjaxServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 响应数据
        String _username = request.getParameter("username");
        //2. 解决URL获取的参数乱码
        String username = new String(_username.getBytes("ISO-8859-1"),"UTF-8");

        //3. 模拟数据库的读取操作
        List<String> usernames = new ArrayList();
        usernames.add("张三");
        usernames.add("李四");
        usernames.add("王五");
        
        //4,获取的数据与已存在的进行匹配
        for (String u: usernames) {
            if(u.equals(username)){
                response.getWriter().write("true");
                return;
            }
        }
        response.getWriter().write("false");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}
客户端

ajax.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <form id="reg-form" action="#" method="get">
        <label>账号: <input type=text id=usernmae placeholder="请输入账号"></label><br>
        <p id="username_err" style="display: none">该账号已经注册<p/>
        <label>密码: <input type=password id=password placeholder="请输入密码"></label><br><br>
        <input type="button" value="注册" >
    </form>

</head>
<body>
    <script>
        document.getElementById("usernmae").onblur = function(){
            //2. 发送ajax请求
            // 获取用户名的值
            var username = this.value;
            var xhttp;
            if (window.XMLHttpRequest) {
            xhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        //建立连接
        xhttp.open("GET", "http://localhost/ajaxServlet?username="+username);
        //发送请求
        xhttp.send();

        //3. 获取响应
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                //4. 存在则显示已经注册过
                if (this.responseText == "true") {
                    document.getElementById("username_err").style.display = ""
                }else{
                    document.getElementById("username_err").style.display = "none"
                }
            }
        };
        }

    </script>
</body>
</html>

image-20220305100605540

image-20220305100620971

12. axios

Axios 对原生的AJAX进行封装,简化书写。

Axios官网是:https://www.axios-http.cn

12.1 基本使用

axios 使用是比较简单的,分为以下两步:

  • 引入 axios 的 js 文件
<script src="js/axios-0.18.0.js"></script>
  • 使用axios 发送请求,并获取响应结果

    • 发送 get 请求

      axios({
          method:"get",
          url:"http://localhost/axioservlet?username=mrfan"
      }).then(function (resp){
          alert(resp.data);
      })
      
    • 发送 post 请求

      axios({
          method:"post",
          url:"http://localhost/axiosservlet",
          data:"username=mrfan"
      }).then(function (resp){
          alert(resp.data);
      });
      

axios() 是用来发送异步请求的,小括号中使用 js 对象传递请求相关的参数:

  • method 属性:用来设置请求方式的。取值为 get 或者 post
  • url 属性:用来书写请求的资源路径。如果是 get 请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2
  • data 属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为 data 属性的值。

then() 需要传递一个匿名函数。我们将 then() 中传递的匿名函数称为 回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。

12.2 代码演示

12.2.1 后端实现

定义一个用于接收请求的servlet,代码如下:

AxiosServlet.java

@WebServlet("/axioServlet")
public class AxiosServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get...");
        //1. 接收请求参数
        String username = request.getParameter("username");
        System.out.println(username);
        //2. 响应数据
        response.getWriter().write("hello Axios~");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post...");
        this.doGet(request, response);
    }
}
12.2.2 前端实现

axios.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<script src="js/axios-0.18.0.js"></script>
<script>
    //1. get
    /* axios({
         method:"get",
         url:"http://localhost/axioServlet?username=zhangsan"
     }).then(function (resp) {
         alert(resp.data);
     })*/

    //2. post  在js中{} 表示一个js对象,而这个js对象中有三个属性
    axios({
        method:"post",
        url:"http://localhost/axioServlet",
        data:"username=zhangsan"
    }).then(function (resp) {
        alert(resp.data);
    })
</script>
</body>
</html>

image-20220305103238109

12.3 请求方法别名

为了方便起见, Axios 已经为所有支持的请求方法提供了别名。如下:

  • get 请求 : axios.get(url[,config])
  • delete 请求 : axios.delete(url[,config])
  • head 请求 : axios.head(url[,config])
  • options 请求 : axios.option(url[,config])
  • post 请求:axios.post(url[,data[,config])
  • put 请求:axios.put(url[,data[,config])
  • patch 请求:axios.patch(url[,data[,config])

而我们只关注 get 请求和 post 请求。

入门案例中的 get 请求代码可以改为如下:

axios.get("http://localhost/axioServlet?username=zhangsan").then(function (resp) {
    alert(resp.data);
});

入门案例中的 post 请求代码可以改为如下:

axios.post("http://localhost/axioServlet","username=zhangsan").then(function (resp) {
    alert(resp.data);
})

13. JSON

13.1 概述

概念:JavaScript Object Notation。JavaScript 对象表示法.

如下是 JavaScript 对象的定义格式:

{
	name:"mrfan",
	age:18,
	city:"广东"
}

接下来我们再看看 JSON 的格式:

{
	"name":"mrfan",
	"age":18,
	"city":"广东"
}

通过上面 js 对象格式和 json 格式进行对比,发现两个格式特别像。只不过 js 对象中的属性名可以使用引号(可以是单引号,也可以是双引号);而 json 格式中的键要求必须使用双引号括起来,这是 json 格式的规定。json 格式的数据有什么作用呢?

作用:由于其语法格式简单,层次结构鲜明,现多用于作为数据载体,在网络中进行数据传输。

13.2 JSON 基础语法

13.2.1 定义格式

JSON 本质就是一个字符串,但是该字符串内容是有一定的格式要求的。 定义格式如下:

var 变量名 = '{"key":value,"key":value,...}';

JSON 串的键要求必须使用双引号括起来,而值根据要表示的类型确定。value 的数据类型分为如下

  • 数字(整数或浮点数)
  • 字符串(使用双引号括起来)
  • 逻辑值(true或者false)
  • 数组(在方括号中)
  • 对象(在花括号中)
  • null

示例:

var jsonStr = '{"name":"zhangsan","age":23,"addr":["北京","上海","西安"]}'

13.3 JSON与JS相互转换

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script>
        //JSON字符串
        let _jsonStr = '{"name":"mrfan","age":18,"addr":"广东"}';

        //将JSON字符串转为JS对象
        let jsObject = JSON.parse(_jsonStr);
        //获取JSON字符串中name的值
        alert(jsObject.name);

        //将JS对象转为JSON字符串
        let jsonStr = JSON.stringify(jsObject)
        alert(jsonStr)
    </script>
</body>
</html>
  • parse(str) :将 JSON串转换为 js 对象。使用方式是: var jsObject = JSON.parse(jsonStr);
  • stringify(obj) :将 js 对象转换为 JSON 串。使用方式是:`var jsonStr = JSON.stringify(jsObject)

一个 js 对象,我们就可以通过 js对象.属性名 的方式来获取数据。

13.3.1 发送异步请求携带参数

如果要携带复杂的数据时都会以 JSON 格式进行传递,如下

axios({
    method:"post",
    url:"http://localhost/axioServlet",
    data:"username=zhangsan"
}).then(function (resp) {
    alert(resp.data);
})

请求参数不可能由我们自己拼接字符串吧?肯定不用,可以提前定义一个 js 对象,用来封装需要提交的参数,然后使用 JSON.stringify(js对象) 转换为 JSON 串,再将该 JSON 串作为 axiosdata 属性值进行请求参数的提交。如下:

var jsObject = {name:"张三"};
axios({
    method:"post",
    url:"http://localhost/axioServlet",
    data: JSON.stringify(jsObject)
}).then(function (resp) {
    alert(resp.data);
})

axios 是一个很强大的工具。我们只需要将需要提交的参数封装成 js 对象,并将该 js 对象作为 axiosdata 属性值进行,它会自动将 js 对象转换为 JSON 串进行提交。如下:

var jsObject = {name:"张三"};

axios({
    method:"post",
    url:"http://localhost/axioServlet",
    data:jsObject  //这里 axios 会将该js对象转换为 json 串的
}).then(function (resp) {
    alert(resp.data);
})
  • axios 会自动对 js 对象和 JSON 串进行想换转换。
  • 发送异步请求时,如果请求参数是 JSON 格式,那请求方式必须是 POST。因为 JSON 串需要放在请求体中。

13.4 JSON串和Java对象的相互转换

​ 以 json 格式的数据进行前后端交互。前端发送请求时,如果是复杂的数据就会以 json 提交给后端;而后端如果需要响应一些复杂的数据时,也需要以 json 格式将数据响应回给浏览器。

在后端我们就需要重点学习以下两部分操作:

  • 请求数据:JSON字符串转为Java对象
  • 响应数据:Java对象转为JSON字符串

接下来给大家介绍一套 API,可以实现上面两部分操作。这套 API 就是 Fastjson

13.4.1 Fastjson 概述

Fastjson 是阿里巴巴提供的一个Java语言编写的高性能功能完善的 JSON 库,是目前Java语言中最快的 JSON 库,可以实现 Java 对象和 JSON 字符串的相互转换。

13.4.2 Fastjson 使用

Fastjson 使用也是比较简单的,分为以下三步完成

  1. 导入坐标

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.62</version>
    </dependency>
    
  2. Java对象转JSON

    String jsonStr = JSON.toJSONString(obj);
    

    将 Java 对象转换为 JSON 串,只需要使用 Fastjson 提供的 JSON 类中的 toJSONString() 静态方法即可。

  3. JSON字符串转Java对象

    User user = JSON.parseObject(jsonStr, User.class);
    

    将 json 转换为 Java 对象,只需要使用 Fastjson 提供的 JSON 类中的 parseObject() 静态方法即可。

13.4.3 应用
13.4.3.1 查询所有数据库中User用户信息
基本结构:

image-20220305155436379

后端实现

将 json 数据响应回给浏览器。这里一定要设置响应数据的类型及字符集 response.setContentType("text/json;charset=utf-8");

import com.alibaba.fastjson.JSON;
import com.mrfan.pojo.User;
import com.mrfan.service.UserService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet("/fastjsonServlet")
public class fastjsonServlet extends HttpServlet {
    UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<User> users = service.selectAll();

        String jsonStr = JSON.toJSONString(users);
        response.setContentType("text/json;charset=utf-8");
        //2. 响应数据
        response.getWriter().write(jsonStr);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post...");
        this.doGet(request, response);
    }
}
前端实现

fastjson.jsp

<%--
  Created by IntelliJ IDEA.
  User: MrFan
  Date: 2022/3/5
  Time: 15:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <table border="1px" cellspacing="0" style="width:800px;" id="tableDate">

    </table>
    <script src="js/axios-0.18.0.js"></script>
    <script>

        window.onload = function(){
            axios({
                method:"get",
                url:"http://localhost/fastjsonServlet"
            }).then(function(resp){
                var tableHtml = "<tr>\n"+
                    "     <th>序号</th>\n"+
                    " <th>账号</th>\n"+
                    " <th>密码</th>\n"+
                    " <th>性别</th>\n"+
                    " <th>地址</th>\n"+
                    "</tr>"
                for(let i=0;i<resp.data.length;i++){
                    //返回的resp.data是一个对象,可以通过索引去取值
                    let user = resp.data[i];
                    tableHtml += "<tr>\n"+
                        "     <td>"+user.id+"</td>\n"+
                        " <td>"+user.username+"</td>\n"+
                        " <td>"+user.password+"+</td>\n"+
                        " <td>"+user.gender+"</td>\n"+
                        " <td>"+user.addr+"</td>\n"+
                        "</tr>";
                }
                document.getElementById("tableDate").innerHTML = tableHtml
            })

        }
    </script>
</body>
</html>

image-20220305160028928

13.4.3.2 添加用户信息
基本结构:

image-20220305165703227

前端实现

jastjson.jsp

<%--
  Created by IntelliJ IDEA.
  User: MrFan
  Date: 2022/3/5
  Time: 15:06
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <button id="add">新增用户</button><br><br>

    <table border="1px" cellspacing="0" style="width:800px;" id="tableDate">
    </table>
    <script src="js/axios-0.18.0.js"></script>
    <script>

        window.onload = function(){
            axios({
                method:"get",
                url:"http://localhost/fastjsonServlet"
            }).then(function(resp){
                var tableHtml = "<tr>\n"+
                    "     <th>序号</th>\n"+
                    " <th>账号</th>\n"+
                    " <th>密码</th>\n"+
                    " <th>性别</th>\n"+
                    " <th>地址</th>\n"+
                    "</tr>"
                console.log(resp.data)
                for(let i=0;i<resp.data.length;i++){
                    let user = resp.data[i];
                    console.log(user);
                    tableHtml += "<tr>\n"+
                        "     <td>"+user.id+"</td>\n"+
                        " <td>"+user.username+"</td>\n"+
                        " <td>"+user.password+"+</td>\n"+
                        " <td>"+user.gender+"</td>\n"+
                        " <td>"+user.addr+"</td>\n"+
                        "</tr>";
                }
                document.getElementById("tableDate").innerHTML = tableHtml
                document.getElementById("add").onclick = function(){
                    location.href = "/addUser.jsp";
                }
            })

        }
    </script>
</body>
</html>

addUser.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="reg-form"  method="post">
        <label>账号: <input type=text id=username name="username" placeholder="请输入账号"></label><br>
        <p id="username_err" style="display: none">该账号已经注册<p/>
        <label>密码: <input type=password id=password name="password" placeholder="请输入密码"></label><br><br>
        <label>性别: <input type="radio" name="gender" value="男">男
        <input type="radio" name="gender" value="女">女<br><br>
        <label>地址: <input type=text id="addr" name="addr" placeholder="请输入地址"></label><br><br>
        <input type="button" value="注册" id="btn">
    </form>
    <script src="js/axios-0.18.0.js"></script>
    <script>
        var formData = {
            username: "",
            password: "",
            gender: "",
            addr: ""
        };


        //1. 给按钮绑定单击事件
        document.getElementById("btn").onclick = function () {
            formData.username = document.getElementById("username").value;
            formData.password = document.getElementById("password").value;
            formData.addr = document.getElementById("addr").value;

            let gender =  document.getElementsByName("gender");
            for (let i = 0; i < gender.length; i++) {
                if(gender[i].checked){
                    formData.gender = gender[i].value ;
                }
            }
            console.log(formData);

            // 2. 发送ajax请求
            axios({
                method:"post",
                url:"http://localhost/addServlet",
                data:formData
        }).then(function (resp) {
                // 判断响应数据是否为 success
                if(resp.data == "success"){
                    location.href = "http://localhost/fastjson.jsp";
                }
            })
        }

    </script>
</body>
</html>
后端实现

addServlet

import com.alibaba.fastjson.JSON;
import com.mrfan.pojo.User;
import com.mrfan.service.UserService;

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

@WebServlet("/addServlet")
public class addServlet extends HttpServlet {
    UserService service = new UserService();
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收数据,request.getParameter 不能接收json的数据
       /* String brandName = request.getParameter("brandName");
        System.out.println(brandName);*/

        // 获取请求体数据
        BufferedReader br = request.getReader();
        String params = br.readLine();
        // 将JSON字符串转为Java对象
        User user = JSON.parseObject(params, User.class);
        //2. 调用service 添加
        service.add(user);

        //3. 响应成功标识
        response.getWriter().write("success");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post...");
        this.doGet(request, response);
    }
}

image-20220305165938985

14. VUE

14.1 概述

接下来我们学习一款前端的框架,就是 VUE。

Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写。

我们之前也学习过后端的框架 MybatisMybatis 是用来简化 jdbc 代码编写的;而 VUE 是前端的框架,是用来简化 JavaScript 代码编写的。我们在添加用户去获取相关字段信息,里面进行了大量的DOM操作,如下

image-20220307155752214

学习了 VUE 后,这部分代码我们就不需要再写了

基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上。之前我们是将关注点放在了 DOM 操作上;而要了解 MVVM 思想,必须先聊聊 MVC 思想,如下图就是 MVC 思想图解

image-20220307160054430

C 就是咱们 js 代码,M 就是数据,而 V 是页面上展示的内容,如下图是我们之前写的代码

image-20220307160303102

MVC 思想是没法进行双向绑定的。双向绑定是指当数据模型数据发生变化时,页面展示的会随之发生变化,而如果表单数据发生变化,绑定的模型数据也随之发生变化。接下来我们聊聊 MVVM 思想,如下图是三个组件图解

image-20220307160405075

图中的 Model 就是我们的数据,View 是视图,也就是页面标签,用户可以通过浏览器看到的内容;ModelView 是通过 ViewModel 对象进行双向绑定的,而 ViewModel 对象是 Vue 提供的。接下来让大家看一下双向绑定的效果,下图是提前准备的代码,输入框绑定了 username 模型数据,而在页面上也使用 {{}} 绑定了 username 模型数据

image-20220307161044468

通过浏览器打开该页面可以看到如下页面

image-20220307161134332

当我们在输入框中输入内容,而输入框后面随之实时的展示我们输入的内容,这就是双向绑定的效果。

14.2 快速入门

Vue 使用起来是比较简单的,总共分为如下三步:

Vue 使用起来是比较简单的,总共分为如下三步:

1.新建 HTML 页面,引入 Vue.js文件

<script src="js/vue.js"></script>

2.在JS代码区域,创建Vue核心对象,进行数据绑定

new Vue({
    el: "#app",
    data() {
        return {
            username: ""
        }
    }
});

创建 Vue 对象时,需要传递一个 js 对象,而该对象中需要如下属性:

  • el : 用来指定哪儿些标签受 Vue 管理。 该属性取值 #app 中的 app 需要是受管理的标签的id属性值
  • data :用来定义数据模型
  • methods :用来定义函数。这个我们在后面就会用到

3.编写视图

<div id="app">
    <input name="username" v-model="username" >
    {{username}}
</div>

{{}} 是 Vue 中定义的 插值表达式 ,在里面写数据模型,到时候会将该模型的数据值展示在这个位置。

整体代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input v-model="username">
    <!--插值表达式-->
    {{username}}
</div>
<script src="js/vue.js"></script>
<script>
    //1. 创建Vue核心对象
    new Vue({
        el:"#app",
        data(){  // data() 是 ECMAScript 6 版本的新的写法
            return {
                username:""
            }
        }

        /*data: function () {
            return {
                username:""
            }
        }*/
    });

</script>
</body>
</html>

14.3 Vue 指令

**指令:**HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义。例如:v-if,v-for…

常用的指令有:

指令作用
v-bind为HTML标签绑定属性值,如设置 href , css样式等
v-model在表单元素上创建双向数据绑定
v-on为HTML标签绑定事件
v-if条件性的渲染某元素,判定为true时渲染,否则不渲染
v-else
v-else-if
v-show根据条件展示某元素,区别在于切换的是display属性的值
v-for列表渲染,遍历容器的元素或者对象的属性
  • 单击事件 : 事件属性名是 onclick,而在vue中使用是 v-on:click
  • 失去焦点事件:事件属性名是 onblur,而在vue中使用时 v-on:blur
Vue指令综合入门
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <a v-bind:href="url">点击一下</a>
    <a :href="url">点击一下</a>
    <input v-model="url" placeholder="控制url模型,请输入URL地址">
    <br><hr>
    <input type="button" value="一个按钮" v-on:click="show()">
    <br><hr>
    <span v-if="count == 1">count为1</span>
    <span v-else-if="count == 0">count为0</span>
    <span v-else>count不为0也不为1</span>
    <input v-model="count" placeholder="控制count模型">
    <br><hr>
    <span v-for="(addr,i) in addrs" style="color:red">
        {{i+1}}--->{{addr}}<br>
    </span>

</div>

<script src="js/vue.js"></script>
<script>
    //1. 创建Vue核心对象
    new Vue({
        el:"#app",
        data(){
            return {
                url:"",
                count:"",
                addrs:["广东","广西","上海","北京"]
            }
        },
        methods:{
            show(){
                alert("我被点击了!!!");
            }
        }
    });
</script>
</body>
</html>

image-20220307163352071

image-20220307163418681

14.4 生命周期

生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法,这些生命周期方法也被称为钩子方法。

image-20220307163622018

下图是 Vue 官网提供的从创建 Vue 到效果 Vue 对象的整个过程及各个阶段对应的钩子函数

image-20220307163700881

看到上面的图,大家无需过多的关注这张图。这些钩子方法我们只关注 mounted 就行了。

mounted:挂载完成,Vue初始化成功,HTML页面渲染成功。

14.5 修改Dom获取的添加用户代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <form id="reg-form"  method="post">
        <label>账号: <input type=text id=username name="username" placeholder="请输入账号" v-model="user.username"></label><br>
        <p id="username_err" style="display: none">该账号已经注册<p/>
        <label>密码: <input type=password id=password name="password" placeholder="请输入密码" v-model="user.password"></label><br><br>
        <label>性别: <input type="radio" name="gender" value="男" v-model="user.gender">男
            <input type="radio" name="gender" value="女" v-model="user.gender">女<br><br>
            <label>地址: <input type=text id="addr" name="addr" placeholder="请输入地址" v-model="user.addr"></label><br><br>
            <input type="button" id="btn" @click="submitForm" value="提交">
    </form>
</div>

<script src="js/axios-0.18.0.js"></script>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data(){
            return{
                user:{}
            }
        },
        methods:{
            submitForm(){
                var _this = this;
                // 发送ajax请求
                axios({
                    method:"post",
                    url:"http://localhost/addServlet",
                    data:_this.user
                }).then(function (resp) {
                    // 判断响应数据是否为 success
                    if(resp.data == "success"){
                        location.href = "http://localhost/user.jsp";
                    }
                })
            }

        }
    })


</script>
</body>
</html>

15. Element

Element:是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页。

Element 提供了很多组件(组成网页的部件)供我们使用。

https://element.eleme.cn/#/zh-CN

15.1快速入门

  1. element-ui 文件夹直接拷贝到项目的 webapp 下。目录结构如下

image-20220314161934989

  1. 创建页面,并在页面引入Element 的css、js文件 和 Vue.js

    <script src="vue.js"></script>
    <script src="element-ui/lib/index.js"></script>
    <link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">
    
  2. .创建Vue核心对象

    Element 是基于 Vue 的,所以使用Element时必须要创建 Vue 对象

<script>
    new Vue({
        el:"#app"
    })
</script>
  1. 官网复制Element组件代码

image-20220314162327053

整体页面代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
        <el-menu-item index="1">处理中心</el-menu-item>
        <el-submenu index="2">
            <template slot="title">我的工作台</template>
            <el-menu-item index="2-1">选项1</el-menu-item>
            <el-menu-item index="2-2">选项2</el-menu-item>
            <el-menu-item index="2-3">选项3</el-menu-item>
            <el-submenu index="2-4">
                <template slot="title">选项4</template>
                <el-menu-item index="2-4-1">选项1</el-menu-item>
                <el-menu-item index="2-4-2">选项2</el-menu-item>
                <el-menu-item index="2-4-3">选项3</el-menu-item>
            </el-submenu>
        </el-submenu>
        <el-menu-item index="3" disabled>消息中心</el-menu-item>
        <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
    </el-menu>
    <div class="line"></div>
    <el-menu
            :default-active="activeIndex2"
            class="el-menu-demo"
            mode="horizontal"
            @select="handleSelect"
            background-color="#545c64"
            text-color="#fff"
            active-text-color="#ffd04b">
        <el-menu-item index="1">处理中心</el-menu-item>
        <el-submenu index="2">
            <template slot="title">我的工作台</template>
            <el-menu-item index="2-1">选项1</el-menu-item>
            <el-menu-item index="2-2">选项2</el-menu-item>
            <el-menu-item index="2-3">选项3</el-menu-item>
            <el-submenu index="2-4">
                <template slot="title">选项4</template>
                <el-menu-item index="2-4-1">选项1</el-menu-item>
                <el-menu-item index="2-4-2">选项2</el-menu-item>
                <el-menu-item index="2-4-3">选项3</el-menu-item>
            </el-submenu>
        </el-submenu>
        <el-menu-item index="3" disabled>消息中心</el-menu-item>
        <el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
    </el-menu>

    <script>
        export default {
            data() {
                return {
                    activeIndex: '1',
                    activeIndex2: '1'
                };
            },
            methods: {
                handleSelect(key, keyPath) {
                    console.log(key, keyPath);
                }
            }
        }
    </script>
</div>

<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script>
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">

<script>
    new Vue({
        el:"#app"
    })
</script>
</body>
</html>

image-20220314162520748

15.2 利用Element设计页面

利用Element查询相关用法 配合使用即可达到如下效果:

image-20220314184352368

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .el-table .warning-row {
            background: oldlace;
        }

        .el-table .success-row {
            background: #f0f9eb;
        }
    </style>
</head>
<body>
<div id="app">
    <el-form :inline="true" :model="formInline" class="demo-form-inline">
        <el-form-item label="姓名">
            <el-input v-model="formInline.user" placeholder="请填写姓名"></el-input>
        </el-form-item>
        <el-form-item label="地址">
            <el-select v-model="formInline.region" placeholder="地址选择">
                <el-option label="上海" value="shanghai"></el-option>
                <el-option label="北京" value="beijing"></el-option>
            </el-select>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
    </el-form>
    <el-button type="danger" plain  onclick="alert('批量删除')">批量删除</el-button>
    <el-button type="primary" plain @click="dialogVisible = true">新增</el-button>
    <template>
        <el-table
                ref="multipleTable"
                :data="tableData"
                style="width: 100%"
                :row-class-name="tableRowClassName"
                 @selection-change="handleSelectionChange">
            <el-table-column
                    type="selection"
                    width="55">
            </el-table-column>
            <el-table-column
                    prop="id"
                    label="学号"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="username"
                    label="姓名"
                    width="180">
            </el-table-column>
            <el-table-column
                    prop="password"
                    label="密码">
            </el-table-column>
            <el-table-column
                    prop="addr"
                    label="地址">
            </el-table-column>
            <el-table-column>
                <el-button type="success">修改</el-button>
                <el-button type="danger">删除</el-button>
            </el-table-column>
        </el-table>
    </template>
    <el-dialog
            title="提示"
            :visible.sync="dialogVisible"
            width="30%"
            :before-close="handleClose">
        <el-form ref="form" :model="adduser" label-width="80px">
            <el-form-item label="姓名">
                <el-input v-model="adduser.name"></el-input>
            </el-form-item>

            <el-form-item label="性别">
                <el-checkbox-group v-model="adduser.gender">
                    <el-checkbox label="" name="type" ></el-checkbox>
                    <el-checkbox label="" name="type"></el-checkbox>
                </el-checkbox-group>
            </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
  </span>
    </el-dialog>


    <div class="block">
        <el-pagination
                layout="prev, pager, next"
                :total="1000">
        </el-pagination>
    </div>



</div>

<script src="js/vue.js"></script>
<script src="element-ui/lib/index.js"></script>
<link rel="stylesheet" href="element-ui/lib/theme-chalk/index.css">

<script>
    new Vue({
        el:"#app",
        methods: {
            tableRowClassName({row, rowIndex}) {
                if (rowIndex === 1) {
                    return 'warning-row';
                } else if (rowIndex === 3) {
                    return 'success-row';
                }
                return '';
            },
            toggleSelection(rows) {
                if (rows) {
                    rows.forEach(row => {
                        this.$refs.multipleTable.toggleRowSelection(row);
                    });
                } else {
                    this.$refs.multipleTable.clearSelection();
                }
            },
            handleSelectionChange(val) {
                this.multipleSelection = val;
            },
            onSubmit() {
                console.log('submit!');
            },handleClose(done) {
                this.$confirm('确认关闭?')
                    .then(_ => {
                        done();
                    })
                    .catch(_ => {});
            }
        },
        data() {
            return {
                tableData: [{
                    id: '1',
                    username: 'mrfan',
                    password:"admin",
                    addr: '广东省广州市'
                }, {
                    id: '2',
                    username: 'admin',
                    password:"admin",
                    addr: '广东省广州市'
                }, {
                    id: '3',
                    username: 'zs',
                    password:"admin",
                    addr: '广东省广州市',
                }, {
                    id: '4',
                    username: 'ls',
                    password:"admin",
                    addr: '广东省广州市'
                }],
                formInline: {
                    user: '',
                    region: ''
                },
                dialogVisible: false,
                adduser : {
                    username:'',
                    gender : ''
                }
            }
        }
    })
</script>

</body>
</html>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!欢迎您对JavaWeb基础学习的兴趣。如果您是初学者,我可以为您提供一些入门的建议和学习资源。以下是一些建议: 1. Java基础知识:在学习JavaWeb之前,首先需要掌握Java的基础知识,包括面向对象编程、控制流、集合框架等。您可以通过在线教程、书籍或视频教程学习这些基础知识。 2. HTML和CSS:了解HTML和CSS是非常重要的,因为JavaWeb开发涉及到与前端页面的交互。您可以通过在线教程或相关书籍学习HTML和CSS的基础知识。 3. Servlet:Servlet是JavaWeb的核心技术之一,它用于处理HTTP请求和响应。学习Servlet可以帮助您理解JavaWeb开发的基本原理和流程。您可以通过阅读相关的文档、教程或者参考书籍来学习Servlet。 4. JSP:JSP(JavaServer Pages)是一种用于创建动态Web页面的技术。它可以帮助您将Java代码嵌入到HTML中,从而实现动态内容的生成和展示。学习JSP可以让您更高效地开发JavaWeb应用程序。 5. 数据库知识:JavaWeb应用程序通常需要与数据库进行交互,因此了解数据库的基本知识也是必要的。您可以学习关系型数据库(如MySQL)的基本概念、SQL语句的使用以及Java与数据库的连接。 6. 框架和工具:学习一些常用的JavaWeb框架和工具,例如Spring、Hibernate等,可以提高您的开发效率和代码质量。 除了以上建议,您还可以通过参加培训班、加入开发社区或者实践项目来加强自己的JavaWeb技能。希望以上建议对您有所帮助!如果您有任何进一步的问题,请随时向我提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值