0%

1
2
3
4
5
6
MyBatis获取参数值的两种方式:${}与#{}

${}的本质就是字符串拼接,#{}的本质就是占位符赋值

${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;
但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号

情况一:mapper接口方法参数为单个字面量类型

1
2
3
4
5
6
7
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
List<User> result = parameterMapper.getUserByUsername("张三");
result.forEach(user -> System.out.println(user));
}
1
2
3
4
<!--User getUserByUsername(String username);-->
<select id="getUserByUsername" resultType="User">
select * from t_user where username = #{username}
</select>

情况二:mapper接口方法参数为多个

  • 使用arg0,arg1,…… 或 param1,param2,…… 为键,参数为值
  • 只需通过#{}或${}以键的方式访问值即可
1
2
3
4
5
6
7
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
List<User> result = parameterMapper.checkLogin("张三", "123456");
result.forEach(user -> System.out.println(user));
}
1
2
3
4
<!--User checkLogin(String username, String password)-->
<select id="checkLogin" resultType="User">
select * from t_user where username = #{arg0} and password = #{arg1}
</select>

情况三:mapper接口方法参数有多个,可以手动放在一个map中存储

  • 只需通过#{}或${}以键的方式访问值即可
1
2
3
4
5
6
7
8
9
10
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
Map<String, Object> mp = new HashMap<>();
mp.put("username", "张三");
mp.put("password", "123456");
List<User> result = parameterMapper.checkLoginByMap(mp);
result.forEach(user -> System.out.println(user));
}
1
2
3
4
<!--List<User> checkLoginByMap(Map<String, Object> mp)-->
<select id="checkLoginByMap" resultType="User">
select * from t_user where username = #{username} and password = #{password}
</select>

情况四:参数是一个实体类类型

  • 直接通过属性名访问属性值
1
2
3
4
5
6
7
8
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
User user = new User("Alice", "666666", 22, "女", "666@163.com");
int result = parameterMapper.insertUser(user);
System.out.println(result);
}
1
2
3
4
<!--int insertUser(User user)-->
<insert id="insertUser">
insert into t_user values(null, #{username}, #{password}, #{age}, #{sex}, #{email})
</insert>

情况五:通过@param命名参数

  • 以@param注解的值 或 param1,param2,……为键,以参数为值
1
2
3
4
5
6
7
@Test
public void testMybatis() throws IOException {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
List<User> result = parameterMapper.checkLoginByParam("Alice", "666666");
result.forEach(User -> System.out.println(User));
}
1
2
3
4
<!--List<User> checkLoginByParam(@Param("username") String username, @Param("password") String password)-->
<select id="checkLoginByParam" resultType="User">
select * from t_user where username = #{username} and password = #{password}
</select>

建议整合为两种情况

  • 参数是实体类对象
  • 否则全都用@param

测试添加功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.sympa.mybatis.test;

import com.sympa.mybatis.mapper.UserMapper;
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 org.junit.jupiter.api.Test;

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

public class MybatisTest {

@Test
public void testMybatis() throws IOException {
//加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis.config.xml");
//获取sqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
SqlSession sqlSession = sqlSessionFactory.openSession();
//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//通过代理模式创建UserMapper接口的代理实现类对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句
//测试添加功能
int result = userMapper.insertUser();
System.out.println("result:" + result);
//提交事务
sqlSession.commit();
}
}
1
2
3
<insert id="insertUser">
insert into t_user values(null, '张三', '123456', 18, '男', '123@qq.com')
</insert>

测试查询功能

查询功能标签必须设置resultType或resultMap

  • resultType:设置默认映射关系
  • resultMap:设置自定义的映射关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.sympa.mybatis.test;

import com.sympa.mybatis.mapper.UserMapper;
import com.sympa.mybatis.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 org.junit.jupiter.api.Test;

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

public class MybatisTest {

@Test
public void testMybatis() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.config.xml");

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> result = userMapper.getUserById();
result.forEach(user -> System.out.println(user));
}
}
设置结果映射
1
2
3
4
<!--User getUserById();-->
<select id="getUserById" resultType="com.sympa.mybatis.pojo.User">
select * from t_user
</select>

封装SqlSessionUtils工具类,获取SqlSession对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.sympa.mybatis.utils;

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;

public class SqlSessionUtils {

public static SqlSession getSqlSession(){
InputStream is = null;
try {
is = Resources.getResourceAsStream("mybatis.config.xml");
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
return sqlSession;
}
}

Request继承体系

  • ServletRequest:Java提供的请求对象根接口
  • HttpServletRequest:Java提供的对Http协议封装的请求对象接口
  • RequestFacade:Tomcat定义的实现类

Request获取请求数据

  • 请求行:GET /request-demo/req1?username=zhangsan HTTP/1.1
    • String getMethod():获取请求方式,GET
    • String getContextPath():获取虚拟目录(项目访问路径),/request-demo
    • StringBuffer getRequestURL():获取URL(统一资源定位符)
    • String getRequestURI():获取URI(统一资源标识符),/request-demo/req1
    • String getQueryString():获取请求参数,username=zhangsan&password=123
  • 请求头
    • String getHeader(String name):根据请求头名称,获取值
  • 请求体
    • ServletInputStream getInputSteam():获取字节输入流
    • BufferedReader getReader():获取字符输入流

Request通用方式获取参数

  • Map getParameterMap():获取所有参数Map集合
  • String[] getParameterValues(String name):根据名称获取参数值(数组)
  • String getParameter(String name):根据名称获取参数值(单个值)

POST请求参数中文乱码解决

1
req.setCharacterEncoding("UTF-8"); //设置输入流编码

Tomcat8.0版本前,GET请求参数中文乱码解决(POST通用)

  • 本质是URL字符集的编解码
1
2
3
4
5
6
7
8
9
10
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get..");
StringBuffer url = req.getRequestURL();
System.out.println(url);
String username = req.getParameter("username");
byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
username = new String(bytes, StandardCharsets.UTF_8);
System.out.println(username);
}

请求转发

  • 一种在服务器内部的资源跳转方式
  • 实现方式
1
req.getRequestDisptcher("资源B路径").forward(req, resp);
  • 请求转发资源间共享数据,使用Request对象
1
2
3
void setAttribute(String name, Object o) //存储数据到request域中
Object getAttribute(String name) //根据key,获取值
void removeAttribute(String name) //根据key,删除该键值对

Maven中Servlet的配置

1.创建web项目,导入Servlet依赖坐标

1
2
3
4
5
6
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

2.创建:定义一个类,实现Servlet接口,并重写接口中的所有方法,并在service方法中输出一句话

3.再类上使用@WebServlet注解,配置该Servlet的访问路径

4.访问:启动Tomcat,浏览器输入URL访问该Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.sympa.web;

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

@WebServlet("/demo1")
//浏览器输入http://localhost:8080/demo1
public class ServletDemo1 implements Servlet {

public void init(ServletConfig servletConfig) throws ServletException {

}

public ServletConfig getServletConfig() {
return null;
}

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("servlet hello world!!!");
}

public String getServletInfo() {
return null;
}

public void destroy() {

}
}

Servlet的生命周期

  1. 加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象
  2. 初始化:在Servlet实例化后,容器将调用Servlet的init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次
  3. 请求处理:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理
  4. 服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放。在destroy()方法调用之后,容器就会释放Servlet实例,该实例随后会被Java的垃圾收集器回收

Servlet的体系结构

  • Servlet:Servlet体系根接口
  • GenericServlet:Servlet抽象实现类(实现了Servlet接口)
  • HttpServlet:对HTTP协议封装的Servlet实现类(继承于GenericServlet抽象类)
    • 重写doGet和doPost方法

Servlet urlPattern配置

  • Servlet想要被访问,必须配置其访问路径
  • 一个Servlet,可以配置多个访问路径
    • @WebServlet(urlPatterns = {“/demo1”, “/demo2”})
  • urlPattern四种配置规则(按优先级)
    • 精确匹配:/xxx/xxx
    • 目录匹配:/xxx/*
    • 扩展名匹配:*.xxx
    • 任意匹配: /

Response继承体系

  • ServletResponse:Java提供的请求对象根接口
  • HttpServletResponse:Java提供的对Http协议封装的请求对象接口
  • ResponseFacade:Tomcat定义的实现类

Response获取请求数据

  • 响应行:HTTP/1.1 200 OK
    • void setStatus(int sc):设置响应状态码
  • 响应头:Content-Type: text/html
    • void setHeader(String name, String value):设置响应头键值对
  • 响应体
    • ServletOutputStream getOutputSteam():获取字节输出流
    • PrintWriter getWriter():获取字符输出流

Response完成重定向

  • 重定向:一种资源跳转方式
1
response.sendRedirect("虚拟路径");
  • 动态获取虚拟路径

    1
    2
    String contextPath = request.getContextPath();
    response.sendRedirect(contextPath + "/demo1");

Response响应字符数据

  • 使用

    • 通过Response对象获取字符输出流
    1
    PrintWriter writer = resp.getWriter();
    • 写数据
    1
    writer.write("aaa");
    • 响应头设置响应体解析格式与编码
    1
    response.setContentType("text/html;charset=utf-8");

    流不需要关闭

Response响应字节数据

  • 使用

    • 通过Response对象获取字节输出流
    1
    ServletOutputStream outputStream = resp.getOutputStream();
    • 写数据

      1
      outputStream.write(字节数据);
    • 文件copy工具类(在pom.xml中引入commons-io工具包)

    1
    IOUtils.copy(fis, os);

Web基本概念

  • web,网页的意思
  • 静态web
    • html,css
    • 提供给所有人看的数据始终不变
  • 动态web
    • Servlet/JSP,ASP,PHP
    • 提供给所有人看的数据始终变化
  • 在Java中,动态web资源开发的技术统称为JavaWeb

Web应用程序

  • 可以提供浏览器访问的程序
  • 一个web应用由多部份组成
    • html,css,js
    • jsp,servlet
    • java程序
    • jar包
    • 配置文件(Properties)
  • 若想提供给外界访问,需要一个服务器统一管理

Web服务器

  • 服务器是一种被动操作,用来处理用户的一些请求和给用户一些相应信息
  • IIS,Tomcat

什么是MyBatis

  • MyBatis是一款优秀的持久层框架,用于简化JDBC开发
  • MyBatis本是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github
  • 官网:https://mybatis.org/mybatis-3/zh/index.html
持久层
  • 负责将数据保存到数据库的那一层代码
  • JavaEE三层架构:表现层,业务层,持久层

MyBatis核心配置文件mybatis.config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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>

<properties resource="jdbc.properties"/>

<!--设置类型别名-->
<typeAliases>
<package name="com.sympa.mybatis.pojo"/>
</typeAliases>

<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--设置映射别名-->
<mappers>
<package name="com.sympa.mybatis.mapper"/>
</mappers>
</configuration>

创建实现类与mapper接口


创建Mybatis的映射文件

相关概念:ORMObject Relationship Mapping)对象关系映射

  • 对象:Java实体类对象
  • 关系:关系型数据库
  • 映射:二者之间的对应关系
Java概念 数据库概念
属性 字段/列
对象 记录/行

1、映射文件的命名规则:

表所对应的实体类的类名+Mapper.xml

例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml

因此一个映射文件对应一个实体类,对应一张表的操作

MyBatis映射文件用于编写SQL,访问以及操作表中的数据

MyBatis映射文件存放的位置是src/main/resources/mappers目录下

2、MyBatis中可以面向接口操作数据,要保证两个一致

a>mapper接口的全类名和映射文件的命名空间(namespace)保持一致

b>mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致

表 —> 实体类 —> mapper接口 —> 映射文件

1
2
3
4
5
6
7
8
9
<?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">
<mapper namespace="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>

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

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

仓库分类

  • 本地仓库:自己计算机的一个目录
  • 中央仓库:由Maven团队维护的全球唯一的仓库
  • 远程放库:一般由公司团队搭建的私有仓库

当项目中使用坐标引入对应依赖jar包后,首先会查找本地仓库中是否有对应的jar包

  • 有,则在项目中直接引用
  • 没有,则去中央仓库下载对应jar包到本地仓库

Maven常用命令

  • compile:编译
  • clean:清理
  • test:测试
  • package:打包
  • install:安装

Maven生命周期

  • Maven构建项目生命周期描述的是一次构建过程经历了多少个事件
  • Maven对项目构建的生命周期划分为3套
    • clean:清理工作
    • default:核心工作,例如编译,测试,打包,安装等
    • site:产生报告,发布站点等
  • 同一生命周期内,执行后边的命令,前边所有的命令会自动执行

Maven坐标详解

  • 什么是坐标?
    • Maven中的坐标是资源的唯一标识
    • 使用坐标来定义项目或引入项目中需要的依赖
  • Maven坐标主要组成
    • groupId:定义当前Maven项目隶属组织名称(通常是域名反写)
    • artifactId:定义当前Maven项目名称(通常是模块名称)
    • version:定义当前项目版本号

使用坐标导入jar包

  1. 在pom.xml中编写标签
  2. 标签中使用引入坐标
  3. 定义坐标的groupId,artifactId,version
  4. 点击刷新按钮,使坐标生效

依赖范围

通过设置坐标的依赖范围(scope),可以设置对应jar包的作用范围:编译环境,测试环境,运行环境

依赖范围 编译classpath 测试classpath 运行classpath 例子
compile(默认) Y Y Y logback
test - Y - Junit
provided Y Y - servlet-api
runtime - Y Y jdbc驱动
system Y Y - 存储在本地的jar包
import 引入DependencyManagement

  • 数据库连接池是个容器,负责分配,管理数据库链接
  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
  • 好处:
    • 资源重用
    • 提升系统响应速度
    • 避免数据库连接遗漏

数据库连接池实现

  • 标准接口:DataSource
    • 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口
    • 功能:获取连接 Connection getConnextion()
  • 常见的数据库连接池
    • DBCP
    • C3P0
    • Druid(德鲁伊)
      • Druid连接池是阿里巴巴开源的数据库连接池项目
      • 功能强大,性能优秀,是Java语言最好的数据库连接池之一

Druid使用步骤

  1. 导入jar包druid-1.1.12.jar
  2. 定义配置文件
  3. 加载配置文件
  4. 获取数据库连接池对象
  5. 获取连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.sympa.lesson01;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;

/*
Druid数据库连接池
*/
public class JdbcFirstDemo {
public static void main(String[] args) throws Exception {

//加载配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src/druid.properties"));

//获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

//获取数据库连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
}

HTTP协议特点

  • 基于TCP协议,面向连接,安全
  • 基于请求-相应模型的,一次请求对应一次相应
  • HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-相应都是独立的
    • 缺点:多次请求间不能共享数据
    • 优点:速度快

HTTP-请求数据格式

  • 请求数据分为3部分:
    1. 请求行:请求数据的第一行。其中GET表示请求方式,/表示请求资源路径,HTTP/1.1表示协议版本
    2. 请求头:第二行开始,格式为key : value形式
    3. 请求体:POST请求的最后一部分,存放请求参数
1
2
3
4
5
GET / HTTP/1.1
Host: www.itcast.cn
Connection: keep-alive
Cache-Control: max-age=0 Upgrade-Insecure-Requests:1
User-Agent: Mozilla/5.0 Chrome/91.0.4472.106
  • 常见HTTP请求头:
    • Host:表示请求的主机名
    • User-Agent:浏览器版本,例如Chrome浏览器的标识类似Mozilla/5.0 … Chrome/79
    • Accept:标识浏览器能接收的资源类型
    • Accept-Language:表示浏览器偏好的语言
    • Accept——Encoding:表示浏览器可以支持的压缩类型
  • GET请求和POST请求区别
    • GET请求请求参数在请求行中,没有请求体。POST请求请求参数在请求体中
    • GET请求请求参数大小有限制,POST没有

HTTP-相应数据格式

  • 响应数据分为三部分
    1. 相应行:相应数据第一行。200表示状态码,OK表示状态码描述
    2. 响应头:第二行开始,格式为key : value
    3. 响应体
1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1 200 OK
Server: Tengine
Content-Type: text/html
Transfer-Encoding: chunked

<html>
<head>
<title></title>
<head>
<body></body>
</html>
  • 常见的HTTP响应头
    • Content-Type:表示该相应内容的类型
    • Content-Length:表示该相应内容长度
    • Content-Encoding:表示该相应压缩算法
    • Cache-Control:指示客户端应如何缓存

响应状态码大全

状态码分类 说明
1xx 响应中——临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略
2xx 成功——表示请求已经被成功接收,处理已完成
3xx 重定向——重定向到其它地方,它让客户端再发起一个请求以完成整个处理
4xx 客户端错误——处理发生错误,责任在客户端
5xx 服务器错误——处理发生错误,责任在服务器