JavaWeb基础学习笔记

Tomcat

Web 应⽤服务器:Tomcat、Jboos、Weblogic、Jetty

  • 安装 Tomcat
    1、官⽹下载压缩⽂件。https://tomcat.apache.org/download-90.cgi
    在这里插入图片描述
    2、解压缩。
    bin:存放各个平台下启动和停⽌ Tomcat 服务的脚本⽂件。
    conf:存放各种 Tomcat 服务器的配置⽂件。
    lib:存放 Tomcat 服务器所需要的 jar。
    logs:存放 Tomcar 服务运⾏的⽇志。
    temp:Tomcat 运⾏时的临时⽂件。
    webapps:存放允许客户端访问的资源(Java 程序)。
    work:存放 Tomcat 将 JSP 转换之后的 Servlet ⽂件。

IDEA 集成 Tomcat

1、创建 Java Web ⼯程。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Servlet

  • 什么是 Servlet?
    Servlet 是 Java Web 开发的基⽯,与平台⽆关的服务器组件,它是运⾏在 Servlet 容器/Web 应⽤服务
    器/Tomcat,负责与客户端进⾏通信。
    Servlet 的功能:
    1、创建并返回基于客户请求的动态 HTML ⻚⾯。
    2、与数据库进⾏通信。
  • 如何使⽤ Servlet?
    Servlet 本身是⼀组接⼝,⾃定义⼀个类,并且实现 Servlet 接⼝,这个类就具备了接受客户端请求以及
    做出响应的功能。
package com.southwind.servlet;
import javax.servlet.*;
import java.io.IOException;
public class MyServlet implements Servlet {
	 @Override
	 public void init(ServletConfig servletConfig) throws ServletException {
	 }
	 @Override
	 public ServletConfig getServletConfig() {
	 	return null;
	 }
	 @Override
	 public void service(ServletRequest servletRequest, ServletResponse
	 servletResponse) throws ServletException, IOException {
		 String id = servletRequest.getParameter("id");
		 System.out.println("我是Servlet,我已经接收到了客户端发来的请求,参数是"+id);
		 servletResponse.setContentType("text/html;charset=UTF-8");
		 servletResponse.getWriter().write("客户端你好,我已接收到你的请求");
	 }
	 @Override
	 public String getServletInfo() {
	 	return null;
	 }
	 @Override
	 public void destroy() {
	 }
}

浏览器不能直接访问 Servlet ⽂件,只能通过映射的⽅式来间接访问 Servlet,映射需要开发者⼿动配
置,有两种配置⽅式。

  • 基于 XML ⽂件的配置⽅式。
<servlet>
	 <servlet-name>hello</servlet-name>
	 <servlet-class>com.southwind.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
	 <servlet-name>hello</servlet-name>
	 <url-pattern>/demo2</url-pattern>
</servlet-mapping>
  • 基于注解的⽅式。
@WebServlet("/demo2")
public class HelloServlet implements Servlet {

}

上述两种配置⽅式结果完全⼀致,将 demo2 与 HelloServlet 进⾏映射,即在浏览器地址栏中直接访问
demo 就可以映射到 HelloServlet。

Servlet 的⽣命周期

1、当浏览器访问 Servlet 的时候,Tomcat 会查询当前 Servlet 的实例化对象是否存在,如果不存在,
则通过反射机制动态创建对象,如果存在,直接执⾏第 3 步。
2、调⽤ init ⽅法完成初始化操作。
3、调⽤ service ⽅法完成业务逻辑操作。
4、关闭 Tomcat 时,会调⽤ destory ⽅法,释放当前对象所占⽤的资源。
反射机制:(如下图)
在这里插入图片描述
Servlet 的⽣命周期⽅法:⽆参构造函数、init、service、destory
1、⽆参构造函数只调⽤⼀次,创建对象。
2、init 只调⽤⼀次,初始化对象。
3、service 调⽤ N 次,执⾏业务⽅法。
4、destory 只调⽤⼀次,卸载对象。

ServletConfig

该接⼝是⽤来描述 Servlet 的基本信息的。
getServletName() 返回 Servlet 的名称,全类名(带着包名的类名)
getInitParameter(String key) 获取 init 参数的值(web.xml)
在这里插入图片描述
getInitParameterNames() 返回所有的 initParamter 的 name 值,⼀般⽤作遍历初始化参数
getServletContext() 返回 ServletContext 对象,它是 Servlet 的上下⽂,整个 Servlet 的管理者。
ServletConfig 和 ServletContext 的区别:
ServletConfig 作⽤于某个 Servlet 实例,每个 Servlet 都有对应的 ServletConfig,ServletContext 作⽤
于整个 Web 应⽤,⼀个 Web 应⽤对应⼀个 ServletContext,多个 Servlet 实例对应⼀个
ServletContext。
⼀个是局部对象,⼀个是全局对象。
在这里插入图片描述

Servlet 的层次结构

Servlet ====> GenericServlet ====> HttpServlet
HTTP 请求有很多种类型,常⽤的有四种:

GET 读取
POST 保存
PUT 修改
DELETE 删除

GenericServlet 实现 Servlet 接⼝,同时为它的⼦类屏蔽了不常⽤的⽅法,⼦类只需要重写 service ⽅
法即可。
HttpServlet 继承 GenericServlet,根据请求类型进⾏分发处理,GET 进⼊ doGET ⽅法,POST 进⼊
doPOST ⽅法。
开发者⾃定义的 Servlet 类只需要继承 HttpServlet 即可,重新 doGET 和 doPOST。

package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
	 @Override
	 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
	 throws ServletException, IOException {
	 	resp.getWriter().write("GET");
	 }
	 @Override
	 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
	 throws ServletException, IOException {
	 	resp.getWriter().write("POST");
	 }
}

在这里插入图片描述

JSP

JSP 本质上就是⼀个 Servlet,JSP 主要负责与⽤户交互,将最终的界⾯呈现给⽤户,
HTML+JS+CSS+Java 的混合⽂件。
当服务器接收到⼀个后缀是 jsp 的请求时,将该请求交给 JSP 引擎去处理,每⼀个 JSP ⻚⾯第⼀次被访
问的时候,JSP 引擎会将它翻译成⼀个 Servlet ⽂件,再由 Web 容器调⽤ Servlet 完成响应。
单纯从开发的⻆度看,JSP 就是在 HTML 中嵌⼊ Java 程序。
具体的嵌⼊⽅式有 3 种:
1、JSP 脚本,执⾏ Java 逻辑代码

<% Java代码 %>

2、JSP 声明:定义 Java ⽅法

<%!
 声明 Java ⽅法
%>

3、JSP 表达式:把 Java 对象直接输出到 HTML ⻚⾯中

<%=Java变量 %>
<%!
 public String test(){
 return "HelloWorld";
}
%>
<%
String str = test();
%>
<%=str%>

JSP内置对象 9 个

1、request:表示⼀次请求,HttpServletRequest。
2、response:表示⼀次响应,HttpServletResponse。
3、pageContext:⻚⾯上下⽂,获取⻚⾯信息,PageContext。
4、session:表示⼀次会话,保存⽤户信息,HttpSession。
5、application:表示当前 Web 应⽤,全局对象,保存所有⽤户共享信息,ServletContext。
6、config:当前 JSP 对应的 Servlet 的 ServletConfig 对象,获取当前 Servlet 的信息。
7、out:向浏览器输出数据,JspWriter。
8、page:当前 JSP 对应的 Servlet 对象,Servlet。
9、exception:表示 JSP ⻚⾯发⽣的异常,Exception。
常⽤的是 request、response、session、application、pageContext

request 常⽤⽅法:
1、String getParameter(String key) 获取客户端传来的参数。
2、void setAttribute(String key,Object value) 通过键值对的形式保存数据。(服务端内部传递参数)
3、Object getAttribute(String key) 通过 key 取出 value。
4、RequestDispatcher getRequestDispatcher(String path) 返回⼀个 RequestDispatcher 对象,该对象的 forward ⽅法⽤于请求转发。
5、String[] getParameterValues() 获取客户端传来的多个同名参数。
6、void setCharacterEncoding(String charset) 指定每个请求的编码。

HTTP 请求状态码

200:正常
404:资源找不到
400:请求类型不匹配
500:Java 程序抛出异常

response 常⽤⽅法:
1、sendRedirect(String path) 重定向,⻚⾯之间的跳转。
转发 getRequestDispatcher 和重定向 sendRedirect 的区别:
转发是将同⼀个请求传给下⼀个⻚⾯,重定向是创建⼀个新的请求传给下⼀个⻚⾯,之前的请求结束⽣
命周期。
转发:同⼀个请求在服务器之间传递,地址栏不变,也叫服务器跳转。
重定向:由客户端发送⼀次新的请求来访问跳转后的⽬标资源,地址栏改变,也叫客户端跳转。
如果两个⻚⾯之间需要通过 request 来传值,则必须使⽤转发,不能使⽤重定向。
⽤户登录,如果⽤户名和密码正确,则跳转到⾸⻚(转发),并且展示⽤户名,否则重新回到登陆⻚⾯
(重定向)。

Session

⽤户会话
服务器⽆法识别每⼀次 HTTP 请求的出处(不知道来⾃于哪个终端),它只会接受到⼀个请求信号,所
以就存在⼀个问题:将⽤户的响应发送给其他⼈,必须有⼀种技术来让服务器知道请求来⾃哪,这就是
会话技术。
会话:就是客户端和服务器之间发⽣的⼀系列连续的请求和响应的过程,打开浏览器进⾏操作到关闭浏
览器的过程。
会话状态:指服务器和浏览器在会话过程中产⽣的状态信息,借助于会话状态,服务器能够把属于同⼀次会话的⼀系列请求和响应关联起来。
实现会话有两种⽅式:

  • session
  • cookie

属于同⼀次会话的请求都有⼀个相同的标识符,sessionID

session 常⽤的⽅法:
String getId() 获取 sessionID
void setMaxInactiveInterval(int interval) 设置 session 的失效时间,单位为秒
int getMaxInactiveInterval() 获取当前 session 的失效时间
void invalidate() 设置 session ⽴即失效
void setAttribute(String key,Object value) 通过键值对的形式来存储数据
Object getAttribute(String key) 通过键获取对应的数据
void removeAttribute(String key) 通过键删除对应的数据

Cookie

Cookie 是服务端在 HTTP 响应中附带传给浏览器的⼀个⼩⽂本⽂件,⼀旦浏览器保存了某个 Cookie,
在之后的请求和响应过程中,会将此 Cookie 来回传递,这样就可以通过 Cookie 这个载体完成客户端
和服务端的数据交互。

  • 创建 Cookie
Cookie cookie = new Cookie("name","tom");
response.addCookie(cookie);
  • 读取 Cookie
Cookie[] cookies = request.getCookies();
for (Cookie cookie:cookies){
 out.write(cookie.getName()+":"+cookie.getValue()+"<br/>");
}

Cookie 常⽤的⽅法
void setMaxAge(int age) 设置 Cookie 的有效时间,单位为秒
int getMaxAge() 获取 Cookie 的有效时间
String getName() 获取 Cookie 的 name
String getValue() 获取 Cookie 的 value

Session 和 Cookie 的区别

session:保存在服务器
保存的数据是 Object
会随着会话的结束⽽销毁
保存重要信息
cookie:保存在浏览器
保存的数据是 String
可以⻓期保存在浏览器中,⽆会话⽆关
保存不重要信息

存储⽤户信息:
session

setAttribute("name","admin")   //存
getAttribute("name")   //取

⽣命周期:服务端:只要 WEB 应⽤重启就销毁,客户端:只要浏览器关闭就销毁。
退出登录:session.invalidate()

cookie

response.addCookie(new Cookie(name,"admin"))  //存

Cookie[] cookies = request.getCookies();  //取
for (Cookie cookie:cookies){
 if(cookie.getName().equals("name")){
 out.write("欢迎回来"+cookie.getValue());
 }
}

⽣命周期:不随服务端的重启⽽销毁,客户端:默认是只要关闭浏览器就销毁,我们通过 setMaxAge()
⽅法设置有效期,⼀旦设置了有效期,则不随浏览器的关闭⽽销毁,⽽是由设置的时间来决定。
退出登录:setMaxAge(0)

JSP 内置对象作⽤域

4个
page、request、session、application
setAttribute、getAttribute
page 作⽤域:对应的内置对象是 pageContext。
request 作⽤域:对应的内置对象是 request。
session 作⽤域:对应的内置对象是 session。
application 作⽤域:对应的内置对象是 application。

page < request < session < application

page 只在当前⻚⾯有效。
request 在⼀次请求内有效。
session 在⼀次会话内有效。
application 对应整个 WEB 应⽤的。

  • ⽹站访问量统计
<%
 Integer count = (Integer) application.getAttribute("count");
 if(count == null){
 	count = 1;
 	application.setAttribute("count",count);
 }else{
 	count++;
 	application.setAttribute("count",count);
 }
%>
您是当前的第<%=count%>位访客

EL 表达式

Expression Language 表达式语⾔,替代 JSP ⻚⾯中数据访问时的复杂编码,可以⾮常便捷地取出域对
象(pageContext、request、session、application)中保存的数据,前提是⼀定要先 setAttribute,
EL 就相当于在简化 getAttribute
${变量名} 变量名就是 setAttribute 对应的 key 值。

1、EL 对于 4 种域对象的默认查找顺序:

pageContext ====> request ====> session ====> application

按照上述的顺序进⾏查找,找到⽴即返回,在 application 中也⽆法找到,则返回 null

2、指定作⽤域进⾏查找
pageContext:${pageScope.name}
request:${requestScope.name}
session:${sessionScope.name}
application:${applicationScope.name}

数据级联:

<%
// pageContext.setAttribute("name","page");
// request.setAttribute("name","request");
// session.setAttribute("name","session");
// application.setAttribute("name","application");
 User user = new User(1,"张三",86.5,new Address(1,"⼩寨"));
 System.out.println(user.toString());
 pageContext.setAttribute("user",user);
%>
 <table>
	 <tr>
		 <th>编号</th>
		 <th>姓名</th>
		 <th>成绩</th>
		 <th>地址</th>
	 </tr>
	 <tr>
		 <td>${user.id}</td>
		 <td>${user.name}</td>
		 <td>${user.score}</td>
		 <td>${user.address}</td>
	 </tr>
 </table>

${user[“id”]}

EL 执⾏表达式:

${num1&&num2}
&& || ! < > <= <= ==
&& and
|| or
! not
== eq
!= ne
< lt
> gt
<= le
>= ge
empty  //变量为 null,⻓度为0的String,size为0的集合

在这里插入图片描述
在这里插入图片描述

JSTL

JSP Standard Tag Library JSP 标准标签库,JSP 为开发者提供的⼀系列的标签,使⽤这些标签可以完成
⼀些逻辑处理,⽐如循环遍历集合,让代码更加简洁,不再出现 JSP 脚本穿插的情况。
实际开发中 EL 和 JSTL 结合起来使⽤,JSTL 侧重于逻辑处理,EL 负责展示数据。

JSTL 的使⽤
1、需要导⼊ jar 包(两个 jstl.jar standard.jar)存放的位置 web/WEB-INF
2、在 JSP ⻚⾯开始的地⽅导⼊ JSTL 标签库

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

3、在需要的地⽅使⽤

<c:forEach items="${list}" var="user">
 <tr>
 <td>${user.id}</td>
 <td>${user.name}</td>
 <td>${user.score}</td>
 <td>${user.address.value}</td>
 </tr>
</c:forEach>

JSTL 优点:
1、提供了统⼀的标签
2、可以⽤于编写各种动态功能

  • 核⼼标签库常⽤标签:

set、out、remove、catch

set:向域对象中添加数据

<%
 requset.setAttribute(key,value)
%>
<c:set var="name" value="tom" scope="request"></c:set>
${requestScope.name}
<%
User user = new User(1,"张三",66.6,new Address(1,"科技路"));
request.setAttribute("user",user);
%>
${user.name}
<hr/>
<c:set target="${user}" property="name" value="李四"></c:set>
${user.name}

out:输出域对象中的数据

<c:set var="name" value="tom"></c:set>
<c:out value="${name}" default="未定义"></c:out>

remove:删除域对象中的数据

<c:remove var="name" scope="page"></c:remove>
<c:out value="${name}" default="未定义"></c:out>

catch:捕获异常

<c:catch var="error">
 <%
 int a = 10/0;
 %>
</c:catch>
${error}
  • 条件标签:if choose
<c:set var="num1" value="1"></c:set>
<c:set var="num2" value="2"></c:set>
<c:if test="${num1>num2}">ok</c:if>
<c:if test="${num1<num2}">fail</c:if>
<hr/>
<c:choose>
 <c:when test="${num1>num2}">ok</c:when>
 <c:otherwise>fail</c:otherwise>
</c:choose>
  • 迭代标签:forEach
<c:forEach items="${list}" var="str" begin="2" end="3" step="2"
varStatus="sta">
 ${sta.count}、${str}<br/>
</c:forEach>

格式化标签库常⽤的标签:

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>


<%
request.setAttribute("date",new Date());
%>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss">
</fmt:formatDate><br/>
<fmt:formatNumber value="32145.23434" maxIntegerDigits="2"
maxFractionDigits="3"></fmt:formatNumber>

函数标签库常⽤的标签:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>


<%
request.setAttribute("info","Java,C");
%>
${fn:contains(info,"Python")}<br/>
${fn:startsWith(info, "Java")}<br/>
${fn:endsWith(info, "C")}<br/>
${fn:indexOf(info, "va")}<br/>
${fn:replace(info, "C","Python")}<br/>
${fn:substring(info, 2, 3)}<br/>
${fn:split(info, ",")[0]}-${fn:split(info, ",")[1]}

过滤器 Filter

功能:
1、⽤来拦截传⼊的请求和传出的响应。
2、修改或以某种⽅式处理正在客户端和服务端之间交换的数据流。
如何使⽤?
与使⽤ Servlet 类似,Filter 是 Java WEB 提供的⼀个接⼝,开发者只需要⾃定义⼀个类并且实现该接⼝
即可。

package com.southwind.filter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterFilter implements Filter {
 @Override
 public void doFilter(ServletRequest servletRequest, 
 seservletResponse, FilterChain filterChain) throws IOException, ServletException
 {
	 servletRequest.setCharacterEncoding("UTF-8");
	 filterChain.doFilter(servletRequest,servletResponse);
 }
}

web.xml 中配置 Filter

<filter>
 <filter-name>charcater</filter-name>
 <filter-class>com.southwind.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>charcater</filter-name>
 <url-pattern>/login</url-pattern>
 <url-pattern>/test</url-pattern>
</filter-mapping>

【注意】:doFilter ⽅法中处理完业务逻辑之后,必须添加filterChain.doFilter(servletRequest,servletResponse);
否则请求/响应⽆法向后传递,⼀直停留在过滤器中。

Filter 的⽣命周期

当 Tomcat 启动时,通过反射机制调⽤ Filter 的⽆参构造函数创建实例化对象,同时调⽤ init ⽅法实现
初始化,doFilter ⽅法调⽤多次,当 Tomcat 服务关闭的时候,调⽤ destory 来销毁 Filter 对象。
⽆参构造函数:只调⽤⼀次,当 Tomcat 启动时调⽤(Filter ⼀定要进⾏配置)
init ⽅法:只调⽤⼀次,当 Filter 的实例化对象创建完成之后调⽤
doFilter:调⽤多次,访问 Filter 的业务逻辑都写在 Filter 中
destory:只调⽤⼀次,Tomcat 关闭时调⽤。

同时配置多个 Filter,Filter 的调⽤顺序是由 web.xml 中的配置顺序来决定的,写在上⾯的配置先调
⽤,因为 web.xml 是从上到下顺序读取的。

<filter>
 <filter-name>my</filter-name>
 <filter-class>com.southwind.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>my</filter-name>
 <url-pattern>/login</url-pattern>
</filter-mapping>
<filter>
 <filter-name>charcater</filter-name>
 <filter-class>com.southwind.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>charcater</filter-name>
 <url-pattern>/login</url-pattern>
 <url-pattern>/test</url-pattern>
</filter-mapping>

1、MyFilter
2、CharacterFilter

也可以通过注解的⽅式来简化 web.xml 中的配置

<filter>
 <filter-name>my</filter-name>
 <filter-class>com.southwind.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>my</filter-name>
 <url-pattern>/login</url-pattern>
</filter-mapping>

等于

@WebFilter("/login")
public class MyFilter implements Filter {

}

Filter 的使⽤场景

实际开发中 Filter 的使⽤场景:
1、统⼀处理中⽂乱码。
2、屏蔽敏感词。

package com.southwind.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/test")
public class WordFilter implements Filter {
 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain) throws IOException, ServletException
{
	 servletRequest.setCharacterEncoding("UTF-8");
	 //将"敏感词"替换成"***"
	 String name = servletRequest.getParameter("name");
	 name = name.replaceAll("敏感词","***");
	 servletRequest.setAttribute("name",name);
	 filterChain.doFilter(servletRequest,servletResponse);
 }
}
package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
	 String name = (String) req.getAttribute("name");
	 System.out.println("servlet:"+name);
 }
}

3、控制资源的访问权限。

package com.southwind.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebFilter("/download.jsp")
public class DownloadFilter implements Filter {
 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse, FilterChain filterChain) throws IOException, ServletException
{
	 HttpServletRequest request = (HttpServletRequest) servletRequest;
	 HttpServletResponse response = (HttpServletResponse) servletResponse;
	 HttpSession session = request.getSession();
	 String name = (String) session.getAttribute("name");
	 if(name == null){
		 //不是登录状态
		 response.sendRedirect("/login.jsp");
	 }else{
	 	filterChain.doFilter(servletRequest,servletResponse);
	 }
 }
}

⽂件上传下载

  • JSP
    1、input 的 type 设置为 file
    2、form 表单的 method 设置 post,get 请求会将⽂件名传给服务端,⽽不是⽂件本身
    3、form 表单的 enctype 设置 multipart/form-data,以⼆进制的形式传输数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
</head>
<body>
 <form enctype="multipart/form-data" action="/upload" method="post">
	 <input name="desc" type="text"/><br/>
	 <input name="text" type="file"/><br/>
	 <input type="submit" value="上传"/>
 </form>
</body>
</html>
  • Servlet
    fileupload 组件可以将所有的请求信息都解析成 FileIteam 对象,可以通过对 FileItem 对象的操作完成上传,⾯向对象的思想。
package com.southwind.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
	// //通过输⼊流获取客户端传来的数据流
	// InputStream inputStream = req.getInputStream();
	// Reader reader = new InputStreamReader(inputStream);
	// BufferedReader bufferedReader = new BufferedReader(reader);
	// //通过输出流将数据流输出到本地硬盘
	// //获取⽂件夹的绝对路径
	// String path = req.getServletContext().getRealPath("file/copy.txt");
	// OutputStream outputStream = new FileOutputStream(path);
	// Writer writer = new OutputStreamWriter(outputStream);
	// BufferedWriter bufferedWriter = new BufferedWriter(writer);
	// String str = "";
	// while((str = bufferedReader.readLine())!=null){
	// System.out.println(str);
	// bufferedWriter.write(str);
	// }
	// bufferedWriter.close();
	// writer.close();
	// outputStream.close();
	// bufferedReader.close();
	// reader.close();
	// inputStream.close();
	 try {
		 DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
		 ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
		 List<FileItem> list = servletFileUpload.parseRequest(req);
		 for(FileItem fileItem : list){
			 if(fileItem.isFormField()){
				 String name = fileItem.getFieldName();
				 String value = fileItem.getString("UTF-8");
				 System.out.println(name+":"+value);
			 }else{
				 String fileName = fileItem.getName();
				 long size = fileItem.getSize();
				 System.out.println(fileName+":"+size+"Byte");
				 InputStream inputStream = fileItem.getInputStream();
				// Reader reader = new InputStreamReader(inputStream);
				// BufferedReader bufferedReader = new BufferedReader(reader);
				 String path = req.getServletContext().getRealPath("file/"+fileName);
				 OutputStream outputStream = new FileOutputStream(path);
				// Writer writer = new OutputStreamWriter(outputStream);
				// BufferedWriter bufferedWriter = new BufferedWriter(writer);
				 int temp = 0;
				 while((temp = inputStream.read())!=-1){
				 	outputStream.write(temp);
			 	 }
				// bufferedWriter.close();
				// writer.close();
				 outputStream.close();
				// bufferedReader.close();
				// reader.close();
				 inputStream.close();
				 System.out.println("上传成功");
		 	}
	 	}
	 } catch (FileUploadException e) {
	 	e.printStackTrace();
	 }
 }
}

⽂件下载

package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
 String type = req.getParameter("type");
 String fileName = "";
 switch (type){
	 case "png":
	 	fileName = "1.png";
	 	break;
	 case "txt":
		 fileName = "test.txt";
		 break;
 }
 //设置响应⽅式
 resp.setContentType("application/x-msdownload");
 //设置下载之后的⽂件名
 resp.setHeader("Content-Disposition","attachment;filename="+fileName);
 //获取输出流
 OutputStream outputStream = resp.getOutputStream();
 String path = req.getServletContext().getRealPath("file/"+fileName);
 InputStream inputStream = new FileInputStream(path);
 int temp = 0;
 while((temp=inputStream.read())!=-1){
 	outputStream.write(temp);
 }
 inputStream.close();
 outputStream.close();
 }
}

Ajax

Asynchronous JavaScript And XML:异步的 JavaScript 和 XML
AJAX 不是新的编程,指的是⼀种交互⽅式,异步加载,客户端和服务器的数据交互更新在局部⻚⾯的
技术,不需要刷新整个⻚⾯(局部刷新)
优点:
1、局部刷新,效率更⾼
2、⽤户体验更好

【注】:同步:(打电话);异步:(发微信)

基于 jQuery 的 A JAX:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
 <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
 <script type="text/javascript">
 $(function(){
	 var btn = $("#btn");
	 btn.click(function(){
		 $.ajax({
		 	url:'/test',
		 	type:'post',
		 	data:'id=1',
		 	dataType:'text',
		 	success:function(data){
		 		var text = $("#text");
		 		text.before("<span>"+data+"</span><br/>");
		 	}
		 });
	 });
 })
 </script>
</head>
<body>
	 <input id="text" type="text"/><br/>
	 <input id="btn" type="button" value="提交"/>
</body>
</html>

不能⽤表单提交请求,改⽤ jQuery ⽅式动态绑定事件来提交。
Servlet 不能跳转到 JSP,只能将数据返回

package com.southwind.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
 String id = req.getParameter("id");
 try {
 	Thread.sleep(3000);
 } catch (InterruptedException e) {
 	e.printStackTrace();
 }
 String str = "Hello World";
 resp.getWriter().write(str);
 }
}

传统的 WEB 数据交互 VS AJAX 数据交互

  • 客户端请求的⽅式不同:
    传统:浏览器发送同步请求 (form、a)
    AJAX:异步引擎对象发送异步请求
  • 服务器响应的⽅式不同:
    传统:响应⼀个完整 JSP ⻚⾯(视图)
    AJAX:响应需要的数据
  • 客户端处理⽅式不同:
    传统:需要等待服务器完成响应并且重新加载整个⻚⾯之后,⽤户才能进⾏后续的操作
    AJAX:动态更新⻚⾯中的局部内容,不影响⽤户的其他操作

AJAX 原理

在这里插入图片描述

基于 jQuery 的 AJAX 语法

$.ajax({属性})
常⽤的属性参数:
url:请求的后端服务地址
type:请求⽅式,默认 get
data:请求参数
dataType:服务器返回的数据类型,text/json
success:请求成功的回调函数
error:请求失败的回调函数
complete:请求完成的回调函数(⽆论成功或者失败,都会调⽤)

JSON

JavaScript Object Notation,⼀种轻量级数据交互格式,完成 js 与 Java 等后端开发语⾔对象数据之间
的转换。
客户端和服务器之间传递对象数据,需要⽤ JSON 格式。

package com.southwind.entity;
public class User {
 private Integer id;
 private String name;
 private Double score;
 public Integer getId() {
 	return id;
 }
 public void setId(Integer id) {
	 this.id = id;
 }
 public String getName() {
 	return name;
 }
 public void setName(String name) {
	 this.name = name;
 }
 public Double getScore() {
 	return score;
 }
 public void setScore(Double score) {
	 this.score = score;
 }
 public User(Integer id, String name, Double score) {
	 this.id = id;
	 this.name = name;
	 this.score = score;
 }
}
User user = new User(1,"张三",96.5)
var user = {
 id:1,
 name:"张三",
 score:96.5
}
package com.southwind.servlet;
import com.southwind.entity.User;
import net.sf.json.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/test")
public class TestServlet extends HttpServlet {
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
	 User user = new User(1,"张三",96.5);
	 //将 Java 对象转为 JSON 格式
	 resp.setCharacterEncoding("UTF-8");
	 JSONObject jsonObject = JSONObject.fromObject(user);
	 resp.getWriter().write(jsonObject.toString());
 }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
 <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
 <script type="text/javascript">
 $(function(){
	 var btn = $("#btn");
	 btn.click(function(){
	 $.ajax({
		 url:'/test',
		 type:'post',
		 dataType:'json',
		 success:function(data){
			 $("#id").val(data.id);
			 $("#name").val(data.name);
			 $("#score").val(data.score);
		 }
		});
	 });
 })
 </script>
</head>
<body>
	 编号:<input id="id" type="text"/><br/>
	 姓名:<input id="name" type="text"/><br/>
	 成绩:<input id="score" type="text"/><br/>
	 <input id="btn" type="button" value="提交"/>
</body>
</html>

AJAX的简单应用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
 <title>Title</title>
 <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
 <script type="text/javascript">
 $(function(){
	 //修改省份
	 $("#province").change(function () {
		 var id = $(this).val();
		 $.ajax({
			 url:"/location",
			 type:"POST",
			 data:"id="+id+"&type=province",
			 dataType:"JSON",
			 success:function(data){
				 var content = "";
				 var cities = data.cities;
				 for(var i=0;i<cities.length;i++){
				 	content += "<option>"+cities[i]+"</option>";
		 		 }
				 $("#city").html(content);
				 content = "";
				 var areas = data.areas;
				 for(var i=0;i<areas.length;i++){
				 	content += "<option>"+areas[i]+"</option>";
				 }
				 $("#area").html(content);
		      }
		 });
	 });
	 //修改城市
	 $("#city").change(function(){
		 var id = $(this).val();
		 $.ajax({
			 url:"/location",
			 type:"POST",
			 data:"id="+id+"&type=city",
			 dataType:"JSON",
			 success:function(data){
				 var content = "";
				 for(var i=0;i<data.length;i++){
				 	content += "<option>"+data[i]+"</option>";
				 }
				 $("#area").html(content);
			 }
		 });
	 });
 });
 </script>
</head>
<body>
 省:<select id="province">
		 <option value="陕⻄省">陕⻄省</option>
		 <option value="河南省">河南省</option>
		 <option value="江苏省">江苏省</option>
	 </select>
 市:<select id="city">
		 <option value="⻄安市">⻄安市</option>
		 <option value="宝鸡市">宝鸡市</option>
		 <option value="渭南市">渭南市</option>
	 </select>
 区:<select id="area">
		 <option>雁塔区</option>
		 <option>莲湖区</option>
		 <option>新城区</option>
	 </select>
</body>
</html>
package com.southwind.entity;
import java.util.List;
public class Location {
 private List<String> cities;
 private List<String> areas;
 public List<String> getCities() {
 return cities;
 }
 public void setCities(List<String> cities) {
 this.cities = cities;
 }
 public List<String> getAreas() {
 return areas;
 }
 public void setAreas(List<String> areas) {
 this.areas = areas;
 }
}
package com.southwind.servlet;
import com.southwind.entity.Location;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet("/location")
public class LocationServlet extends HttpServlet {
 private static Map<String, List<String>> cityMap;
 private static Map<String,List<String>> provinceMap;
 
 static {
	 cityMap = new HashMap<>();
	 List<String> areas = new ArrayList<>();
	 //⻄安
	 areas.add("雁塔区");
	 areas.add("莲湖区");
	 areas.add("新城区");
	 cityMap.put("⻄安市",areas);
	 //宝鸡
	 areas = new ArrayList<>();
	 areas.add("陈仓区");
	 areas.add("渭宾区");
	 areas.add("新城区");
	 cityMap.put("宝鸡市",areas);
	 //渭南
	 areas = new ArrayList<>();
	 areas.add("临渭区");
	 areas.add("⾼新区");
	 cityMap.put("渭南市",areas);
	 //郑州
	 areas = new ArrayList<>();
	 areas.add("郑州A区");
	 areas.add("郑州B区");
	 cityMap.put("郑州市",areas);
	 //洛阳
	 areas = new ArrayList<>();
	 areas.add("洛阳A区");
	 areas.add("洛阳B区");
	 cityMap.put("洛阳市",areas);
	 
	 provinceMap = new HashMap<>();
	 List<String> cities = new ArrayList<>();
	 cities.add("⻄安市");
	 cities.add("宝鸡市");
	 cities.add("渭南市");
	 provinceMap.put("陕⻄省",cities);
	 cities = new ArrayList<>();
	 cities.add("郑州市");
	 cities.add("洛阳市");
	 cities.add("开封市");
	 provinceMap.put("河南省",cities);
	 cities = new ArrayList<>();
	 cities.add("南京市");
	 cities.add("苏州市");
	 cities.add("南通市");
	 provinceMap.put("江苏省",cities);
 }
 
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
 }
 
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
	 String type = req.getParameter("type");
	 resp.setCharacterEncoding("UTF-8");
	 String id = req.getParameter("id");
	 switch (type){
		 case "city":
			 List<String> areas = cityMap.get(id);
			 JSONArray jsonArray = JSONArray.fromObject(areas);
			 resp.getWriter().write(jsonArray.toString());
		 	 break;
		 case "province":
			 List<String> cities = provinceMap.get(id);
			 String city = cities.get(0);
			 List<String> cityAreas = cityMap.get(city);
			 Location location = new Location();
			 location.setCities(cities);
			 location.setAreas(cityAreas);
			 JSONObject jsonObject = JSONObject.fromObject(location);
			 resp.getWriter().write(jsonObject.toString());
			 break;
	 }
 }
}

JDBC

Java DataBase Connectivity 是⼀个独⽴于特定数据库的管理系统,通⽤的 SQL 数据库存取和操作的公
共接⼝。
定义了⼀组标准,为访问不同数据库提供了统⼀的途径。
在这里插入图片描述

JDBC 体系结构

JDBC 接⼝包括两个层⾯:

  • ⾯向应⽤的 API,供程序员调⽤
  • ⾯向数据库的 API,供⼚商开发数据库的驱动程序
    在这里插入图片描述

JDBC API
提供者:Java 官⽅
内容:供开发者调⽤的接⼝
java.sql 和 javax.sql

  • DriverManager
  • Connection 接⼝
  • Statement 接⼝
  • ResultSet 接⼝

DriverManager
提供者:Java 官⽅
作⽤:管理不同的 JDBC 驱动
JDBC 驱动
提供者:数据库⼚商
作⽤:负责连接不同的数据库

JDBC 的使⽤

1、加载数据库驱动,Java 程序和数据库之间的桥梁。
2、获取 Connection,Java 程序与数据库的⼀次连接。
3、创建 Statement 对象,由 Connection 产⽣,执⾏ SQL 语句。
4、如果需要接收返回值,创建 ResultSet 对象,保存 Statement 执⾏之后所查询到的结果。

package com.southwind.test;
import java.sql.*;
import java.util.Date;
public class Test {
 public static void main(String[] args) {
	 try {
		 //加载驱动
		 Class.forName("com.mysql.cj.jdbc.Driver");
		 //获取连接
		 String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
		 String user = "root";
		 String password = "root";
		 Connection connection = DriverManager.getConnection(url,user,password);
		// String sql = "insert into student(name,score,birthday) values('李四',78,'2019-01-01')";
		// String sql = "update student set name = '李四'";
		// String sql = "delete from student";
		// Statement statement = connection.createStatement();
		// int result = statement.executeUpdate(sql);
		 String sql = "select * from student";
		 Statement statement = connection.createStatement();
		 ResultSet resultSet = statement.executeQuery(sql);
		 while (resultSet.next()){
			 Integer id = resultSet.getInt("id");
			 String name = resultSet.getString(2);
			 Double score = resultSet.getDouble(3);
			 Date date = resultSet.getDate(4);
			 System.out.println(id+"-"+name+"-"+score+"-"+date);
		 }
	 } catch (ClassNotFoundException e) {
	 	e.printStackTrace();
	 } catch (SQLException e){
	 	e.printStackTrace();
	 }
 }
}

PreparedStatement

Statement 的⼦类,提供了 SQL 占位符的功能
使⽤ Statement 进⾏开发有两个问题:
1、需要频繁拼接 String 字符串,出错率较⾼。
2、存在 SQL 注⼊的⻛险。
SQL 注⼊:利⽤某些系统没有对⽤户输⼊的信息进⾏充分检测,在⽤户输⼊的数据中注⼊⾮法的 SQL
语句,从⽽利⽤系统的 SQL 引擎完成恶意⾏为的做法。

String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
String user = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url,user,password);
String username = "lisi";
String mypassword = "000";
String sql = "select * from t_user where username = ? and password = ?";
System.out.println(sql);
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,username);
preparedStatement.setString(2,mypassword);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
 System.out.println("登录成功");
}else{
 System.out.println("登录失败");
}
} catch (ClassNotFoundException e) {
 e.printStackTrace();
} catch (SQLException e){
 e.printStackTrace();
}

数据库连接池

JDBC 开发流程

  • 加载驱动(只需要加载⼀次)
  • 建⽴数据库连接(Connection)
  • 执⾏ SQL 语句(Statement)
  • ResultSet 接收结果集(查询)
  • 断开连接,释放资源

数据库连接对象是通过 DriverManager 来获取的,每次获取都需要向数据库申请获取连接,验证⽤户
名和密码,执⾏完 SQL 语句后断开连接,这样的⽅式会造成资源的浪费,数据连接资源没有得到很好的重复利⽤。(栗子:就像是你每次打一个电话都要买一个手机,打完一个电话就把手机扔了,很浪费,为什么我们不一直使用第一次买的手机一直打电话呢?)

可以使⽤数据库连接池解决这⼀问题。
数据库连接池的基本思想就是为数据库建⽴⼀个缓冲池,预先向缓冲池中放⼊⼀定数量的连接对象,当需要获取数据库连接的时候,只需要从缓冲池中取出⼀个对象,⽤完之后再放回到缓冲池中,供下⼀次请求使⽤,做到了资源的重复利⽤,允许程序重复使⽤⼀个现有的数据库连接对象,⽽不需要重新创
建。
当数据库连接池中没有空闲的连接时,新的请求就会进⼊等待队列,等待其他线程释放连接。

数据库连接池实现

JDBC 的数据库连接池使⽤ javax.sql.DataSource 接⼝来完成的,DataSource 是 Java 官⽅提供的接
⼝,使⽤的时候开发者并不需要⾃⼰来实现该接⼝,可以使⽤第三⽅的⼯具,C3P0 是⼀个常⽤的第三
⽅实现,实际开发中直接使⽤ C3P0 即可完成数据库连接池的操作。
1、导⼊ jar 包
传统⽅式拿到的 Connection:com.mysql.cj.jdbc.ConnectionImpl@557caf28
C3P0 拿到的 Connection:com.mchange.v2.c3p0.impl.NewProxyConnection@4988d8b8
2、代码实现

package com.southwind.test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
public class DataSourceTest {
 public static void main(String[] args) {
 try {
	 //创建C3P0
	 ComboPooledDataSource dataSource = new ComboPooledDataSource();
	 dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
	 dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8");
	 dataSource.setUser("root");
	 dataSource.setPassword("root");
	 Connection connection = dataSource.getConnection();
	 System.out.println(connection);
	 //还回到数据库连接池中
	 connection.close();
 } catch (PropertyVetoException e) {
	 e.printStackTrace();
 } catch (SQLException e){
 	e.printStackTrace();
 }
 }
}

在这里插入图片描述
实际开发,将 C3P0 的配置信息定义在 xml ⽂件中,Java 程序只需要加载配置⽂件即可完成数据库连接
池的初始化操作。
1、配置⽂件的名字必须是 c3p0-config.xml
2、初始化 ComboPooledDataSource 时,传⼊的参数必须是 c3p0-config.xml 中 named-config 标签的 name 属性值

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
 <named-config name="testc3p0">
 
	 <!-- 指定连接数据源的基本属性 -->
	 <property name="user">root</property>
	 <property name="password">root</property>
	 <property name="driverClass">com.mysql.jdbc.Driver</property>
	 <property name="jdbcUrl">jdbc:mysql://localhost:3306/library?useUnicode=true&amp;characterEncoding=UTF-8</property>
	 <!-- 若数据库中连接数不⾜时, ⼀次向数据库服务器申请多少个连接 -->
	 <property name="acquireIncrement">5</property>
	 <!-- 初始化数据库连接池时连接的数量 -->
	 <property name="initialPoolSize">20</property>
	 <!-- 数据库连接池中的最⼩的数据库连接数 -->
	 <property name="minPoolSize">2</property>
	 <!-- 数据库连接池中的最⼤的数据库连接数 -->
	 <property name="maxPoolSize">40</property>
 
 </named-config>
</c3p0-config>
package com.southwind.test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
public class DataSourceTest {
 public static void main(String[] args) {
	 try {
		 //创建C3P0
		 ComboPooledDataSource dataSource = new ComboPooledDataSource("testc3p0");
		 Connection connection = dataSource.getConnection();
		 System.out.println(connection);
		 //还回到数据库连接池中
		 connection.close();
	 } catch (SQLException e){
	 	e.printStackTrace();
	 }
 }
}

DBUtils

DBUtils 可以帮助开发者完成数据的封装(结果集到 Java 对象的映射)
1、导⼊ jar 包
ResultHandler 接⼝是⽤来处理结果集,可以将查询到的结果集转换成 Java 对象,提供了 4 种实现类。

  • BeanHandler 将结果集映射成 Java 对象 Student
  • BeanListHandler 将结果集映射成 List 集合List <Student >
  • MapHandler 将结果集映射成 Map 对象
  • MapListHandler 将结果集映射成 MapList 结合

【注】:根据返回值决定以上handler。

public static Student findByDBUtils(Integer id){
 Connection connection = null;
 Student student = null;
	 try {
		 connection = dataSource.getConnection();
		 String sql = "select * from student";
		 //String sql = "select * from student where id=?";
		 QueryRunner queryRunner = new QueryRunner();
		 List<Map<String,Object>> list = queryRunner.query(connection,sql,new MapListHandler());
		 //List<Map<String,Object>> list = queryRunner.query(connection,sql,new BeanHandler<>(Student.class),id);
		 for (Map<String,Object> map:list){
			 System.out.println(map);
		 }
	 } catch (SQLException e) {
	 	e.printStackTrace();
	 } finally {
		 try {
		 	connection.close();
		 } catch (SQLException e) {
		 	e.printStackTrace();
		 }
	 }
 return student;
}

在这里插入图片描述
【代码来源】参考楠哥教学视频:https://www.bilibili.com/video/BV1BJ411L7NR
【JavaWeb实战代码及所需jar包】:https://download.csdn.net/download/hhhmonkey/21516713

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值