代码地址:https://github.com/Autunomy/webstudy
1.HttpServlet对象
在编写web程序的时候,我们都会让自己的servlet继承于Tomcat的HttpServlet类,重写其中的service方法。我们自己编写的Servlet的对象,在全局只创建一次,也就是说Servlet对象是单例的,Servlet对象的创建是第一次访问此Servlet时创建;
2.HttpServlet中,两种service方法的区别
在tomcat的HttpServlet对象中有两个service方法,他们的权限修饰符不同
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
/*-------------------------------------------------------------------------------------------------*/
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
}
两种方法并没有本质的区别,查看源码
这里的this就是HttpServlet的protected的service方法,也就是说如果我们调用public的service方法,那么本质上还是调用的是protected的service方法
3.HttpServletRequest对象
HttpServletRequest对象是请求对象,这个对象不需要我们创建,是Tomcat创建并传递给我们的一个对象,这个对象里面封装了请求的所有数据,比如,请求头,请求体,请求方法等的内容
常用api
方法 | 参数 | 含义 |
---|---|---|
getHeader() | String 请求头参数的key | 获取请求头 |
getContextPath() | 无 | 获取上下文路径 |
getServletPath() | 无 | 获取servlet中的映射路径 |
getMethod() | 无 | 获取请求方式 |
getRequestURL() | 无 | 获取url |
getRequestURI() | 无 | 获取uri |
getParameter() | String 请求参数的key | 获取请求的数据 |
案例
public class Servlet01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求头 这里我们获取的是主机和端口号
String host = req.getHeader("host");
System.out.println("请求头="+host);
//获取上下文路径
String contextPath = req.getContextPath();
System.out.println("上下文路径="+contextPath);
//获取servlet中的映射路径
String servletPath = req.getServletPath();
System.out.println("servlet中的映射路径="+servletPath);
//获取请求方式
String method = req.getMethod();
System.out.println("请求方式="+method);
//获取url和uri
StringBuffer url = req.getRequestURL();
String uri = req.getRequestURI();
System.out.println("url="+url);
System.out.println("uri="+uri);
//获取请求的数据 这里我们需要自己在浏览器地址栏加上参数
//http://localhost:8080/servlet01?name=zhangsan&age=18
String name = req.getParameter("name");
String age = req.getParameter("age");
System.out.println("name="+name+" "+"age="+age);
}
}
4.HttpServletResponse对象
HttpServletRequest对象是响应对象,这个对象不需要我们创建,是Tomcat创建并传递给我们的一个对象,这个对象里面封装了响应的所有数据,包括响应体,响应头等等
常用api
方法 | 参数 | 含义 |
---|---|---|
setHeader() | String Object 是一个key-value键值对 | 给响应数据包设置响应头 |
setContentType() | String 数据的格式 | 设置数据类型 |
setCharacterEncoding() | String 编码的类型 | 设置响应实体编码 |
setStatus() | 无 | 给响应数据包设置状态码 |
getWriter() | 无 | 获取页面输出对象PrintWriter |
write() | Object 需要写入页面的数据 | 向页面写数据 |
案例
public class Servlet02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//给响应数据包设置响应头
resp.setHeader("mydata","data");
//设置数据类型
resp.setContentType("application/json");
//设置响应实体编码(默认为) 另一种设置方式为resp.setContentType("application/json;charset=utf-8");
resp.setCharacterEncoding("utf-8");
//给响应数据包设置状态码,一般不用自己设置,由系统自动判断
resp.setStatus(200);
//设置页面输出的数据
resp.getWriter().write("servlet02你好");
}
}
5.Servlet的生命周期
Servlet是全局单例的,也就是说这个实例在第一次访问的时候被创建,之后就不再进行创建了
整个生命周期
- 第一次访问被创建,执行对象的创建回调构造方法
- 回调init()初始化方法,执行初始化操作
- 每次请求到达都会执行service()方法
- 程序停止的时候会自动回调destroy()函数来销毁servlet
案例
public class Servlet03 extends HttpServlet {
public Servlet03() {
System.out.println("servlet03被创建了");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("servlet03");
}
@Override
public void destroy() {
System.out.println("servlet03被销毁了");
}
@Override
public void init() throws ServletException {
System.out.println("servlet03被初始化了");
}
}
5.HttpServletConfig对象
在HttpServlet对象中,有两个init()
方法其中一个方法是无参的一个方法是有参的,有参的方法的参数是HttpServletConfig
,这个对象可以将我们在web.xml
文件中提前配置的内容取出来
案例
<servlet>
<servlet-name>servlet03</servlet-name>
<servlet-class>com.hty.web01.Servlet03</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>zhangsan</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>18</param-value>
</init-param>
</servlet>
public void init(ServletConfig config) throws ServletException {
String name = config.getInitParameter("name");
String age = config.getInitParameter("age");
System.out.println("name="+name+" "+"age="+age);
}
问题:如果我们将两个init方法都重写了,那么调用哪一个呢?
查看源码
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
在有参的init中调用了无参的init,说明了,如果我们重写之后没有调用父类的init方法,那么就只会执行有参的init方法,但是如果我们在有参的init方法中调用了父类的init方法,那么就会在调用有参的init方法之前先调用一次无参的init方法
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
String name = config.getInitParameter("name");
String age = config.getInitParameter("age");
System.out.println("name="+name+" "+"age="+age);
}
输出结果
servlet03被创建了
servlet03被初始化了
name=zhangsan age=18
6.请求转发
其实请求转发是服务器内部的请求转发,与浏览器没有任何关系,对于浏览器而言页面不会出现出现刷新,就是一个请求
案例
public class Servlet04 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/servlet01").forward(req,resp);
}
}
这个案例转发到了servlet01中,ide的控制台就会展示出上面servlet01中的内容
7.请求重定向
浏览器发送一次请求,服务器返回302状态码+Location响应头,浏览器因为有一个机制(碰到响应码是302的就会去检查Location响应头,然后跳转访问Location响应头中携带的地址)
请求重定向之后,浏览器地址栏就会发生变化
案例
public class Servlet05 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/servlet01");
}
}
8.ServletContext对象
Tomcat在加载我们的应用程序的时候,会给我们的应用程序创建一个ServletContext对象,代表我们这个应用程序对象,我么可以通过Servlet中的api来获取此对象。这个对象相当于一个变量的保存区,可以将我们每一个servlet设置key-value键值对保存在里面,在任何一个servlet中都可以使用这些key-value键值对
案例
public class Servlet06 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//设置参数
servletContext.setAttribute("name","zhangsan");
servletContext.setAttribute("age","18");
}
}
public class Servlet07 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
//获取参数
String name = (String) servletContext.getAttribute("name");
String age = (String) servletContext.getAttribute("age");
System.out.println(name + " " + age);
}
}
9.service()方法详解
public class Servlet08 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
}
}
在上面的程序中,我们直接调用了父类的service()方法,最后的执行结果为
原因:
阅读源码我们可以发现,service方法调用了HttpServlet中的doGet(),doPost()等一系列的方法,他是根据请求的方法来进行选择的,又由于浏览器只能发送get请求,所以service方法还是调用了doGet()方法,进入到doGet()方法就会发现,405错误时从这里来的。根据这个例子来看,我们重写service方法的时候,一定不能调用父类方法。
10.json与对象之间的转换
前后端交互的数据格式就是json格式
一种json字符串 {"author":"吴承恩","id":1,"name":"西游记"}
要拼接为这种字符串那么我们就要重写toString()方法,并利用反射机制获取到属性的值
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("{");
Class<? extends Book> bookClass = this.getClass();
//获取私有的属性
Field[] fileds = bookClass.getDeclaredFields();
for (int i = 0; i < fileds.length; i++) {
String name = fileds[i].getName();
sb.append("\"" + name + "\": ");
try {
sb.append("\"" + fileds[i].get(this) + "\",");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
sb.replace(sb.length()-1,sb.length(),"");
sb.append("}");
return sb.toString();
}
通过拼接我们发现,这种方式非常的麻烦,那么我们就需要借用第三方的工具包来实现json的转换
11.fastjson
由于自行拼接json字符串很麻烦,于是我们就可以使用第三方的工具包来帮助我们拼接json字符串,fastjson就是阿里巴巴的一个工具包,专门用来处理json字符串的
public class json01 {
public static void main(String[] args) {
Book book = new Book();
book.setId(1);
book.setName("西游记");
book.setAuthor("吴承恩");
book.setDate(new Date(System.currentTimeMillis()));
//json的序列化
//不换行的格式显示
String s = JSON.toJSONStringWithDateFormat(book,"yyyy-MM-dd HH:mm:ss", SerializerFeature.BrowserCompatible);
//换行的格式显示
String s1 = JSON.toJSONStringWithDateFormat(book,"yyyy-MM-dd HH:mm:ss", SerializerFeature.PrettyFormat);
System.out.println(s);
//json的反序列化
Book book1 = JSON.parseObject(s, Book.class);
System.out.println(book1);
}
}
集合的转换
public class json02 {
public static void main(String[] args) {
List<Book> bookList = new ArrayList<>();
Book book1 = new Book();
book1.setId(1);
book1.setName("西游记");
book1.setAuthor("吴承恩");
book1.setDate(new Date(System.currentTimeMillis()));
Book book2 = new Book();
book2.setId(2);
book2.setName("三国演义");
book2.setAuthor("罗贯中");
book2.setDate(new Date(System.currentTimeMillis()));
bookList.add(book1);
bookList.add(book2);
String s = JSON.toJSONStringWithDateFormat(bookList, "yyyy-MM-dd HH:mm:ss");
System.out.println(s);
/*
结果
[{"author":"吴承恩","date":"2022-05-24 21:51:29","id":1,"name":"西游记"},{"author":"罗贯中","date":"2022-05-24 21:51:29","id":2,"name":"三国演义"}]
*/
}
}
详情请见:http://t.csdn.cn/8bPs1
12.Servlet返回json字符串给客户端
由于现在的开发都是前后端分离,所以前后端的数据交互主要都是靠json。
public class Servlet01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Book book = new Book();
book.setId(1);
book.setName("西游记");
book.setAuthor("吴承恩");
book.setDate(new Date());
//将book序列化为json字符串
String bookJson = JSON.toJSONString(book);
resp.getWriter().write(bookJson);
}
}
13.乱码的问题
只有在地址栏中携带数据才不会出现乱码,也就是说get请求永远不会出现乱码,post,put,delete等请求在请求体中携带的参数数会出现乱码问题
解决方法是
req.setCharacterEncoding("urf-8");//设置请求实体中的编码格式
在响应实体中出现乱码的解决方式
resp.setHeader("Content-Type","application/json;charset=utf-8");
14.MIME类型(Type)
在网络中传输数据,需要告诉客户端或者告诉服务器我们传输的数据的类型是什么,这些个类型是有一定规范的,我们常用的类型有以下这么一些:
text/plain(纯文本)
text/html (网页)
text/javascript(js的脚本文件)
text/css(css文件)
image/jpeg(JPEG图像)
image/png(PNG图像)
application/pdf(PDF文档)
application/json(json类型)
application/x-www-form-urlencoded(简单表单数据类型)
multipart/form-data(复合表单类型)
....
这些就是可以设置在Content-Type中的值
如果不指定MIME-TYPE类型,如果客户端是浏览器,那么浏览器就会尝试着去解析,所以在实际开发中,都会显示的指定MIME-TYPE;
15.服务器获取浏览器提交的表单数据
后端编写
public class Servlet01 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
Integer age = Integer.valueOf(req.getParameter("age"));
System.out.println(name);
System.out.println(age);
}
}
前端编写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
action:表单提交的服务器的地址
method:请求方式(默认为GET)
enctype:表单数据的编码方式:默认(application/x-www-form-urlencoded)
-->
<form action="/web03/servlet01" method="POST" enctype="application/x-www-form-urlencoded">
<!--autocomplete 关闭浏览器自动补全提示-->
<input type="text" name="name" placeholder="请输入姓名" autocomplete="off">
<input type="text" name="age" placeholder="请输入年龄" autocomplete="off">
<button>提交</button>
</form>
</body>
</html>
总结: 以上的这种方式提交表单数据的方式是同步的,在网络环境较差的情况下用户体验不好,所以在实际的开发过程中,尽量应该使用异步的方式提交表单数据;
16.异步请求
16.1.原生js的异步请求实现
异步请求的第一步就是先要将表单阻止提交,阻止的方式就是在form中加入onsubmit属性并return false;
<form onsubmit="return false;"></form>
编写前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>提交表单数据</h1>
<form onsubmit="return false;" id="form">
<input type="text" autocomplete="off" name="name" placeholder="请输入姓名"/>
<br>
<input type="text" autocomplete="off" name="age" placeholder="请输入年龄"/>
<br>
男: <input type="radio" name="sex" value="男"> 女:<input type="radio" name="sex" value="女">
<br>
java: <input type="checkbox" value="java" name="loves">
python:<input type="checkbox" value="python" name="loves">
大数据: <input type="checkbox" value="大数据" name="loves">
<br>
<select name="city">
<option>西安市</option>
<option>北京市</option>
<option>宝鸡市</option>
</select>
<br>
<button onclick="doSubmit()">提交数据给服务器</button>
</form>
<script type="text/javascript">
function doSubmit() {
//获取name
let name = document.querySelector("input[name='name']");
//获取age
let age = document.querySelector("input[name='age']");
//由于多个input的name=sex所以需要遍历,选择出来被选择的值
let sex = document.querySelectorAll("input[name='sex']");
//最后获取到的被选择的sex
let sexVal = null;
for (let sexKey in sex) {
if (sex[sexKey].checked) {
sexVal = sex[sexKey].value;
}
}
//获取loves
let lovesInputs = document.querySelectorAll("input[name='loves']");
let loves = [];
lovesInputs.forEach(lovesInput=>{
if(lovesInput.checked){
loves.push(lovesInput.value);
}
})
//获取city
let city = document.querySelector("select[name='city']").value;
const userObj={
name,
age,
sex,
loves,
city
}
//异步请求对象
let xhr = new XMLHttpRequest();
//由于这里的前后端都是一个服务器,所以我们不需要写ip和端口号
xhr.open("POST","/web03/servlet01");
//这里必须指定表单类型,不然会无法提交到服务器
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
xhr.send("name=zhangsan&age=18&sex=男&loves=java&loves=大数据&city=西安市");
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
const responseJsonText = xhr.responseText;
//把json类型的文本转换成js中的对象(js中对象的反序列化)
const jsonObj = JSON.parse(responseJsonText);
//把对象转换成字符串(js中的对象的序列化)
console.log(JSON.stringify(jsonObj));
}
}
}
</script>
</body>
</html>
编写后端
public class Servlet01 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String name = req.getParameter("name");
Integer age = Integer.valueOf(req.getParameter("age"));
String sex = req.getParameter("sex");
String[] loves = req.getParameterValues("loves");
String city = req.getParameter("city");
User user = new User(name,age,sex,loves,city);
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(JSON.toJSONString(user));
}
}
这个Uers实体类
package com.hty.web03.pojo;
public class User {
private String name;
private Integer age;
private String sex;
private String[] loves;
private String city;
public User() {
}
public User(String name, Integer age, String sex, String[] loves, String city) {
this.name = name;
this.age = age;
this.sex = sex;
this.loves = loves;
this.city = city;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String[] getLoves() {
return loves;
}
public void setLoves(String[] loves) {
this.loves = loves;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
16.2.基于jQuery的异步请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>基于jQuery的异步请求实现</title>
<script src="jquery-1.9.1.js"></script>
</head>
<body>
<form onsubmit="return false;" id="form">
<input type="text" autocomplete="off" name="name" placeholder="请输入姓名"/>
<br>
<input type="text" autocomplete="off" name="age" placeholder="请输入年龄"/>
<br>
男: <input type="radio" name="sex" value="男"> 女:<input type="radio" name="sex" value="女">
<br>
java: <input type="checkbox" value="java" name="loves">
python:<input type="checkbox" value="python" name="loves">
大数据: <input type="checkbox" value="大数据" name="loves">
<br>
<select name="city">
<option>西安市</option>
<option>北京市</option>
<option>宝鸡市</option>
</select>
<br>
<button onclick="doSubmit()">提交数据给服务器</button>
</form>
<script>
function doSubmit(){
//将提交的表单信息序列化为一个字符串
let dataform = $("#form").serialize();
//使用jQuery中提供的异步请求的api
$.ajax({
url:"/web03/servlet01",//请求地址
type:"POST",//默认为get
data:dataform,//请求的数据
//args就是响应的数据
success:function (...args){//成功的回调函数
console.log("成功响应",args);
},
fail:function (){//失败的回调函数
console.log("失败响应");
}
})
}
</script>
</body>
</html>
17.Servlet中的域对象
域就是作用域(范围)
- ServletContext(全局域对象)
- ServletRequest(请求域对象)
- HttpSession
18.ServletContext对象
ServletContext域对象是在全局作用域都是同一个对象
要测试这个对象,我们需要先创建两个servlet,一个用来存,一个用来获取
//域对象
public class Servlet03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//给全局域对象设置值
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("name","zhangsan");
System.out.println("servlet03");
}
}
//域对象
public class Servlet04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取全局域对象的值
ServletContext servletContext = this.getServletContext();
String name = servletContext.getAttribute("name").toString();
System.out.println(name);
System.out.println("servlet04");
}
}
请求重定向和请求转发都可以获取到ServletContext对象中的数据
19.ServletRequest对象
ServletRequest对象只在一次请求中有效;
我们仍然需要两个类来进行测试,用一个servlet请求转发到另一个servlet中,就可以测试请求作用域对象
//域对象
public class Servlet03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//请求转发
req.setAttribute("name","张三");
System.out.println("servlet03");
req.getRequestDispatcher("/web03/servlet04").forward(req,resp);
}
}
//域对象
public class Servlet04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getAttribute("name").toString();
System.out.println(name);
System.out.println("servlet04");
}
}
在请求重定向中不能访问到请求作用域对象
20.Filter过滤器
过滤器的本质还是一个Servlet,对Servlet的访问的前后做一些处理
- 过滤器就是Servlet规范中,对servlet前后做处理的一个组件
- 过滤器是对多个请求的前后都可以进行处理
- 过滤器可以有多个,多个过滤器组成了一条过滤链
- 过滤器编写完成后需要注册
- 过滤器中需要配置过滤器到底过滤哪些请求
执行步骤
21.Filter过滤器的生命周期
首先在web.xml中对filter进行注册
<!--注册filter-->
<filter>
<filter-name>myfilter01</filter-name>
<filter-class>com.hty.web03.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter01</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
public class MyFilter01 implements Filter {
//init方法在tomcat容器启动后,加载应用时调用 只调用一次
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器MyFilter01被初始化");
}
//每个能被过滤器过滤的请求都要执行一次
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("执行MyFilter01过滤器------------");
filterChain.doFilter(servletRequest,servletResponse);//放行
}
//destory方法在应用被停止时调用
@Override
public void destroy() {
System.out.println("过滤器MyFilter01被销毁");
}
}
22.过滤链
当有多个过滤器的时候,那么这些过滤器就会组成一个过滤链,过滤链中,配置在前面的过滤器会先执行,回调的时候,顺序是相反的
23.数据库连接池
- dbcp
- c3p0
- druid(阿里巴巴开源数据连接池)
- hikari
24.servlet访问数据库
首先创建数据库和数据
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for book
-- ----------------------------
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`name` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '图书名称',
`author` char(4) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '图书作者',
`release_date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of book
-- ----------------------------
INSERT INTO `book` VALUES ('1', '西游记', '吴承恩', '2022-05-17');
INSERT INTO `book` VALUES ('2', '三国演义', '罗贯中', '2022-05-30');
INSERT INTO `book` VALUES ('3', '水浒传', '施耐庵', '2022-05-30');
INSERT INTO `book` VALUES ('4', '红楼梦', '曹雪芹', '2022-05-30');
在项目根目录下创建一个resources的目录,并标记为resources目录,创建一个db.properties的文件
# 写入自己的配置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://10.10.10.134:3306/java21?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username=root
password=123456
使用数据库连接池
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.fastjson.JSON;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
//根据书籍id查询书名
public class Servlet07 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//获取页面传递的书籍的id
Integer id = Integer.valueOf(req.getParameter("id"));
//数据库连接池
Properties prop = new Properties();
prop.load(this.getClass().getClassLoader().getResourceAsStream("db.properties"));
DataSource druidDataSource = DruidDataSourceFactory.createDataSource(prop);
QueryRunner queryRunner = new QueryRunner(druidDataSource);
Map result = (Map)queryRunner.query("select * from book where id = ?", id, new MapHandler());
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(JSON.toJSONString(result));
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
25.案例-下拉菜单二级联动
前端页面的编写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>homework</title>
<script src="jquery-1.9.1.js"></script>
</head>
<body>
<button onclick="getCity()">获取城市信息</button>
<br>
<select name="city" id="city" class="city" onchange="changeCity(this)">
</select>
<select name="school" id="school">
</select>
<script>
function getCity(){
let city = [];
$.ajax({
url:"/web04/homeworkservlet01",
method:"POST",
success:function (...args){
for(let i=0;i<args[0].length;++i){
city.push(args[0][i][0]);
}
const citySelecter = document.querySelector("#city");
citySelecter.length = 0;
for(let i = 0;i<city.length;++i){
let option = document.createElement("option");
let text = document.createTextNode(city[i]);
option.append(text);
citySelecter.append(option);
}
},
fail:function(){
}
})
}
function changeCity(city){
let dataMsg = city.value;
console.log(dataMsg);
let school = [];
// console.log(jsonStr);
$.ajax({
url:"/web04/homeworkservlet02",
method:"POST",
//在ajax中不能直接指定dataType为json,不然后端无法接收到数据
data:{"city":dataMsg},
success:function(...args){
console.log(args);
for(let i=0;i<args[0].length;++i){
school.push(args[0][i][0]);
}
const schoolSelecter = document.querySelector("#school");
schoolSelecter.length = 0;
for(let i = 0;i<city.length;++i){
let option = document.createElement("option");
let text = document.createTextNode(school[i]);
option.append(text);
schoolSelecter.append(option);
}
},
fail:function(){
}
})
}
</script>
</body>
</html>
两个Servlet
HomeWorkServlet01
package com.hty.web04;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.fastjson.JSON;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
public class HomeWorkServlet01 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
req.setCharacterEncoding("utf-8");
Properties pro = new Properties();
pro.load(this.getClass().getClassLoader().getResourceAsStream("db.properties"));
DataSource druidDataSource = DruidDataSourceFactory.createDataSource(pro);
QueryRunner queryRunner = new QueryRunner(druidDataSource);
List<String> result = (List<String>)queryRunner.query("select name from city",new ArrayListHandler());
// System.out.println(JSON.toJSONString(result));
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(JSON.toJSONString(result));
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
HomeWorkServlet02
package com.hty.web04;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.fastjson.JSON;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
public class HomeWorkServlet02 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
req.setCharacterEncoding("utf-8");
String city = req.getParameter("city");
System.out.println(city);
Properties pro = new Properties();
pro.load(this.getClass().getClassLoader().getResourceAsStream("db.properties"));
DataSource druidDataSource = DruidDataSourceFactory.createDataSource(pro);
QueryRunner queryRunner = new QueryRunner(druidDataSource);
List<String> result = (List<String>)queryRunner.query("select name from school where city = ?",city,new ArrayListHandler());
// System.out.println(JSON.toJSONString(result));
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(JSON.toJSONString(result));
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}