概述
JavaWeb入门学习
此次总结 思路来源于黑马程序的JavaWeb
1.数据库
1.1 JDBC入门使用
基本流程
驱动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 = "728848944";
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();
}
}
初始时, 性别为男
操作完数据库后变成了女
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都自动完成
如图所示
使用方法
①导入依赖
<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标签
当数据库的列与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构建的项目结构。
2.1 JavaWeb项目结构
Web项目的结构分为:开发中的项目和开发完可以部署的Web项目,这两种项目的结构是不一样的,我们一个个来介绍下:
- Maven Web项目结构: 开发中的项目
- 开发完成部署的Web项目
- 开发项目通过执行Maven打包命令package,可以获取到部署的Web项目目录
- 编译后的Java字节码文件和resources的资源文件,会被放到WEB-INF下的classes目录下
- pom.xml中依赖坐标对应的jar包,会被放入WEB-INF下的lib目录下
2.2 Maven创建Web项目
介绍完Maven Web的项目结构后,接下来使用Maven来创建Web项目
具体的步骤包含:
1.创建Maven项目
2.选择使用Web项目骨架
3.输入Maven项目坐标创建项目
4.确认Maven相关的配置信息后,完成项目创建
5.删除pom.xml中多余内容
只留下面的这些内容(结构大概一致即可),注意打包方式 jar和war的区别
6.补齐Maven Web项目缺失的目录结构
3.IDEA使用Tomcat
- Maven Web项目创建成功后,通过Maven的package命令可以将项目打包成war包,将war文件拷贝到Tomcat的webapps目录下,启动Tomcat就可以将项目部署成功,然后通过浏览器进行访问即可。
- 然而我们在开发的过程中,项目中的内容会经常发生变化,如果按照上面这种方式来部署测试,是非常不方便的
- 如何在IDEA中能快速使用Tomcat呢?
在IDEA中集成使用Tomcat有两种方式,分别是集成本地Tomcat和Tomcat Maven插件
3.1 集成本地Tomcat
目标: 将刚才本地安装好的Tomcat8集成到IDEA中,完成项目部署,具体的实现步骤
1.打开添加本地Tomcat的面板
2.指定本地Tomcat的具体路径
3.修改Tomcat的名称,此步骤可以不改,只是让名字看起来更有意义,HTTP port中的端口也可以进行修改
4.将开发项目部署项目到Tomcat中
扩展内容: xxx.war和 xxx.war exploded这两种部署项目模式的区别?
-
war模式是将WEB工程打成war包,把war包发布到Tomcat服务器上
-
war exploded模式是将WEB工程以当前文件夹的位置关系发布到Tomcat服务器上
-
war模式部署成功后,Tomcat的webapps目录下会有部署的项目内容
-
war exploded模式部署成功后,Tomcat的webapps目录下没有,而使用的是项目的target目录下的内容进行部署
-
建议大家都选war模式进行部署,更符合项目部署的实际情况
5.部署成功后,就可以启动项目
3.2Tomcat Maven插件
在IDEA中使用本地Tomcat进行项目部署,相对来说步骤比较繁琐,所以我们需要一种更简便的方式来替换它,那就是直接使用Maven中的Tomcat插件来部署项目,具体的实现步骤,只需要两步,分别是:
- 在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>
2.使用Maven Helper插件快速启动项目,选中项目,右键–>Run Maven --> tomcat7:run
注意:
- 如果选中项目并右键点击后,看不到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路径
②使用注解
在继承HttpServlet或者实现Servlet的类前加上注解如下:
@WebServlet(urlPatterns={"/"})
/*
* 精确匹配 :
* 如 urlPatterns={"/user/select"}
* 目录匹配 :
* 如 urlPatterns={"/user/*"}
* 扩展名匹配 :
* 如 urlPatterns={"*.do"}
* 任意匹配 :
* 如 urlPatterns={"/"}
* 任意匹配 :
* 如 urlPatterns={"/*"}
*/
5.JSP
JSP 本质上就是一个 Servlet。==接下来我们聊聊访问jsp时的流程
- 浏览器第一次访问
hello.jsp
页面tomcat
会将hello.jsp
转换为名为hello_jsp.java
的一个Servlet
tomcat
再将转换的servlet
编译成字节码文件hello_jsp.class
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>
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);
}
}
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);
}
}
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>
8. MVC模式和三层架构
MVC 模式和三层架构是一些理论的知识,将来我们使用了它们进行代码开发会让我们代码维护性和扩展性更好。
8.1 MVC模式
MVC 是一种分层开发的模式,其中:
-
M:Model,业务模型,处理业务
-
V:View,视图,界面展示
-
C:Controller,控制器,处理请求,调用模型和视图
控制器(serlvlet)用来接收浏览器发送过来的请求,控制器调用模型(JavaBean)来获取数据,比如从数据库查询数据;控制器获取到数据后再交由视图(JSP)进行数据展示。
MVC 好处:
-
职责单一,互不影响。每个角色做它自己的事,各司其职。
-
有利于分工协作。
-
有利于组件重用
8.2 三层架构
三层架构是将我们的项目分成了三个层面,分别是 表现层
、业务逻辑层
、数据访问层
。
- 数据访问层:对数据库的CRUD基本操作
- 业务逻辑层:对业务逻辑进行封装,组合数据访问层层中基本功能,形成复杂的业务逻辑功能。例如
注册业务功能
,我们会先调用数据访问层
的selectByName()
方法判断该用户名是否存在,如果不存在再调用数据访问层
的insert()
方法进行数据的添加操作 - 表现层:接收请求,封装数据,调用业务逻辑层,响应数据
而整个流程是,浏览器发送请求,表现层的Servlet接收请求并调用业务逻辑层的方法进行业务逻辑处理,而业务逻辑层方法调用数据访问层方法进行数据的操作,依次返回到serlvet,然后servlet将数据交由 JSP 进行展示。
三层架构的每一层都有特有的包名称:
- 表现层:
com.mrfan.controller
或者com.mrfan.web
- 业务逻辑层:
com.mrfan.service
- 数据访问层:
com.mrfan.dao
或者com.mrfan.mapper
后期我们还会学习一些框架,不同的框架是对不同层进行封装的
8.3 MVC 和 三层架构
通过 MVC 和 三层架构 的学习,有些人肯定混淆了。那他们有什么区别和联系?
如上图上半部分是 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接口,并重写其所有方法
- 配置Filter拦截资源的路径:在类上定义
@WebFilter
注解。而注解的value
属性值/*
表示拦截所有的资源
-
在doFilter方法中输出一句话,并放行
在进行拦截前先会执行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)之一。
-
监听器可以监听就是在
application
,session
,request
三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。request 和 session 我们学习过。而
application
是ServletContext
类型的对象。ServletContext
代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。
10.2 分类
JavaWeb 提供了8个监听器:
这里面只有 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。
JavaScript
和XML
,JavaScript
表明该技术和前端相关;XML
是指以此进行数据交换。
11.1.1 作用
AJAX 作用有以下两方面:
- 与服务器进行数据交换:通过AJAX可以给服务器发送请求,服务器将数据直接响应回给浏览器。
- 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验,等等…
11.1.2 同步和异步
知道了局部刷新后,接下来我们再聊聊同步和异步:
- 同步发送请求过程如下
浏览器页面在发送请求给服务器,在服务器处理请求的过程中,浏览器页面不能做其他的操作。只能等到服务器响应结束后才能,浏览器页面才能继续做其他的操作。
- 异步发送请求过程如下
浏览器页面发送请求给服务器,在服务器处理请求的过程中,浏览器页面还可以做其他的操作。
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);
}
};
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>
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>
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
串作为 axios
的 data
属性值进行请求参数的提交。如下:
var jsObject = {name:"张三"};
axios({
method:"post",
url:"http://localhost/axioServlet",
data: JSON.stringify(jsObject)
}).then(function (resp) {
alert(resp.data);
})
而 axios
是一个很强大的工具。我们只需要将需要提交的参数封装成 js 对象,并将该 js 对象作为 axios
的 data
属性值进行,它会自动将 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
使用也是比较简单的,分为以下三步完成
-
导入坐标
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency>
-
Java对象转JSON
String jsonStr = JSON.toJSONString(obj);
将 Java 对象转换为 JSON 串,只需要使用
Fastjson
提供的JSON
类中的toJSONString()
静态方法即可。 -
JSON字符串转Java对象
User user = JSON.parseObject(jsonStr, User.class);
将 json 转换为 Java 对象,只需要使用
Fastjson
提供的JSON
类中的parseObject()
静态方法即可。
13.4.3 应用
13.4.3.1 查询所有数据库中User用户信息
基本结构:
后端实现
将 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>
13.4.3.2 添加用户信息
基本结构:
前端实现
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);
}
}
14. VUE
14.1 概述
接下来我们学习一款前端的框架,就是 VUE。
Vue 是一套前端框架,免除原生JavaScript中的DOM操作,简化书写。
我们之前也学习过后端的框架 Mybatis
,Mybatis
是用来简化 jdbc
代码编写的;而 VUE
是前端的框架,是用来简化 JavaScript
代码编写的。我们在添加用户去获取相关字段信息,里面进行了大量的DOM操作,如下
学习了 VUE
后,这部分代码我们就不需要再写了
基于MVVM(Model-View-ViewModel)思想,实现数据的双向绑定,将编程的关注点放在数据上。之前我们是将关注点放在了 DOM 操作上;而要了解 MVVM
思想,必须先聊聊 MVC
思想,如下图就是 MVC
思想图解
C 就是咱们 js 代码,M 就是数据,而 V 是页面上展示的内容,如下图是我们之前写的代码
MVC
思想是没法进行双向绑定的。双向绑定是指当数据模型数据发生变化时,页面展示的会随之发生变化,而如果表单数据发生变化,绑定的模型数据也随之发生变化。接下来我们聊聊 MVVM
思想,如下图是三个组件图解
图中的 Model
就是我们的数据,View
是视图,也就是页面标签,用户可以通过浏览器看到的内容;Model
和 View
是通过 ViewModel
对象进行双向绑定的,而 ViewModel
对象是 Vue
提供的。接下来让大家看一下双向绑定的效果,下图是提前准备的代码,输入框绑定了 username
模型数据,而在页面上也使用 {{}}
绑定了 username
模型数据
通过浏览器打开该页面可以看到如下页面
当我们在输入框中输入内容,而输入框后面随之实时的展示我们输入的内容,这就是双向绑定的效果。
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>
14.4 生命周期
生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法,这些生命周期方法也被称为钩子方法。
下图是 Vue 官网提供的从创建 Vue 到效果 Vue 对象的整个过程及各个阶段对应的钩子函数
看到上面的图,大家无需过多的关注这张图。这些钩子方法我们只关注 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快速入门
element-ui
文件夹直接拷贝到项目的webapp
下。目录结构如下
-
创建页面,并在页面引入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">
-
.创建Vue核心对象
Element 是基于 Vue 的,所以使用Element时必须要创建 Vue 对象
<script>
new Vue({
el:"#app"
})
</script>
- 官网复制Element组件代码
整体页面代码如下:
<!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>
15.2 利用Element设计页面
利用Element查询相关用法 配合使用即可达到如下效果:
<!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>
最后
以上就是甜蜜咖啡为你收集整理的JavaWeb入门学习JavaWeb入门学习的全部内容,希望文章能够帮你解决JavaWeb入门学习JavaWeb入门学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复