XML简介
何为 XML
- XML是可扩展的标记性语言
XML的作用
- 用来保存数据,且这些数据具有描述性
- 可以作为项目、模块的配置文件
- 可以作为网络传输的数据格式(现在用 JSON)
// students.xml
<students>
<student>
<id>1</id>
<name>花花</name>
</student>
<student>
<id>2</id>
<name>花儿</name>
</student>
</students>
XML语法
- 文档声明
- 元素(标签)
- xml属性
- xml注释
- 文本区域(CDATA区)
<?xml version="1.0" encoding="UTF-8" ?>
<!--
以上内容就是 XML文件的声明
version="1.0" 表示 xml的版本
encoding="UTF-8" 表示 xml文件本身的编码
-->
<!-- books表示多个图书信息 -->
<books>
<!-- book 表示单个图书信息 -->
<book sn="SN645148461234512">
<name>时间简史</name>
<author>霍金</author>
<price>78$</price>
</book>
<book sn="SN6451496161234512">
<name>Java从入门到出门</name>
<author>花花</author>
<price>88$</price>
</book>
</books>
文档声明
<?xml version="1.0" encoding="UTF-8" ?>
元素(标签)
何为 xml元素:
XML元素指的是从(且包括)开始标签直到(且包括)结束标签的部分;元素可包含其它元素、文本或者两者的混合物,元素也可以有属性
XML元素命名规则:
- 名称可以含字母、数字及其它字符
- 名称不能以数字、标点符号或 XML字符开始
- 名称不能包含空格
XML中的元素(标签)也分为单标签和双标签
- 单标签:<标签名 属性="值" 属性="值" ... />
- <book sn="SN61548616516451" name="必雷真" author="必爷" price="9999" />
- 双标签:<标签名 属性="值" ...>文本数据、子标签</标签名>
xml属性
xml的属性和 html的标签属性是非常类似的,属性可以提供元素的额外信息;
- 在标签上可以书写属性
- 一个标签上可以书写多个属性,
每个属性的值必须使用 引号引起来
语法规则
- 所有 XML元素都必须有关闭标签
- XML标签对大小写敏感
- XML中标签必须正确的嵌套
- XML文档必须有根元素
- XML中的特殊元素:<-<, >->
- 文本区域(CDATA区)语法:<![CDATA[这里可以将输入的字符原样显示,不会解析]]>
xml解析技术介绍
xml是可扩展的标记语言。不管是 html文件还是 xml文件他们都是标记型文档,都可以使用 w3c组织指定的 dom技术来解析。document对象表示是整个文档(可以是 html文档,也可以是 xml文档)
- 早期 JDK为我们提供了两种 xml解析技术 DOM和 SAX
- 第三方解析:
- jdom在 dom基础上进行了封装
- dom4j又对 jdom进行了封装
- pull主要用在 Android手机开发
dom4j解析技术 ★
dom4j类库的使用
package com.atguitu.pojo;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* @author lv
* @create 2021-07-12 21:31
*/
public class Dom4jTest {
@Test
public void test1 () throws Exception {
// 创建一个 SAXReader输入流,读取 xml配置文件,生成 Document对象
SAXReader reader = new SAXReader();
try {
Document document = reader.read("src/books.xml");
System.out.println(document);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取 books.xml文件,生成 book类
*/
@Test
public void test2 () {
// 1.读取 books.xml文件
SAXReader reader = new SAXReader();
ArrayList<Book> books = new ArrayList<>();
try {
// 在 junit测试中,相对路径是从模块名开始计算
Document document = reader.read("src/books.xml");
// 2.通过 Document对象获取根元素
Element rootElement = document.getRootElement();
// 3.通过根元素获取 book标签对象
// System.out.println(rootElement);
// element()和 elements()都是通过标签名查找子元素
List<Element> bookList = rootElement.elements("book");
// 遍历,方式一:
// bookList.forEach(System.out :: println);
// 遍历,方式二:
for (Element book : bookList) {
// asXML():将标签对象转换为标签字符串
// System.out.println(book.asXML());
Element nameElement = book.element("name");
// System.out.println(nameElement.asXML());
// 获取文本内容
// getText():获取标签中的文本内容
String nameText = nameElement.getText();
// Element authorElement = book.element("author");
// String authorText = authorElement.getText();
// elementText():直接获取指定标签名的内容
String authorText = book.elementText("author");
Element priceElement = book.element("price");
String priceText = priceElement.getText();
// System.out.println("name: " + nameText + " author: " + authorText + " price: " + priceText);
// 获取属性
// attribute()、attributeValue()
// Attribute sn = book.attribute("sn");
// String snValue1 = sn.getValue();
String snValue = book.attributeValue("sn");
// 4.遍历,处理每个 book标签转化为 Book类
// Double.parseDouble
// new BigDecimal(double)
books.add(new Book(snValue, nameText, authorText, new BigDecimal(Double.parseDouble(priceText))));
}
books.forEach(System.out :: println);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Tomcat
JavaWeb的概念
-
JavaWeb:指所有通过 Java语言编写,可以通过浏览器访问的程序的总称;JavaWeb是基于请求和响应来开发的。
-
请求:指客户端向服务器端发送数据,叫请求 request
-
响应:指服务器端给客户端回传数据,叫响应 response
-
请求和响应的关系:请求和响应是成对出现的,有请求就有响应
Web资源的分类
web资源按实现的技术和呈现的效果不同,可以分为 静态资源和 动态资源两种。
- 静态资源:html、css、js、txt、视频、图片
- 动态资源:jsp页面、Servlet程序
常用的 Web服务器
- Tomcat:由 Apache 组织提供的一种 Web 服务器,提供对 jsp 和 Servlet 的支持。它是一种轻量级的
javaWeb 容器(服务器),也是当前应用最广的 JavaWeb 服务器(免费)。 - Jboss:是一个遵从 JavaEE 规范的、开放源代码的、纯 Java 的 EJB 服务器,它支持所有的 JavaEE 规范(免费)。
- Resin:是 CAUCHO 公司的产品,是一个非常流行的服务器,对 servlet 和 JSP 提供了良好的支持, 性能也比较优良,resin 自身采用 JAVA 语言开发(收费,应用比较多)。
- GlassFish: 由 Oracle 公司开发的一款 JavaWeb 服务器,是一款强健的商业服务器,达到产品级质量(应用很少)。
- WebLogic:是 Oracle 公司的产品,是目前应用最广泛的 Web 服务器,支持 JavaEE 规范, 而且不断的完善以适应新的开发要求,适合大型项目(收费,用的不多,适合大公司)。
Tomcat服务器和 Servlet版本的对应关系
当前企业常用版本 7.* / 8.*
| Tomcat | Servlet/JSP版本 | JavaEE | 运行环境 |
|---|---|---|---|
| 5.5/6.0 | 2.5/2.1 | 5.0 | JDK5.0 |
| 7.0 | 3.0/2.2 | 6.0 | JDK6.0 |
| 8.0 | 3.1/2.3 | 7.0 | JDK7.0 |
- Servlet程序从 2.5版本是现在市面上使用最多的版本(xml配置)
- Servlet3.0后,就是注解版本的 Servlet使用
Tomcat的使用
安装
- 目录介绍
- bin:存放 Tomcat服务器的可执行程序
- conf:存放 Tomcat服务器的配置文件
- lib:存放 Tomcat服务器的 jar包
- logs:存放 Tomcat服务器运行时输出的日志
- temp:存放 Tomcat运行时产生的临时数据
- webapps:存放部署的 Web工程
- work:Tomcat工作时的目录,用来存放 Tomcat运行时 jsp翻译为 Servlet的源码,和 Session钝化(序列化,将对象写到磁盘上)的目录
- 启动 Tomcat服务器
- 方式一:在 Tomcat目录下的 bin目录下的 startup.bat,双击就可以启动 Tomcat
- 方式二:在 Tomcat目录的 bin目录下 输入命令 catalina run
- 测试 Tomcat服务器启动成功:http://localhost:8080,http://127.0.0.1:8080,http://计算机ip:8080
- Tomcat的停止
- 方式一:点击 Tomcat服务器的关闭按钮
- 方式二:选中 Tomcat服务器窗口 按 ctrl + c
- 方式三:找到 Tomcat下的 bin目录下的 shutdown.bat,双击停止 Tomcat服务器
- 修改 Tomcat的端号
- 默认端口号是:8080
- Tomcat目录下 conf目录,找到 server.xml文件中的 Connector标签的 port属性
- 端口号范围是 1 - 65535
- http协议默认的端口号是:80,不会在地址中显示
- 部署 web工程到 Tomcat中
- 方式一:将 web工程的文件夹拷贝到 Tomcat的 webapps目录下即可;并在浏览器地址中输入对应的文件夹名称和文件名就能访问
- 方式二:在 Tomcat下的 conf\Catalina\localhost中新建 xxx.xml文件
// 访问路径:http://localhost:8080/abc/index.html <!-- 1. Context表示一个工程的上下文 2. path表示工程的访问路径 /abc 3. docBase表示真正的工程目录的磁盘位置 --> <Context path="/abc" docBase="D:\book"> - 手拖 html页面到浏览器和在浏览器中输入 http://... 访问的区别
- 手拖 html页面到浏览器,使用的是 file:///E:/... 协议,浏览器会直接读取 html文件的路径进行渲染,不会出现网络请求
- 在浏览器输入 http://... 协议,浏览器会向服务器端发起请求,服务器端收到请求后,读取所需资源文件,然后响应给客户端需要的页面内容,浏览器得到页面内容后解析并展示在浏览器上
- ROOT工程的访问,以及默认 index.html页面的访问
- http://ip:port ,没有工程名时,默认访问的时 ROOT工程
- http://ip:port/工程名/ ,没有资源名时,默认访问 index.html页面
IDEA整合 Tomcat服务器
- File | Settings | Build, Execution, Deployment | Application Servers
- 点击 + 号添加 服务器
IDEA中动态 web工程的操作
IDEA中创建动态 web工程
- 创建一个新模块 Module
- 选择 Java Enterprise、勾选 Web Application,其它默认
- 点击完成
Web工程目录介绍
- 目录结构:
|-- 05_web
|-- src
|-- web
|-- index.jsp
|-- WEB-INF
|-- lib
|-- web.xml
- src:存放项目的源代码
- web:存放 web工程资源文件,html、css、js、图片等
- WEB-INF:一个受服务器保护的目录,浏览器无法直接访问此目录的内容
- web.xml:整个 web动态工程的配置部署描述文件,可以配置很多 web工程的组件,如:Servlet、Filter、Listener、Session超时等 ...
- lib:存放第三方的 jar包(IDEA需要自己配置导入)
给动态 web工程添加额外 jar包
- 将 jar包放到 lib文件夹中,右击选择 Add as library选项,选择 Module模块
在 IDEA中部署工程到 Tomcat上运行
- 修改 web工程对应的 Tomcat的服务器的名字,改成和 web工程同名
- 在 Deployment选项中确认你的 Tomcat实例中有你要部署运行的 web工程模块
- 启动:点击 当前 web工程服务器右边的
箭头,就能启动 当前web工程
修改工程路径的访问
- Development -> Application context: /05_web
修改运行的端口号
- 在服务器中选择 Edit Configurations,修改端口号
修改运行使用的浏览器
- 在服务器中选择 Edit Configurations,修改默认浏览器
配置资源热部署
- 在服务器中选择 Edit Configurations,选择 Update classes and resources
Servlet
Servlet技术
什么是Servlet
- Servlet是 JavaEE规范之一,规范就是接口
- Servlet是 JavaEE三大组件之一;三大组件分别是:Servlet、Filter、Listener
- Servlet是运行在服务器上的一个 java程序,
它可以接收客户端发送过来的请求,并响应数据给客户端
手动实现 Servlet程序
- 编写一个类区去实现 Servlet接口
- 实现 service方法,处理请求,并响应数据
- 到 web.xml中去配置 servlet程序的访问地址
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--servlet标签给 Tomcat配置 Servlet程序-->
<servlet>
<!--此标签的作用是给 Servlet程序起一个别名(一般是类名)-->
<servlet-name>HelloServlet</servlet-name>
<!--此标签的作用是 Servlet程序的全类名-->
<servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
</servlet>
<!--给 Servlet程序配置访问地址-->
<servlet-mapping>
<!--此标签的作用是告诉服务器,当前配置的地址给哪个 Servlet程序使用,要求与上面的 name一致-->
<servlet-name>HelloServlet</servlet-name>
<!--
此标签的作用是配置访问地址
/:此斜杠在服务器解析时,表示地址为:http://ip:port/工程路径
/hello:表示地址为 http://ip:port/工程路径/hello
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
url地址到 Servlet程序的访问
Servlet的生命周期
- 执行 Servlet构造器方法
- 执行 init初始化方法
- 执行 service方法
- 执行 destroy销毁方法
说明:
- 第一、二步,只会在第一次访问时创建 Servlet程序会调用
- 第三步,每次访问都会调用
- 第四步,在 web工程停止时会调用
GET和 POST请求的分发处理
- 通过 getMethod方法判断,并分开处理
package com.atguigu.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-18 16:37
*/
public class HelloServlet implements Servlet {
public HelloServlet() {
System.out.println("1.构造器");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.init初始化");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service方法是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3.service - Hello Servlet 被访问了");
// 强制类型转换,重要,下面有解释
HttpServletRequest hsr = (HttpServletRequest) servletRequest;
// 获取请求方式
String hsrMethod = hsr.getMethod();
System.out.println(hsrMethod);
if ("GET".equals(hsrMethod)) {
doGet();
} else if ("POST".equals(hsrMethod)) {
doPost();
}
}
// 处理 get请求
public void doGet () {
System.out.println("doGET");
}
// 处理 post请求
public void doPost () {
System.out.println("doPOST");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4.destroy销毁");
}
}
重要
HttpServletRequest和ServletRequest都是接口,他们都只是定义了方法却没有提供相关实现。所以我们看到的ServletRequest request中的request对象其实并不是我们ServletRequest 的一个具体实现。
其实主要看request 对象的具体实现类究竟是继承的哪个接口,如果继承自HttpServletRequest接口那么我们向下转型使用HttpServletRequest接口的方法就是安全的。
在service的参数request对象的生成方式不是ServletRequest request = new ServletRequest();这种形式,而是ServletRequest request = new HttpServletRequest();这种形式,参数里的request不是父类ServletRequest的对象,而是HttpServletRequest的上转型对象。
根据《java面向对象程序设计(第2版)》,一个父类类型的对象如果是用子类new出来的时候(ServletRequest request = new HttpServletRequest();//就是这行代码), 就不能称之为父类对象,而是一个子类的上转型对象。这两者是有区别的,区别的其中一点就是父类对象不可强制转换为子类对象,而子类的上转型对象可以强制转换回子类对象。
通过继承 HttpServlet实现 Servlet程序
一般在实际项目开发中,都是使用继承 HttpServlet类的方式去实现 Servlet程序
- 编写一个类去继承 HttpServlet类
- 根据业务需要重写 doGet、doPost方法
- 到 web.xml中配置 Servlet程序的访问地址
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-19 20:50
*/
public class HelloServlet3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doPost");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet");
}
}
使用 IDEA创建 Servlet程序
- 选中类的包名 右击,NEW,选择 Servlet
Servlet类的继承体系
- Interface Servlet:Servlet接口,只是负责定义 Servlet程序的访问规范
- Class GenericServlet:此类实现了 Servlet接口,做了很多空实现;并持有一个 ServletConfig类的引用
- Class HttpServlet:此类继承了 GenericServlet类,实现了 service()方法,并实现了请求的分发处理
- 自定义的 Servlet程序:继承了 HttpServlet类,并根据业务需要重写了 doGet、doPost方法
ServletConfig类
ServletConfig类从类名上看,就知道是 Servlet程序的配置信息类
Servlet类从类名来看,就知道是 Servlet程序的配置信息类
Servlet程序默认是第一次访问的时候创建,ServletConfig是每个 Servlet程序创建时,就创建一个对应的 ServletConfig对象
ServletConfig类的三大作用,在 init初始化方法中使用
- 可以获取 Servlet程序的别名 servlet-name的值
- 获取初始化参数 init-param
- 获取 ServletContext对象
package com.atguigu.servlet;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-18 16:37
*/
public class HelloServlet implements Servlet {
public HelloServlet() {
System.out.println("1.构造器");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2.init初始化");
// 1. 可以获取 Servlet程序的别名 servlet-name的值
System.out.println("Servlet程序的别名:" + servletConfig.getServletName());
// 2. 获取初始化参数 init-param
System.out.println("初始化参数:username:" + servletConfig.getInitParameter("username"));
System.out.println("初始化参数:url:" + servletConfig.getInitParameter("url"));
// 3. 获取 ServletContext对象
System.out.println("获取 ServletContext对象:" + servletConfig.getServletContext());
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* service方法是专门用来处理请求和响应的
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("3.service - Hello Servlet 被访问了");
HttpServletRequest hsr = (HttpServletRequest) servletRequest;
// 获取请求方式
String hsrMethod = hsr.getMethod();
System.out.println(hsrMethod);
if ("GET".equals(hsrMethod)) {
doGet();
} else if ("POST".equals(hsrMethod)) {
doPost();
}
}
// 处理 get请求
public void doGet () {
System.out.println("doGET");
}
// 处理 post请求
public void doPost () {
System.out.println("doPOST");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4.destroy销毁");
}
}
ServletContext类
何为 ServletContext
- ServletContext是一个接口,它表示 Servlet上下文对象
一个 web工程,只有一个 ServletContext对象实例- ServletContext对象是一个域对象
- ServletContext是在 web工程部署启动时创建,在 web工程停止时销毁
- 在 ServletContext中存入一个属性,那在工程停止运行之前,任何地方都能访问到存入的属性
域对象 域对象,是可以像 Map一样存取数据的对象,叫域对象;这里的域指的是存取数据的操作范围,整个 web工程。
| 操作对象 | 存数据 | 取数据 | 删除数据 |
|---|---|---|---|
| Map | put() | get() | remove() |
| 域对象 | setAttribute() | getAttribute() | removeAttribute() |
ServletContext类的四个作用
- 获取 web.xml中配置的上下文参数 context-param
- 获取当前的工程路径,格式:/工程路径
- 获取工程部署后在服务器硬盘上的绝对路径
- 像 Map一样存取数据
// ContextServlet
package com.atguigu.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-20 22:12
*/
public class ContextServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 4. 像 Map一样存取数据,doGet()
ServletContext servletContext = getServletContext();
servletContext.setAttribute("key1", "values");
Object key1 = servletContext.getAttribute("key1");
System.out.println("key1: " + key1);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 获取 web.xml中配置的上下文参数 context-param
ServletContext servletContext = getServletConfig().getServletContext();
String username = servletContext.getInitParameter("username");
System.out.println("username:" + username); // username:context
// 2. 获取当前的工程路径,格式:/工程路径
String contextPath = servletContext.getContextPath();
System.out.println("contextPath: " + contextPath); // contextPath:
// 3. 获取工程部署后在服务器硬盘上的绝对路径
/**
* "/":表示被服务器解析地址为: http://ip:port/工程名/ -> 映射到 IDEA代码的 web目录
*/
String realPath = servletContext.getRealPath("/");
// realPath:E:\java_workspace\JavaWeb\out\artifacts\06_servlet_war_exploded\
System.out.println("realPath:" + realPath);
String realPath1 = servletContext.getRealPath("/css");
System.out.println("工程目录下的 css目录:" + realPath1);
// 工程目录下的 css目录:E:\java_workspace\JavaWeb\out\artifacts\06_servlet_war_exploded\css
// 4. 像 Map一样存取数据,doPost()
}
}
// ContextServlet2
package com.atguigu.servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-20 23:10
*/
public class ContextServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
Object key1 = servletContext.getAttribute("key1");
System.out.println("get-key1: " + key1);
}
}
Http协议
何为Http协议
所谓 Http协议是指,客户端和服务器端之间通信时,发送的数据,需要遵守的规则,叫 Http协议;Http协议中的数据又叫报文。
请求的 Http协议的格式
- 客户端给服务端发送数据叫请求
- 服务端给客户端回传数据叫响应
- 请求又分为 GET请求和 POST请求
GET请求
请求行
- 请求的方式:get
- 请求路径:
请求的资源路径[ + ? + 请求参数 ] - 请求的协议的版本号:HTTP/1.1
请求头:主要作用是告诉服务器,当前浏览器的一些信息
- 由 key : value组成不同的键值对,表示不同的含义
- Accept:告诉服务器,客户端可以接收的数据类型
- Accept-Language:告诉服务器,客户端可以接收的语言类型
- User-Agent:浏览器的信息
- Accept-Encoding:告诉服务器,客户端可以接收的数据编码(压缩)格式
- Host:表示请求的服务器 ip和端口号
- Connection:告诉服务器,请求连接如何处理(Keep-Alive、Closed)
POST请求
请求行
- 请求方式:post
- 请求路径:
请求的资源路径[ + ? + 请求参数 ] - 请求协议的版本号:HTTP/1.1
请求头
- key : value
- Content-Type:表示发送的数据的类型
- form-urlencoded:表示提交的格式是 name=value&name=value,然后对其进行 url编码;url编码是把 非英文内容转换为 %xx%xx
- form-data:表示以多端的形式提交数据给服务器(以流的形式提交,用于上传)
- Cache-Control:表示如何控制缓存(no-cache不缓存)
请求体
- 发送给服务器的数据
get请求和 post请求的区分
Get请求:
- form标签 method=get
- a标签
- link标签引入 css
- script标签引入 js文件
- img标签导入图片
- iframe引入 html页面
- 在浏览器地址栏输入地址后回车
Post请求:
- form标签 method=post
响应的 Http协议格式
响应行:
- 响应的协议和版本号:HTTP/1.1
- 响应状态码:200
- 响应状态描述符:OK
响应头:
- key : value
- Server:表示服务器的信息
- Content-Type:表示响应体的数据类型
响应体:
- 回传给客户端的数据
常用的响应码说明
- 200:请求成功
- 302:请求重定向
- 404:请求服务器已经收到,但请求地址错误
- 500:服务器已经收到请求,但服务器内部错误
MIME类型说明
MIME的英文全称是 'Multipurpose Innternet Mail Extensions'多功能 Internet邮件扩充服务;MIME类型的格式是 '大类型/小类型',并与某一种文件的扩展名相对应。
- MIME是 Http协议中数据类型
常见 MIME类型:
| 文件 | MIME类型 |
|---|---|
| 超文本标记语言文本 | .html、.htm - text/html |
| 普通文本 | .txt - text/plain |
| RTF文本 | .rtf - application/rtf |
| GIF图形 | .gif - image/gif |
| JPEG图形 | .jpeg、.jpg - image/jpeg |
| au声音文件 | .au - audio/basic |
| MIDI音乐文件 | .mid、.midi - audio/midi,audio/x-midi |
| RealAudio音乐文件 | .ra、.ram - audio/x-pn-realaudio |
| MPEG文件 | .mpg、.mpeg - video/mpeg |
| MIDI音乐文件 | .mid、.midi - audio/midi,audio/x-midi |
| AVI文件 | .avi - video/x-msvideo |
| GZIP文件 | .gz - application/x-gzip |
| TAR文件 | .tar - application/x-tar |
HttpServletRequest类
- 在HelloServlet2.java的 doGet、doPost中出现
HttpServletRequest类的作用
每次只要有请求进入 Tomcat服务器,Tomcat服务器就会把请求过来的 HTTP协议信息解析好封装到 Request对象中;然后传递到 service方法(doGet、doPost)中给我们使用;我们可以通过 HttpServletRequest对象,获取到所有请求的信息。
HttpServletRequest类的常用方法
- getRequestURI():获取请求的工程及资源路径
- getRequestURL():获取请求的统一资源定位符(绝对路径)
- getRemoteHost():获取客户端的 ip地址
- getHeader():获取请求头
- getParameter():获取请求的参数
- getParameterValues():获取请求的参数(多个值的时候使用)
- getMethod():获取请求的方式 get、post
- setAttribute(key, value):设置域数据
- getAttribute(key):获取域数据
- getRequestDispatcher():获取请求转发对象
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-22 21:37
*/
public class RequestAPIServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
// - getRequestURI():获取请求的工程及资源路径
System.out.println("URI:" + req.getRequestURI()); // URI:/request
// - getRequestURL():获取请求的统一资源定位符(绝对路径)
System.out.println("URL:" + req.getRequestURL()); // URL:http://localhost:8080/request
// - getRemoteHost():获取客户端的 ip地址
System.out.println("Host:" + req.getRemoteHost()); // Host:127.0.0.1
// - getHeader():获取请求头
System.out.println("Header:" + req.getHeader("User-Agent"));
// - getParameter():获取请求的参数
// System.out.println("Parameter:" + req.getParameter());
// - getParameterValues():获取请求的参数(多个值的时候使用)
// System.out.println("ParameterValues:" + req.getParameterValues());
// - getMethod():获取请求的方式 get、post
System.out.println("Method:" + req.getMethod()); // Method:GET
}
//
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
System.out.println("doPost");
}
}
获取请求参数
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
/**
* @author lv
* @create 2021-07-22 22:09
*/
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("doGet");
// 获取请求的参数:
System.out.println("user:" + req.getParameter("user"));
System.out.println("password:" + req.getParameter("password"));
// System.out.println("hobby:" + req.getParameter("hobby"));
System.out.println("hobby:" + Arrays.asList(req.getParameterValues("hobby"))); // hobby:[cpp, java, js]
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
System.out.println("doPost");
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8080/param" method="get">
<input name="user" value="root" />
<input name="password" value="root123" />
<input type="checkbox" name="hobby" value="cpp" />c++
<input type="checkbox" name="hobby" value="java" />java
<input type="checkbox" name="hobby" value="js" />js
<input type="submit" />
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>RequestAPIServlet</servlet-name>
<servlet-class>com.atguigu.servlet.RequestAPIServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestAPIServlet</servlet-name>
<url-pattern>/request</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ParameterServlet</servlet-name>
<servlet-class>com.atguigu.servlet.ParameterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ParameterServlet</servlet-name>
<url-pattern>/param</url-pattern>
</servlet-mapping>
</web-app>
POST请求的中文乱码解决
- 设置请求体的字符集为 UTF-8,从而解决 post请求的中文乱码问题
- req.setCharacterEncoding("UTF-8")
- 它必须在获取请求参数之前设置才有效
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
/**
* @author lv
* @create 2021-07-22 22:09
*/
public class ParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("doGet");
// 获取请求的参数:
System.out.println("user:" + req.getParameter("user"));
System.out.println("password:" + req.getParameter("password"));
// System.out.println("hobby:" + req.getParameter("hobby"));
System.out.println("hobby:" + Arrays.asList(req.getParameterValues("hobby"))); // hobby:[cpp, java, js]
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
System.out.println("doPost");
/**
* 设置请求体的字符集为 UTF-8,从而解决 post请求的中文乱码问题
* 它必须在获取请求参数之前调用才有效
*/
req.setCharacterEncoding("UTF-8");
// 获取请求参数
String user = req.getParameter("user");
String password = req.getParameter("password");
String[] hobbies = req.getParameterValues("hobby");
System.out.println("user:" + user);
System.out.println("password:" + password);
System.out.println("hobbys:" + Arrays.asList(hobbies));
}
}
请求的转发
请求转发是指,服务器收到请求后,从当前资源跳转到另一个资源的操作叫请求转发。
- 使用 getRequestDispatcher()作请求转发
// Servlet1
package com.atguigu.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-27 21:51
*/
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("servlet1");
// 1.获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("在 servlet1中查看材料 username:" + username);
// 2.给请求添加参数
// 方式一:getServletContext
// ServletContext context = getServletContext();
// context.setAttribute("keys", "servlet1");
// 方式二:
req.setAttribute("keyServlet1", "servlet1");
// 3.转发到 servlet2资源
// getRequestDispatcher的参数必须加 '/',表示的地址为:http://ip:port/工程名/
RequestDispatcher dispatcher = req.getRequestDispatcher("/servlet2");
// RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/form1.html");
dispatcher.forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
// Servlet2
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-27 21:54
*/
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("servlet2");
// 1.获取请求参数
String username = req.getParameter("username");
// 2.获取在 Servlet1中添加的参数
Object keyServlet1 = req.getAttribute("keyServlet1");
System.out.println("servlet1添加的参数:" + keyServlet1);
// 3.处理自己的业务
System.out.println("处理自己的业务");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
特点:
- 浏览器地址栏没有变化
- 它们一共算一次请求
- 它们共享 Request域中的数据
- 可以转发到 WEB-INF目录下
- 不能访问工程以外的资源
所有相对路径在工作时,都会参照当前浏览器地址栏中的地址进行跳转,所以在使用请求转发的方式进行跳转时可能会出错,可以使用 base标签的 herf属性值作为相对路径的参照路径。
- 设置当前页面中相对路径工作时参照的地址
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<div>
这是 web下的 index.html页面
<br />
<a href="a/b/c.html">跳转到c.html</a>
<br />
<a href="http://localhost:8080/forwardc">请求转发到c.html</a>
</div>
</body>
</html>
// c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--
base标签:设置当前页面中相对路径工作时参照的地址
href属性就是参照的地址值
-->
<base href="http://localhost:8080/a/b/" />
</head>
<body>
<div>
这是 /a/b/c.html页面<br />
<a href="../../index.html">跳回首页</a>
</div>
</body>
</html>
// ForwardC
package com.atguigu.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-07-28 22:38
*/
public class ForwardC extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("ForwardC");
RequestDispatcher dispatcher = req.getRequestDispatcher("/a/b/c.html");
dispatcher.forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
web 中的相对路径和绝对路径
在 JavaWeb 中,路径分为相对路径和绝对路径:
- 相对路径:
- ',' 表示当前目录
- '..' 表示上一级目录
- 资源名,表示当前目录/资源名
web 中 / 斜杠的不同意义
- 在 web中 / 斜杆是一种绝对路径。
- 斜杠,如果被浏览器解析,得到地址是:http://ip:port/
<a href="/">斜杠</a> - 斜杠,如果被服务器解析,得到的地址是:http://ip:port/工程路径
<url-pattern>/param</url-pattern> - 特殊情况:response.sendRedirect("/"),将斜杠发送给浏览器,得到 http://ip:port/ 地址
HttpServletResponse 类
HttpServletResponse 类的作用
HttpServletResponse 类和 HttpServletRequest 类一样,每次请求进来,Tomcat服务器都会创建一个 Response 对象,传递给 Servlet程序去使用;HttpServletRequest 类表示请求过来的信息,HttpServletResponse 类表示所有响应的信息。
我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 类来进行设置。
两个输出流的说明
- 字节流:getOutputStream(),常用于下载(传递二进制数据)
- 字符流:getWriter(),常用于传递字符串(常用) 注意:两者在使用时,只能二选一,否则会报错。
向客户端回传数据
要求:向客户端回传 字符串数据。
PrintWriter respWriter = resp.getWriter();
// resp.getOutputStream();
// 向客户端回传 字符串数据。
respWriter.write("response`s content!");
解决客户端回传数据在浏览器展示乱码问题
方式一:
- resp.getCharacterEncoding(); 获取响应默认的字符集
- resp.setCharacterEncoding("UTF-8"); 设置服务器响应的字符集:UTF-8
- resp.setHeader("Content-Type", "text/html; charset=UTF-8"); 设置浏览器使用的字符集,通过响应头
方式二:推荐
- resp.setContentType("test/html; charset=UTF-8"); 它会同时设置 服务器和客户端使用同样的字符集 UTF-8
- 注意:此方法一定要在获取流对象之前设置才有效
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author lv
* @create 2021-07-31 17:34
*/
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取响应默认的字符集
System.out.println("响应的字符集:" + resp.getCharacterEncoding()); // 响应的字符集:ISO-8859-1
// 方式一:
// 设置服务器响应的字符集:UTF-8
// resp.setCharacterEncoding("UTF-8");
// 设置浏览器使用的字符集,通过响应头
// resp.setHeader("Content-Type", "text/html; charset=UTF-8");
// 方式二:它会同时设置 服务器和客户端使用同样的字符集 UTF-8
// 注意:此方法一定要在获取流对象之前设置才有效
resp.setContentType("test/html; charset=UTF-8");
// super.doGet(req, resp);
PrintWriter respWriter = resp.getWriter();
// resp.getOutputStream();
// 向客户端回传 字符串数据。
respWriter.write("response`s content!");
}
}
请求重定向
请求重定向是指,客户端给服务器端发送请求,服务器收到请求后告诉客户端,我给你一个地址,你去访问这个新地址,这叫请求重定向(因为旧的地址已被废弃)。
重定向中客户端和服务器的内部操作
- 服务器告诉客户端,我已更改地址,响应码 302,新的地址,响应头 Location
- 客户端收到服务器返回的响应码 302和新地址后,自动通过新地址再次发起请求
- 服务器收到请求并返回给客户端
方式一:
- resp.setStatus(302); 设置响应头,表示重定向
- resp.setHeader("Location", "http://localhost:8080/response2"); 设置响应头,说明新的地址
方式二:
- resp.sendRedirect("http://localhost:8080/response2");
// Response1
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author lv
* @create 2021-08-01 17:53
*/
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("重定向-Response1");
// 方式一:
// 设置响应头,表示重定向
// resp.setStatus(302);
// 设置响应头,说明新的地址
// resp.setHeader("Location", "http://localhost:8080/response2");
// 不能访问 WEB-INF下的资源
// resp.setHeader("Location", "http://localhost:8080/WEB-INF/form1.html");
// 方式二:
resp.sendRedirect("http://localhost:8080/response2");
}
}
// Response2
package com.atguigu.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author lv
* @create 2021-08-01 17:53
*/
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
System.out.println("Response2");
// resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8");
PrintWriter respWriter = resp.getWriter();
respWriter.write("重定向成功,欢迎回家!");
}
}
重定向的特点
- 浏览器地址栏会发生变化
- 浏览器会发出两次请求
- 不能共享 Request域中的数据(每次的 Request请求都是新生成的)
- 不能访问 WEB-INF下的资源
- 可以访问工程外的资源
实际操作
用户的登录和注册
JavaEE项目的三层架构
Web层/视图展示层
- 获取请求参数,封装为 Bean对象
- 调用 Service业务层,处理业务
- 响应数据给客户端,请求转发、重定向
- 用到的技术:Servlet、SpringMVC
Service业务层
- 处理业务逻辑
- 调用持久层保存到数据库
- 用到的技术:Spring框架
DAO持久层
- DAO持久层,只负责与数据库交互
- 用到的技术:JDBC、DbUtils、Mybatis
注意:项目分层的目的是为了解耦,解耦就是为了降低代码的耦合度,方便项目后期的维护和升级。
项目分层基本目录:
- web层:com.atjava.web/servlet/controller
- service层:com.atjava.service、com.atjava.service.impl
- dao持久层:com.atjava.dao、com.atjava.dao.impl
- 实体 bean对象:com.atjava.pojo/entity/domain/bean
- 测试包:com.atjava.test/junit
- 工具类:com.atjava.utils
创建项目需要的数据库和表
DROP DATABASE IF EXISTS book_project;
CREATE DATABASE book_project;
USE book_project;
CREATE TABLE t_user(
id INT PRIMARY KEY auto_increment,
username VARCHAR(20) NOT NULL UNIQUE,
`password` VARCHAR(32) NOT NULL,
`email` VARCHAR(200)
);
INSERT INTO t_user(`username`, `password`, `email`)
VALUES('admin', 'admin', 'admin@atjava.com');
SELECT * FROM t_user;
编写数据库表对应的 JavaBean对象
public class User {
private Integer id;
private String username;
private String password;
private String email;
// ...
}
编写 工具类 JDBCUtils
- 添加 jar包:Project Structure -> Libraries -> '+' -> 选中目标 jar包
- Modules -> Dependencies -> '+' -> 'JARs or directories'
package com.atjava.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* @author lv
* @create 2021-08-02 22:33
*/
public class JDBCUtils {
private static DruidDataSource dataSource;
static {
try {
Properties properties = new Properties();
// 读取 jabc.properties属性配置文件
InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
// 加载流数据
properties.load(inputStream);
// 创建 数据库连接池
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接池中的连接
* @return
*/
public static Connection getConnection () {
Connection conn = null;
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 关闭连接,放回数据库连接池
* @param conn
*/
public static void close (Connection conn) {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
编写 BaseDao
- BeanHandler
- BeanListHandler
- ScalarHandler
package com.atjava.dao.impl;
import com.atjava.utils.JDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* @author lv
* @create 2021-08-04 21:56
*/
public abstract class BaseDao {
// 使用 DbUtils操作数据
private QueryRunner qr = new QueryRunner();
/**
* 用来操作 insert、update、delete方法
* @return
*/
public int updates (String sql, Object ...args) {
Connection conn = JDBCUtils.getConnection();
try {
return qr.update(conn, sql, args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(conn);
}
return -1;
}
/**
* 返回结果为 单个数据
* @param type
* @param sql
* @param args
* @param <T>
* @return
*/
public <T> T queryForOne (Class<T> type, String sql, Object ...args) {
Connection conn = JDBCUtils.getConnection();
try {
return qr.query(conn, sql, new BeanHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(conn);
}
return null;
}
/**
* 返回结果为 list的数据
* @param type
* @param sql
* @param args
* @param <T>
* @return
*/
public <T> List<T> queryForList (Class<T> type, String sql, Object ...args) {
Connection conn = JDBCUtils.getConnection();
try {
return qr.query(conn, sql, new BeanListHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.close(conn);
}
return null;
}
/**
* 返回一行一列的 sql数据
* @param sql
* @param args
* @return
*/
public Object queryForSingleValue (String sql, Object ...args) {
Connection conn = JDBCUtils.getConnection();
try {
return qr.query(conn, sql, new ScalarHandler(), args);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.close(conn);
}
return null;
}
}
编写 UserDao 和测试
- UserDao 接口
- UserDaoImpl 实现类
- UserDaoImplTest 测试类
- 快捷键 ctrl + shift + t:生成测试代码
package com.atjava.dao;
import com.atjava.pojo.User;
/**
* @author lv
* @create 2021-08-05 22:36
*/
public interface UserDao {
/**
* 根据用户名查询用户信息
*/
User queryUserByUsername(String username);
User queryUserByUsernameAndPassword (String username, String password);
int saveUser (User user);
}
package com.atjava.dao.impl;
import com.atjava.dao.BaseDao;
import com.atjava.dao.UserDao;
import com.atjava.pojo.User;
/**
* @author lv
* @create 2021-08-05 22:44
*
* 快捷键 ctrl + shift + t:生成测试代码
*/
public class UserDaoImpl extends BaseDao implements UserDao {
@Override
public User queryUserByUsername(String username) {
String sql = "select id, username, password, email from t_user where username = ?";
User user = queryForOne(User.class, sql, username);
return user;
}
@Override
public User queryUserByUsernameAndPassword(String username, String password) {
String sql = "select id, username, password, email from t_user where username = ? and password = ?";
User user = queryForOne(User.class, sql, username, password);
return user;
}
@Override
public int saveUser(User user) {
String sql = "insert into t_user(username, password, email)values(?, ?, ?)";
int updates = updates(sql, user.getUsername(), user.getPassword(), user.getEmail());
return updates;
}
}
package com.atjava.test;
import com.atjava.dao.UserDao;
import com.atjava.dao.impl.UserDaoImpl;
import com.atjava.pojo.User;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author lv
* @create 2021-08-05 23:00
*/
public class UserDaoImplTest {
// UserDaoImpl userDao = new UserDaoImpl();
UserDao userDao = new UserDaoImpl();
@Test
public void queryUserByUsername() {
if (null == userDao.queryUserByUsername("admin")) {
System.out.println("用户名可用");
} else {
System.out.println("用户名已存在");
}
}
@Test
public void queryUserByUsernameAndPassword() {
if (null == userDao.queryUserByUsernameAndPassword("admin", "admin")) {
System.out.println("用户不存在,请注册");
} else {
System.out.println("登录成功");
}
}
@Test
public void saveUser() {
int i = userDao.saveUser(new User(null, "admin2", "admin2", "admin2@atjava.com"));
if (-1 != i) {
System.out.println("注册成功");
} else {
System.out.println("注册失败");
}
}
}
编写 UserService
package com.atjava.service;
import com.atjava.pojo.User;
/**
* @author lv
* @create 2021-08-07 21:17
*
* service表示业务层,一个业务一个方法
*/
public interface UserService {
/**
* 注册用户
* @param user
*/
void registUser(User user);
/**
* 登录
* @param user
* @return
*/
User login(User user);
/**
* 检察用户名是否存在
* @param username
* @return
*/
boolean existsUsername(String username);
}
package com.atjava.service.impl;
import com.atjava.dao.impl.UserDaoImpl;
import com.atjava.pojo.User;
import com.atjava.service.UserService;
/**
* @author lv
* @create 2021-08-07 21:29
*/
public class UserServiceImpl implements UserService {
private UserDaoImpl userDao = new UserDaoImpl();
@Override
public void registUser(User user) {
userDao.saveUser(user);
}
@Override
public User login(User user) {
return userDao.queryUserByUsernameAndPassword(user.getUsername(), user.getPassword());
}
@Override
public boolean existsUsername(String username) {
if (null == userDao.queryUserByUsername(username)) {
return false;
}
return true;
}
}
package com.atjava.test;
import com.atjava.pojo.User;
import com.atjava.service.UserService;
import com.atjava.service.impl.UserServiceImpl;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author lv
* @create 2021-08-07 21:38
*/
public class UserServiceImplTest {
UserService us = new UserServiceImpl();
@Test
public void registUser() {
us.registUser(new User(null, "admin3", "admin3", "admin3@atjava.com"));
us.registUser(new User(null, "abc123", "abc123", "abc123@atjava.com"));
}
@Test
public void login() {
User user = us.login(new User(null, "admin", "admin", "admin@atjava.com"));
System.out.println(user);
}
@Test
public void existsUsername() {
boolean existsUsername = us.existsUsername("abc456");
if (existsUsername) {
System.out.println("用户名已存在");
} else {
System.out.println("用户名可使用");
}
}
}