java
auggie

JavaWeb

Tomcat 配置

Tomcat 是 web 服务器。

默认端口号:8080

可以直接使用 bin/startup.bat 启动

配置文件为 conf/server.xml

一开始 Tomcat 访问不了的原因是放在了 x86 文件夹下

网站的访问

  1. 键入 url
  2. 检查本机 system32\drivers\etc\hosts 配置文件下查看是否存在该 url 的映射,如果存在直接返回 IP
  3. 访问 DNS 服务器,获得 IP

使用 Tomcat 发布一个网站

将 html 放在指定的 web 应用文件夹下

网站结构

1
2
3
4
5
6
7
8
9
10
11
12
--webapps: // Tomcat 服务器的 web 目录
-ROOT
-auggie: // 网站目录名
-WEB-INF
-classes: // java 程序
-lib: // web 应用依赖的 jar 包
-web.xml: // 网站配置文件
-index.html // *默认网页
-static
-css
-js
-img

image-20211230145352576

HTTP

超文本传输协议,是一个简单的请求-响应协议。

  1. TCP
  2. port:80

HTTPS:安全的超文本传输协议

HTTP request

image-20211230145331177

HTTP response

image-20211230145322009

状态码:

  • 200:成功
  • 404:找不到
  • 3**:重定向
  • 5**:服务器代码错误

Maven

为什么要学习 Maven

  1. JavaWeb 开发中,需要使用大量的 jar 包,我们需要手动导入
  2. Maven 是一个自动导入和配置 jar 包的工具

Maven 介绍

Maven 的核心思想:约定大于配置

1
2
3
4
bin: 可执行文件
conf: 配置
boot: 启动
lib: 依赖

IDEA 中使用 Maven

  1. 创建 MavenWeb 项目

image-20211228140933067

image-20211228141305382

上面图片的 groupId 配置错误(

  1. IDEA 中的 Maven 设置

Spring 中可能会使用 IDEA 自带的 Maven,所以我们可能需要在 IDEA 中配置 Maven。

Maven 项目结构

1
2
3
4
5
--mian
-java // 存放 java 代码
-resources // 存放一些配置文件
--test
-java // 测试使用

在 IDEA 中配置 Tomcat

左上角配置启动环境即可

Maven Webapp 项目结构

1
2
3
-Lifecycle		// maven 命令行操作
-Plugins // 插件
-Dependencies // 项目依赖

pom.xml 文件

用于配置 maven 项目。只要将需要导入的包放在 dependencies 下面即可。

子项目无法识别父项目的时候,子模块加上

1
2
3
4
5
<parent>
<groupId>com.auggie</groupId>
<artifactId>JavaWeb-Servlet</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

即可

Servlet

Servlet 简介

  • 用于开发动态 Web 的技术

把实现了 Servlet 接口的 Java 程序叫做 Servlet

HelloSverlet

Servlet 接口有两个默认的实现类:HttpServlet

  1. 构建 Maven 项目,删掉里面的全部东西,将依赖全部导入主工程

  2. 将 Servlet 建在 Module 中

    1. 关于 Maven 父子工程的理解:

      在父项目中建立一个 module,类似与继承

  3. Maven 环境优化

    1. 修改 web.xml
    2. 将 maven 环境搭建完整
  4. 实现 Servlet 程序

    1. 编写一个实现 Servlet 接口的类
    2. 继承 HttpServlet
  5. 编写 Servlet 的映射

    1. 为什么需要映射

      JAVA 程序需要使用浏览器访问,浏览器需要连接 Web服务器,所以我们需要 Web 服务器中注册我们写的 Servlet,并且给他一个浏览器能够访问的路径

      用户需要通过浏览器来访问 Web 服务器中的 Servlet。所以我们需要在 Web 服务器中注册 Servlet

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <servlet>
    <servlet-name>hello</servlet-name> // 3
    <servlet-class>com.auggie.Servlet.HelloServlet</servlet-class> // 4
    </servlet>

    <servlet-mapping>
    <servlet-name>hello</servlet-name> // 2
    <url-pattern>/hello</url-pattern> // 1
    </servlet-mapping>

    Java 程序需要 servlet 注册,给定一个 servlet 名字

    然后将 servlet - name 映射到 url - pattern 上面

  6. 配置 Tomcat

一开始使用的 Tomcat 是 10 版本,版本太高了(,导致版本不兼容

Servlet 接口的实现

Servlet interface

1
2
3
4
5
6
7
8
9
void init(ServletConfig var1) throws ServletException;

ServletConfig getServletConfig();

void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

String getServletInfo();

void destroy();

GenericServlet

通用小服务程序

1
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

HttpServlet

已经实现了 service 方法,我们只需要重写 service 调用的子方法

1
2
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException

Servlet 原理

Web 服务器收到浏览器请求之后,会调用 Servlet

mapping 优先级:指定了固有映射的优先级最高。

ServletContext

背景:登陆的时候,一个登陆全部都登陆了

Web 容器在启动的时候,为 Web 程序都创建一个对应的 ServletContext 对象,代表当前的 Web 应用。

应用:

  • 共享数据(不同 Servlet 之间的数据通信)

    在这个 Servlet 中的数据可以在另外一个 Servlet 中访问。

  • 转发

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    ServletContext servletContext = this.getServletContext();
    System.out.println("dispatch");
    servletContext.getRequestDispatcher("/hello").forward(req, resp);
    System.out.println("finish");
    }
    /*
    1. 转发之后,会返回
    2. 需要使用 forward(req, resp) 方法来执行跳转
    */

注意事项:

  1. 如果从 ServletContext 中读取一个不存在的对象,结果为空。

  2. 设置 resp 的字符集即可解决乱码问题。

    1
    2
    resp.setContentType("text/html");
    resp.setCharacterEncoding("utf-8");

Response

  1. 响应状态码

  2. 响应体

    1
    2
    3
    ServletOutputStream getOutputStream() throws IOException;

    PrintWriter getWriter() throws IOException;
  3. 常见应用

    1. 向浏览器输出消息
    2. 下载文件
      1. 获取文件的绝对路径
      2. 获取文件名,可以使用 trick 获得
      3. 设置响应头 + fileName
      4. 创建 FileOutputStream, + realPath
      5. 创建 OutputStream
      6. 创建 buffer
      7. 将 in 读取到 buffer 中,再将 buffer 中的数据读取到 out 中
      8. 关闭流对象

    File -> FileOutputStream -> Buffer -> OutputStream -> Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

String realPath = "C:\\Users\\auggie\\Documents\\IDEA_programs\\MavenDemo\\Servlet\\Response\\target\\classes\\image\\1.jpeg";

String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);

resp.setHeader("Content-Disposition", "attachment; filename=" + fileName);

FileInputStream in = new FileInputStream(realPath);

ServletOutputStream out = resp.getOutputStream();

int len = 0;
byte[] buffer = new byte[1024];

while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}

in.close();
out.close();
}

总结:需要掌握 resp 的状态头,流对象的使用。

 3. **验证码,后端实现**
  1. 如何实现后台刷新

    resp.setHeader(“refresh”, “5”);

  2. 在内存中创建图片

    BufferedImage

  3. 创建随机数

    1. random
    2. 将 int 转化为 String 类
      1. “” + int
      2. String.valueOf(int)
    3. 保证随机数一定是等长的
      1. 使用 StringBuffer 对象
  1. 实现重定向

    页面跳转,该资源请求另外一个 Web 资源

    重定向的路径从项目目录开始,跳转从当前目录开始

    1
    2
    this.getServletContext().getRequestDispatcher("/down").forward(req, resp);
    resp.sendRedirect("/resp/down");

Request

1
2
${pageContext.request.contextPath}
/%--项目当前路径--%/
1
2
3
req.setCharacterEncoding("utf-8");					// 防止乱码
String password = req.getParameter("password"); // 单个参数
String[] hobby = req.getParameterValues("hobby"); // checkbox

会话技术

作用:用于解决 HTTP 协议的无状态性。

从打开浏览器访问某个网站,到关闭浏览器的过程,称为一次会话。会话技术是指在会话中,帮助服务器记录用户状态和数据的技术。

保存会话的两种会话技术

  1. Cookie 客户端会话技术
  2. Session 服务器会话技术

定义:Cookie 属于客户端会话技术,它是服务器发送给浏览器的小段文本信息,存储在客户端浏览器的内存中或硬盘上。当浏览器保存了 Cookie 后,每次访问服务器,都会在 HTTP 请求头中将这个 Cookie 回传给服务器。

Cookie 中存的是键值对。可以使用 getCookie 方法获得全部的 Cookie 数组。然后使用 getName()getValue()

获取单个 Cookie 的值。

setMaxAge(int expiry) 以秒为单位。

  1. String 转化为 Date 对象

    1
    2
    3
    4
    String value = it.getValue();
    Long tmp = Long.parseLong(value);
    Date date = new Date(tmp);
    System.out.println(date);
  2. Date 转化为 String 输出

    SimpleDateFormat

访问其他页面的时候,会把 cookie 带过来。

缺点:

  • 在 HTTP 请求中,Cookie 是明文传递的,容易泄露用户信息,安全性不高。
  • 浏览器可以禁用 Cookie,一旦被禁用,Cookie 将无法正常工作。
  • Cookie 对象中只能设置文本(字符串)信息。
  • 客户端浏览器保存 Cookie 的数量和长度是有限制的。

Session

Session 虽然属于服务端会话技术,但是它的实现离不开客户端浏览器和 Cookie 的支持。

image-20211230131104256

过程:

  1. 当客户端第一次请求会话对象时,服务器会创建一个 Session 对象,并为该 Session 对象分配一个唯一的 SessionID(用来标识这个 Session 对象);
  2. 服务器将 SessionID 以 Cookie(Cookie 名称为:“JSESSIONID”,值为 SessionID 的值)的形式发送给客户端浏览器;
  3. 客户端浏览器再次发送 HTTP 请求时,会将携带 SessionID 的 Cookie 随请求一起发送给服务器;
  4. 服务器从请求中读取 SessionID,然后根据 SessionID 找到对应的 Session 对象。

在 pom.xml 中设置 Session 存活时间

以分钟为单位,默认是 30 min。Session-time 是 0 或者负数的时候,表示会话不会过期。

1
2
3
<session-config>
<session-timeout>10</session-timeout>
</session-config>

Servlet Session的使用 (biancheng.net)

上面总结的很全面

image-20211230131258093

MVC 三层架构

Module View Controller 模型视图控制器

image-20211230140625096

Module:

  • 业务处理(Service):实现业务逻辑
  • 数据持久层(DAO):主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此

View:

  • 展示数据
  • 发起 Servlet 请求

Controller:

  • 接受用户请求
  • 交给业务层处理
  • 控制视图跳转

Demo:

  1. 接受用户登陆请求(controller)
  2. 处理用户用户请求(controller)
  3. 交给业务层,判断是否合法(Module)
  4. 交给 DAO 层查询 DB 是否合法

Filter

能够对 Servlet 容器传给 Web 资源的 request 对象和 response 对象进行检查和修改。

  • 在 Web 资源被访问前,检查 request 对象,修改请求头和请求正文,或对请求进行预处理操作。
  • 将请求传递到下一个过滤器或目标资源。
  • 在 Web 资源被访问后,检查 response 对象,修改响应头和响应正文。

image-20211230142142647

作用:

  • 处理中文乱码
  • 登陆验证

注意事项:

  1. 过滤器需要注册
  2. doFilter 需要下传,如果不写程序将在这里停止。
  1. 过滤器在 Web 服务器启动的时候,初始化
  2. 过滤器在 Web 服务器停止的时候,销毁

过滤经过 url 的全部请求

1
2
3
4
5
6
7
8
<filter>
<filter-name>characterencoding</filter-name>
<filter-class>com.auggie.filter.ChineseCharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterencoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1
filterChain.doFilter(servletRequest, servletResponse); // 不写程序直接停止运行

Filter 和监听器的应用

用户登陆之后才能看到主页,用户注销之后不能进入主页

1
2
3
4
5
6
7
8
9
10
-view
--home // 需要登陆之后才能进入
--login
--error

-controller

-service
--servlet/logout
--servlet/login
  1. 在 home.jsp 中重定向

  2. 使用过滤器实现

    转化之后,才能获得 Session。

    过滤器注册在什么地方?主页下面的一切,主页和其他页面分开

实现用户等级 id name level

小结:

过滤器实现拦截需要将网页放在不同的路径下。

小结

image-20211230145352576

  1. 一般方法
    1. servletResponse.setCharacterEncoding("utf-8"); 设置编码
    2. servletResponse.setContentType("text/html"); 设置浏览器展示样式
  2. rep 常用方法
    1. getSession()
    2. getCookie()
    3. getParameter()
    4. getParameterValues()
  3. Session 常用方法
    1. getAttribute(String)
    2. setAttribute(String, Object)
    3. removeAttribue(String)
    4. invalidate()
    5. sendRedirect(Stirng Absoluteurl)
  4. Cookie 常用方法
    1. getName(String)
    2. getValue(String)
  5. resp 常用方法
    1. getWriter()
    2. getOutputStream()
    3. addCookie(String, String)
  6. ServletContext 常用方法 this.getServletContext()
    1. getAttribute(String)
    2. setAttribute(String)
    3. getRequestDispatcher(String url).forward(req, resp)
  7. Filter
    1. implements Filter
    2. doFilter

JDBC

流程

  1. 加载驱动,生成 DriverManager 对象
  2. 通过 DriverManager 对象,生成数据库连接对象 connection
  3. 通过 connection 对象,生成执行环境对象 statement
  4. 通过 statement 对象,生成 resultSet 对象

加载 JDBC

1
2
3
Class.forName("com.mysql.jdbc.Driver");

// com.java.jdbc.Driver

连接数据库

创建数据库连接对象

1
2
3
4
String url = "jdbc:mysql://IP:Port/DATABASE";
String user = "bus";
String password = "123";
Connection connection = DriverManager.getConnection(url, user, password);

配置 properties 文件

  1. 编写 properties 文件
  2. 使用 ClassName.class.getClassLoad().getResourceAsStream("file")获取文件字节流
  3. 初始化,创建Properties 对象读取字节流p.load(InputStream)
  4. 读取数据 p.getProperty("name")

不要加空格,不要加双引号

1
2
3
4
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://47.101.155.92:3306/idea
user=bus
password=123

从其他文件读取 .properties 文件

1
2
3
4
5
6
7
8
9
10
// 通过类名访问文件加载器
// 通过文件加载器加载文件为字节流对象
InputSream resourceAsStream = ClassName.class.getClassLoader().getresourceAsStream("name");

// 创建 properties 对象,用于读取 InputStream 对象
Propertiers p = new Properties();
p.load(InputStream);

// 从 properties 对象中读取信息
String drive = Properties.getProperty("name");

增删改查基本步骤

  1. 创建连接对象 Connection
  2. 写 SQL 语句
  3. 获取 PerparedStatement 对象
  4. 修改 PerparedStatement 传入参数
  5. 执行 SQL 语句,得到结果集
  6. 处理结果集
  7. 关闭资源

查询

1
2
3
4
// 创建执行环境
Statement statement = connect.createStatement();

ResultSet resultSet = statement.executeQuery(String sql);

插入

1
2
3
4
5
6
7
// 创建环境
PerparedStatement pstmt = connection.perpareStatement(sql);
// 修改数据
pstmt.setString(pos, val);
// 更新数据
pstmt.executeUpdate();
// setDate(), setInt() ...

插入时间类型:

因为 java.util.Date 和 java.sql.Date 不同,所以需要相互转化。

Date(year, month, day)

Date(Long )

MyBatis

Mybatis3 简介

mybatis – MyBatis 3 | 入门

什么是 Mybatis

  1. MyBatis 是一款优秀的持久层框架
  2. 它支持自定义 SQL、存储过程以及高级映射。
  3. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

配置相关:

MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

持久层

持久化

数据持久化,将数据存在数据库中。

持久化就是将程序的数据在持久状态瞬时状态转化的过程

为什么需要持久化:内存断点即失,内存太贵了。存在一些数据不能丢失¥

持久层

Dao层,Service层,Controller层

  • 完成持久化工作的代码块
  • 层是界限明显的

为什么需要 mybatis,而不是直接使用 JDBC

  • 传统 JDBC 代码太复杂
  • 用于简化 JDBC 的框架
  • 自动化

第一个 Mybatis 程序

  1. 搭建环境 database,普通 maven

  2. 导入 mybatis

    1. mybatis
    2. mysql
    3. junite
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <dependencies>
    <!--单元测试-->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
    </dependency>
    <!-- mysql驱动 -->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
    </dependency>
    <!--mybatis依赖-->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.8</version>
    </dependency>
    </dependencies>
  3. 编写代码

    1. 创建一个 module

    2. 编写 mybatis 核心配置文件

      在 resource 下建立一个 mybatis-config.xml 文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      <?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>
      <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://47.101.155.92:3306/idea?useSSL=true"/>
      <property name="username" value="bus"/>
      <property name="password" value="123"/>
      </dataSource>
      </environment>
      </environments>
      <mappers>
      <mapper resource="com/auggie/dao/UserMapper.xml"/>
      </mappers>
      </configuration>
    3. 编写 mybatis 工具类(类似 connection 对象)

      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
      package com.auggie.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 MybatisUtils {
      private static SqlSessionFactory sqlSessionFactory;
      static {
      try {
      // 获取 SqlSessionFactory 对象
      String resource = "mybatis-config.xml";
      InputStream inputStream = Resources.getResourceAsStream(resource);
      sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      System.out.println("配置成功");
      } catch (IOException e) {
      System.out.println("配置失败");
      e.printStackTrace();
      }
      }
      public static SqlSession getSqlSession(){
      return sqlSessionFactory.openSession();
      }
      }

    4. 编写代码

      1. 实体类 pojo
      2. Dao 接口
      3. 接口实现类
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <?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="com.auggie.dao.UserDao">
      <select id="getUserList" resultType="com.auggie.pojo.User">
      SELECT * FROM idea.user;
      </select>
      </mapper>
  4. 测试

    1. junite 测试

      1. 需要注册 Mapper
      2. Maven 过滤掉 .xml 文件,(maven 资源导出失败)
    2. 步骤:

      1. 创建 SqlSession 对象
      2. 创建接口对应的 mapper
      3. 调用接口定义的方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     <build>
    <resources>
    <resource>
    <directory>src/main/resources</directory>
    <includes>
    <include>**/*.properties</include>
    <include>**/*.xml</include>
    </includes>
    <filtering>true</filtering>
    </resource>
    <resource>
    <directory>src/main/java</directory>
    <includes>
    <include>**/*.properties</include>
    <include>**/*.xml</include>
    </includes>
    <filtering>true</filtering>
    </resource>
    </resources>
    </build>

遇到的问题:

  1. 如果文件在 resources 目录下,可以直接使用文件名访问到该文件
  2. mapper 中指定 .xml 文件需要使用 /classes 下的路径
  3. 需要更新到最新版本
  4. Maven 过滤掉除了 resources 目录下的 .xml 文件。
  5. .xml 中不能添加中文(

小结:

  1. 在 pojo 中创建实体类
  2. 在 Dao 中创建接口 XXX
  3. 设置 XXX.xml,设置 namespace,对应函数,返回的实体类,SQL 语句
  4. 在 mybatis-config.xml 中,创建 mapper

CRUD

Create

  1. 在 xml 申明中 parameterType = ""传递参数使用 #{paraName},需要指定具体的类。
  2. 需要指定具体的 select, insert, update, delete
  3. CUD 需要提交事物,否则不成功。sqlSession.commit()

总结:

编写

  1. 编写接口
  2. 编写 mapper 中的 SQL 语句
  3. xml 中配置 namespace

使用

  1. 创建 SqlSession 对象
  2. 创建接口对象 sqlSession.getMapper(Interface.class)
  3. 调用接口中的函数
  4. 提交事务
  5. 关闭 sqlSession 对象

Map && 模糊查询 (LIKE)

解决传递全部属性的问题(我只需要少数的几个参数就可以修改,不需要全部属性)

map 传递参数的好处:

  • 可以随意传递参数名
  • 不需要全部参数

模糊查询:

  • where name like "%"#{name}"%"
  • where name like #{name} // name == "%name%"

XML 配置解析

  1. environment

    1. 可以配置多套环境,但是每次只能选用一套。

    2. 事物管理器 transactionManager

      1. JDBC
      
      1. MANAGER
    3. dataSource

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <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://47.101.155.92:3306/idea?useSSL=true"/>
    <property name="username" value="bus"/>
    <property name="password" value="123"/>
    </dataSource>
    </environment>
    </environments>
  2. properties

    编写 .properties 文件,在 mybatis-config.xml 中导入该文件

    • 可以直接引入外部配置文件(优先使用)
    • 可以在 xml 中直接编写
  3. typeAlias

    它仅用于 XML 配置,意在降低冗余的全限定类名书写。可以在所有 XML 中使用

    • 在 XML 文件中配置。(实体类少的时候)

      1
      2
      3
      4
      5
      6
      7
      8
      <typeAliases>
      <typeAlias alias="Author" type="domain.blog.Author"/>
      <typeAlias alias="Blog" type="domain.blog.Blog"/>
      <typeAlias alias="Comment" type="domain.blog.Comment"/>
      <typeAlias alias="Post" type="domain.blog.Post"/>
      <typeAlias alias="Section" type="domain.blog.Section"/>
      <typeAlias alias="Tag" type="domain.blog.Tag"/>
      </typeAliases>
    • 在 interface 文件中配置。(实体类多的时候)

      1
      2
      3
      4
      5
      <typeAliases>
      <package name="domain.blog"/>
      </typeAliases>

      @Alias("author")

      在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。

  4. setting

    • mapUnderscoreToCamelCase 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn.
  • logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。

ResultSet 结果集映射

用于解决实体类和数据库属性字段名字不同的问题。

解决方法:

  1. SQL 中取别名

  2. ResuletSet 结果集映射

    image-20220102165201143

    自定义映射,如果是组合类对象如何解决?

日志

日志工厂

将异常的 SQL 输出出来。

image-20220102170130007

  • STDOUT_LOGGING

  • LOG4J

    可以使用配置文件进行配置

分页

为什么需要分页?

  • 数据量太大,需要分页展示
  • 减少数据的处理量
1
2
SELECT * FROM user LIMIT startIndex, pageSize;
SELECT * FROM user LIMIT pageSize;
  1. 接口

    1
    List<User> getUserListByLimit(HashMap<String, Integer> map);
  2. Mapper.xml

    1
    2
    3
    <select id="getUserListByLimit" parameterType="map" resultType="user">
    SELECT * FROM user LIMIT #{startIndex}, #{pageSize};
    </select>
  3. 测试

注解开发

面向接口编程

  1. 解耦
  2. 定义与实现的分离
1
2
3
4
5
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。

因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

1
User getUserByID(@Param("id") int id);

使用注解实现 CUD 的时候,需要使用 autoCommit = true

@Param

  1. 基本类型的参数或则 String 类型,需要加上
  2. 引用类型不需要加

Lombok

自动生成方法。

可以放在类上,也可以放在字段上

@Data 无参构造、Set、get、toString、hashCode、equals

@AllArgsConstructor 创建含有全部参数的构造方法

@NoArgsConstructor 创建无参构造

1
2
3
4
5
6
7
8
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String password;
}

复杂查询环境的搭建

数据库结构:

Student 含有 Teacher 的外键

image-20220104154243206

复杂属性的查询

  1. 对象:association
  2. 集合:collection

多对一(学生 -> 学生 + 老师)

查询所有学生信息,以及对应老师的信息

结构中包含另一个类

javaType 表示一个具体的对象

  1. 子查询

    里面的 properties 都是 Student 的属性

    内嵌 select 字段,调用其他函数,函数的入口是 column

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <resultMap id="StudentTeacher" type="com.auggie.pojo.Student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="teacher" column="tid" javaType="com.auggie.pojo.Teacher"
    select="getTeacher"/>
    </resultMap>

    <select id="getStudentList" resultMap="StudentTeacher">
    SELECT * FROM mybatis.student;
    </select>

    <select id="getTeacher" resultType="com.auggie.pojo.Teacher">
    SELECT * FROM mybatis.teacher WHERE id = #{id};
    </select>
  2. 连表查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <resultMap id="StudentTeacher2" type="com.auggie.pojo.Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="com.auggie.pojo.Teacher">
    <result property="name" column="tname"/>
    <result property="ttid" column="id"/>
    </association>
    </resultMap>

    <select id="getStudentList2" resultMap="StudentTeacher2">
    SELECT s.id sid,
    s.name sname,
    t.id ttid,
    t.name tname
    FROM mybatis.student s,
    mybatis.teacher t
    WHERE s.tid = t.id;
    </select>

一对多(老师 -> 老师 + 学生)

查询一个老师教授的全部学生

类中包含一个集合

  1. 连表查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<resultMap id="TeacherStudent" type="com.auggie.pojo.Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="list" ofType="com.auggie.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>

<select id="getTeacher" resultMap="TeacherStudent">
SELECT t.id tid,
t.name tname,
s.id sid,
s.name sname
FROM mybatis.teacher t,
mybatis.student s
WHERE
t.id = #{id}
AND t.id = s.tid
</select>
  1. 子查询

动态 SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

根据不同的条件获得不同的 SQL 语句。

都需要一个永真的条件开始

sql 标签

用于复用一些 sql 片段。

  1. 最好不要包含 where、set 标签
  2. 不要包含太复杂的 SQL

创建

1
2
3
4
5
6
7
8
<sql id="if-id-name">
<if test="id != null">
AND id = #{id}
</if>
<if test="name != null">
AND name = #{name}
</if>
</sql>

使用

1
<include refid="if-id-name"></include>

if

  1. 使用 map 传入参数
  2. 使用 state = ‘ACTIVE’
1
2
3
4
5
6
7
8
9
10
<select id="getStudent" parameterType="map" resultType="com.auggie.pojo.Student">
SELECT * FROM mybatis.student
WHERE 1 = 1
<if test="id != null">
AND id = #{id}
</if>
<if test="name != null">
AND name = #{name}
</if>
</select>

choose

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。

针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

choose <=> switch

when <=> if, else if

otherwise <=> default

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id="getStudent" parameterType="map" resultType="com.auggie.pojo.Student">
SELECT * FROM mybatis.student
WHERE 1 = 1
<choose>
<when test="id != null">
AND id = #{id}
</when>
<when test="name != null">
AND name = #{name}
</when>
<otherwise>
AND 1 = 1
</otherwise>
</choose>
</select>

where, trim, set

where

用于解决出现前置 AND,OR 的情况

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除

使用 优化上一段 XML 配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="getStudent" parameterType="map" resultType="com.auggie.pojo.Student">
SELECT * FROM mybatis.student
<where>
<choose>
<when test="id != null">
AND id = #{id}
</when>
<when test="name != null">
AND name = #{name}
</when>
<otherwise>
AND 1 = 1
</otherwise>
</choose>
</where>
</select>

如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。

set

用于解决动态更新语句的后置 的情况。投影不能使用

1
2
3
4
5
6
7
8
9
10
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>

trim

1
2
3
4
5
6
7
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>

<trim prefix="SET" suffixOverrides=",">
...
</trim>

用于自定义匹配。

foreach

用于解决不定长条件。

这个元素也不会错误地添加多余的分隔符,看它多智能!

例如:需要查询学生 id 为 [1,2,3,…] 学生的全部信息

1
SELECT * FROM mybatis.student WHERE (id = 1 OR id = 2 OR id = 3)

实现:

既可以用在选择中,也可以用在投影中。但是在投影中,需要使用 ${} 不知道为什么(

1
2
3
4
5
6
7
8
9
10
11
12
<select id="get" parameterType="map" resultType="com.auggie.pojo.Student">
SELECT
<foreach collection="alist" item="item" separator="," open="" close="">
${item}
</foreach>
FROM mybatis.student
<where>
<foreach collection="ids" item="id" open="id IN (" close=")" separator=", ">
#{id}
</foreach>
</where>
</select>
  1. 当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。

  2. 当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

foreach 组合条件条件查询。

1
public List<File> getFileWithAttribute(@Param("departmentList") List<String> departmentList, @Param("limit") int limit);
1
2
3
4
5
6
7
8
<select id="getFileWithAttribute" resultType="com.auggie.experi.pojo.File">
SELECT * FROM experiment.file
WHERE
<foreach collection="departmentList" item="item" open="department IN (" close=")" separator=", ">
#{item}
</foreach>
AND #{limit} >= file.attribute
</select>

缓存

问题:查询连接数据库,消耗资源

可以将一次查询的结果缓存下来,再次查询相同数据的时候,直接取走缓存中的数据。提高查询效率,解决高并发系统的性能问题。

MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。

1
2
3
4
5
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

可用的清除策略有:

  • LRU – 最近最少使用:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
  • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

默认的清除策略是 LRU

flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

Springboot

javaJavaBean

JavaBean 是一种实体类

JavaBean 有特定的写法:

  • 必须有无参构造
  • 属性必须私有化
  • 必须有 get / set 方法

一般用于与数据库的字段做映射 ORM。Object Relational Mapping

ORM:对象属性映射

  • 表 -> 类
  • 字段 -> 属性
  • 行记录 -> 对象

Spring MVC 前置知识

Controller & ResquestMapping

本质还是 Servlet

传递参数需要使用 Model 对象,调用 addAttribute 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
// 利用注解在 Spring 中自动注册 Controller
@Controller
public class HelloController {
// 获取请求的 URL
@RequestMapping("/hello")
public String hello(Model model) {
// 将返回的信息放在 Model 中
model.addAttribute("msg", "hello");
// 最后跳转到 XXXX.hello.html,Spring 实现自动拼接
// 只需要将 .html 放在 templates 下即可
return "hello";
}
}

Restful 风格

使用 Restful 风格可以让 URL 变得结构清晰

不使用 Restful:

1
http://localhost:8080/hello?a=1&b=2

使用 Restful:

1
http://localhost:8080/hello/1/2

实现 Restful 风格:

需要使用 @PathVariable 注解

1
2
3
4
5
6
7
8
@Controller
public class HelloController {
@RequestMapping("/hello/{a}/{b}")
public String hello(@PathVariable int a,@PathVariable int b, Model model) {
model.addAttribute("msg", "hello " + (a + b));
return "hello";
}
}

实现转发和重定向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// forword
@RequestMapping("/hello")
public String hello(Model model) {
model.addAttribute("msg", "hello ");
return "hello";
}

// forword
@RequestMapping("/hello1")
public String hello1(Model model) {
model.addAttribute("msg", "hello ");
return "forward:/hello";
}

// redirect
@RequestMapping("/hello2")
public String hello2(Model model) {
model.addAttribute("msg", "hello ");
return "redirect:/hello";
}

获取前端数据 & 数据回显

servlet 中使用 getParam 参数

获取前端数据

  1. 通过 URL 之后的参数获取。

    Restful

    @RequsetMapping(“/hello/{a}/{b}”)

    @ParamVarible

    使用 ?传递参数

    @RequestParam

    1
    http://localhost:8080/hello/1/2

​ 如果前端传递参数和接受的参数不同的时候,可以使用 @RequestParam("alias")最好都加上

  1. 前端传递 Class

    直接使用 JavaBean,即可接受,接受失败返回 null

    如果为添加表单的话,建议使用 POST 方法,@PostMapping 这样就可以接收到 Class 参数。并且顺序无关。

数据回显

详解SpringMVC如何进行数据回显 - 编程语言 - 亿速云 (yisu.com)

  1. 使用参数
  2. 使用 ModelMap
  3. 使用 Model

image-20220105222619527

微服务阶段

  1. JavaSE :oop
  2. Mysql :持久化
  3. HTML, CSS, JS:视图层
  4. JavaWeb :开发 MVC 三层架构的网站
  5. SSM :Spring + Spring MVC + MyBatis 框架,简化开发流程,配置较为复杂

war:tomcat 运行

jar:内嵌 tomcat

该怎么学

Spring Boot:

  1. 是什么
  2. 配置如何编写,yaml
  3. 自动装配原理
  4. 集成 Web 开发,SSM
  5. 集成数据库 Druid
  6. 分布式开发
  7. 接口文档
  8. 任务调度

什么是 Spring Boot

什么是 Spring

容器,为了解决企业级应用开发的复杂性创建的。

什么是 Spring Boot

JavaWeb:Servlet + Tomcat

Spring Boot 就是一个 JavaWeb 的框架。约定大于配置

什么是微服务

将服务拆分成很多小的模块。

第一个 Spring Boot 程序

Controller 层用来写接口

通过 Maven 的 Package 就可以实现打包。使用 java -jar XXX.jar 就可以运行。

自动装配原理

pom.xml 中 spring-boot-dependencies 包含了核心依赖。因此编写依赖的时候,不需要指定具体的版本。

主函数

1
2
3
4
5
6
7
8
9
10
// 标注这个类是一个 SpringBoot 的应用
@SpringBootApplication
public class HelloworldApplication {

public static void main(String[] args) {
// 将 SpringBoot 程序启动
SpringApplication.run(HelloworldApplication.class, args);
}

}

SpringBoot 配置文件

application.*

什么是 YAML 文件

修改 SpringBoot 自动配置的默认值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 普通的 key-value
name= auggie

# 2. 对象
student:
name: auggie
age: 20

student: {name: auggie, age: 20}

# 3. 数组
pets:
- cat
- pig
- brid
- dog

pet: [cat, dog, brid]
  1. YAML 可以直接给实体类注入值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Component
    @ConfigurationProperties(prefix = "dog")
    public class Dog {
    private String name;
    private Integer age;
    }

    @Autowired
    private Dog dog;
    1
    2
    3
    dog:
    name: dogdog
    age: 12

可以包含${random.int} ${random.uuid} 来产生随机数

${person.hello: hello} 如果 person.hello 存在,则为 person.hello;不然为 hello

  1. 一般使用 @Value 给实体类赋值

可以使用 YAML 配置端口:

1
2
server:
port: 8081

JSR303 校验

应用:后端实现前端 input 标签中的校验功能。

例如:url,email 的校验。

需要导入依赖:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

添加上注解即可:

1
2
3
4
5
6
7
8
9
10
11
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "dog")
@Validated
public class Dog {
@Email()
private String name;
private Integer age;
}

如果不正确,则会报错。

JSR303校验

多环境配置以及配置文件位置

application.yaml 文件可以放在:(优先级从高到低)

image-20220105201738841

SpringBoot Web 开发

Controller:@Controller

Dao:@Repository,使用 Dao 层,需要加上 @Autowired 注解

静态资源的导入

放在 resources/[public, resources, static] 都行

其中优先级从高到低

  1. resources:存放上传文件
  2. static:存放静态资源,图片
  3. public:存放公共资源,大家都会访问的 js

首页和图标的定制

templates 下的页面,只能通过 Controller 下面跳转。

首页的定制

自定义 index.html 即可

图标自定义

  1. 创建 /**/favicon.ico
  2. 在 YAML 中创建 spring.mvc.favicon.enable: false

模板引擎

写一个模板,可以生成动态页面/

image-20220105222853586

Maven 依赖:

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.6.2</version>
</dependency>

将 html 存放在 templates 目录下即可。

1
xmlns:th="http://www.thymeleaf.org"

Thymeleaf 常见语法

Thymeleaf

项目实践

首页搭建

首页跳转的实现

  1. 可以使用 RequestMappering 跳转

  2. 也可以使用 MvcConfig 来配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Configuration
    @EnableWebMvc
    public class MyMVCConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("index");
    registry.addViewController("/index").setViewName("index");

    }
    }

首页配置

  1. 将 html 放在 templates 下,将 css, js 放在 static 下
  2. html 中需要加入 thymeleaf 的标签,需要加上 thymeleaf 的超链接标签

首页密码登陆

1
<p th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

当有信息回写的时候,才会触发。

配置拦截器

实现 HandlerInterceptor 的接口。

登陆成功之后,应该有用户的 session。

  1. 拦截器代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();

String userInfo = (String) session.getAttribute("userInfo");

if (userInfo == null) {
// 类似 Model 的作用
request.setAttribute("msg", "please login first");
request.getRequestDispatcher("/").forward(request, response); // 转发请求
return false;
}
else {
return true;
}
}
}
  1. 需要在 login 代码中添加 HttpSession session,然后给 session 添加值

  2. 需要在 MvcConfig 中配置拦截器

    1
    2
    3
    4
    5
    6
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginHandlerInterceptor())
    .addPathPatterns("/sys/*", "/servlet/*")
    .excludePathPatterns("/servlet/login");
    }
  3. html 取出 session 的值,需要 <p>hello, [[${session.userInfo}]]</p> ,使用 [[${}]] 来操作。

CRUD

R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<table class="table table-strip table-sm">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>department</th>
</tr>
</thead>
<tbody>

<tr th:each="emp : ${employeeList}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getName()}"></td>
<td th:text="${emp.getDepartment()}"></td>
</tr>
</tbody>
</table>
CUD

需要使用 form 表单。如果使用 JavaBean 传递参数的话,建议使用 @PostMapping 接受参数。

1
2
3
4
5
6
7
@RequestMapping("/servlet/update")
// 从前端获取到参数
public String employeeUpdate(int id, Employee employee) {
// Controller 传递给 service / dao 层
employeeDao.updateEmployee(id, employee);
return "redirect:/sys/home.html";
}

跳转、action、重定向全部都是经过 servlet

处理 404 / 500

只需要在 templates 下建立 error 文件夹。然后将 404 / 500 放在该文件夹下即可。

集成数据库

添加驱动

image-20220106202050909

  1. 配置数据库连接文件

    1
    2
    3
    4
    5
    6
    spring:
    datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://47.101.155.92:3306/mybatis?useSSL=true
    username: bus
    password: 123

    如果出错的话,需要添加时区。

    自动产生对象 datasource

    1
    2
    3
    4
    5
    6
    7
    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() {
    System.out.println(dataSource.getClass());
    }
  2. 整合 Druid 数据源

    导入 Maven

    1
    2
    3
    4
    5
    6
    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
    </dependency>

    配置 YAML

    1
    2
    3
    4
    5
    6
    7
    spring:
    datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://47.101.155.92:3306/mybatis?useSSL=true
    username: bus
    password: 123
    type: com.alibaba.druid.pool.DruidDataSource

    配置 Druid

    不太想配((((

  3. MyBatis

    Maven 配置,帮助 Spring Boot 快速配置 MyBatis

    1
    2
    3
    4
    5
    6
    7
    <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.1</version>
    </dependency>

    application.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    spring:
    datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://47.101.155.92:3306/mybatis?useSSL=true
    username: bus
    password: 123
    # 整合 mybatis
    mybatis:
    type-aliases-package: com.example.databases.pojo
    mapper-locations: classpath:mybatis/Mapper/*.xml

    UserMapper.xml

    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="com.example.databases.Mapper.UserMapper">
    <select id="queryStudentList" resultType="Student">
    SELECT * FROM mybatis.student
    </select>
    </mapper>

    DAO:UserMapper 接口

    1
    2
    3
    4
    5
    6
    7
    @Mapper
    // 注解表示这是一个 mybatis 的 mapper 类
    @Repository
    // 注解表示这是一个 dao 层的类
    public interface UserMapper {
    List<Student> queryStudentList();
    }

    Controller:StudentController

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @RestController
    public class StudentController {
    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/query")
    public List<Student> query() {
    List<Student> students = userMapper.queryStudentList();
    for (Student student : students) {
    System.out.println(student);
    }
    return students;
    }
    }

Shiro

Apache Shiro 是 Java 的一个安全框架。Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境。Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等。这不就是我们想要的嘛,而且 Shiro 的 API 也是非常简单;

  1. 导入 maven 依赖

  2. 编写 shiro.ini 配置文件

  3. SQL 使用对象传递参数

返回 response

1
2
3
4
5
6
@RequestMapping("/servlet/api")
@ResponseBody
public Employee test() {
Employee employee = new Employee("hello", "world", 10);
return employee;
}