Java Web
Java Web
一、使用Tomcat部署Java web应用
Tomact:
Web应用服务器:Tomcat、JBoos、Weblogic、Jetty
-
安装Tomcat
-
下载压缩文件
-
解压缩
bin:存放各个平台下启动和停止的Tomcat服务的脚本
bonf:存放各种Tomcat服务器的配置文件
lib:存放Tomcat服务器所需要的jar
logs:存放Tomcat服务运行的日记
temp:Tomcat运行时的临时文件
webapps:存放允许客户端访问的资源(Java程序)
work:存放Tomcat将JSP转换之后的Servlet文件
-
IDEA集成Tomcat
-
创建Java Web文件
-
配置Tomcat文件
Servlet
-
什么是Servlet?
Servlet是JavaWeb开发的基石,与开发平台无关,他是运行在Servlet容器/web应用服务器/Tomcat服务器,负责与客户端进行通信。
Servlet的功能:
-
创建并返回基于客户请求的动态HTML页面
-
与数据库进行通信
-
如何使用Servlet?
Servlet本身是一组接口,(javax.serlvet、jiava.lang、java.util、java.sql),自定义一个类,并且实现servlet接口,这类就具备了接收客户端的请求以及做出响应的功能。
-
浏览器不能直接访问Servlet是文件,只能通过映射的方式来间接访问Servlet,映射需要开发者手动配置,有两种配置方式
-
基于XML文件配置方式
<servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.gopan.servlettest.MyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/myservlet</url-pattern> </servlet-mapping>
-
基于注解的方式 代替XML文件很简单
@WebServlet("/demo01") public class MyServlet implements Servlet { }
两种配置一样,将demo1与Myservlet进行映射,就是在浏览器地址中直接访问Demo1就可以映射到Myservlet
-
-
-
Servlet的生命周期
- 当浏览器访问Servlet的时候,Tomcat会查询当前的Servlet的实例化对象是否存在,如果不存在,则通过反射机制动态创建对象,如果存在,直接执行第三步
- 调用init方法完成初始化操作
- 调用service方法完成业务逻辑操作
- 关闭Tomcat时,会destory方法,释放当前对象所占用的资源
Servlet的生命周期方法:无参构造函数、init、service、destory
- 无参构造只调用一次,创建对象
- init只调用一次,初始化对象
- service调用N次,执行业务方法
- destory只调用一次,卸载对象
ServletConfig
该接口是用来描述Servlet的基本信息的。
servletConfig.getServletName();//返回Servlet的名称, getInitParameter(String key); //获取init参数的值(web.xml) getInitParameterNames(); //返回所有的Paramter所有的值,一般用循环 getServletContext();//返回ServletContext对象,他是Servlet的上下文,整个服务的信息
ServletConfig 和 ServletContext
SercletConfig作用于某个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.gopan.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("/demo02") 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种:
-
JSP脚本
<% //Java代码 %>
-
JSP声明:定义Java方法
<%! 声明方法 %>
-
JSP表达式:把Java对象直接到输出到HTML页面中
<%=Java变量%>
<%! public String test(){ return "world..."; } %> <% String str = test(); // %> <%=str%>
-
JSP内置对象 9个
- resqust:表示一次请求,HttpServletRequst
- response:表示一次响应,HttpServlerResponse
- pageContext:页面上下文,获取页面信息,PageContext
- session:表示一次会话,保存用户信息,HttpSession
- application:表示当前的Web应用,全局对象,保存所有用户共享信息,ServlerContext
- config:当前JSP对应的Servlet的ServletConfig对象,获取当前的Servlet的信息
- out:向浏览器输出数据,JSPWriter
- page:当前JSP对象的Servlet对象,Servlet
- excerption:表示JSP页面发生的异常,Exception
常用的是:requst、response、session、appliction、pageContext
-
requst的常用方法:
-
String getParameter(String key)获取客户端传来的参数 客户端传来服务器
-
void setAttribute(String key.Object value)通过键值对的形式保存数据。 服务器内部资源传递
-
Object getAttribute(String key) 通过key取出value。
-
RequstDispatcher getRequstDispatcher(String path)返回一个RequstDispatcher,该对象的forward方法用于请求转发。
-
String[] getParameterValues()获取客户端传来的多个同名参数
-
void setCharacterEncoding(String charset) 指定每个请求的编码。
HTTP请求状态码:200 正常 404资源找不到 400请求类型不匹配 500java程序抛出异常
-
-
response
-
sendRedirect(String path)重定向 页面之间的跳转
转发getRequestDispatcher和重定向sendRedirect区别:
转发就是将同一个请求下传给下一个页面,重定向是创建一个新的请求传给下一个页面。
转发:同一个请求在服务之间传递,地址栏不变,也叫服务器跳转。
重定向:由客户端发送一次新的请求来访问跳转后的目标资源,地址栏改变,也叫客户端跳转
如果两个页面之间需要通过request来传值,则必须要转发,不饿能使用重定向
- 用户登录,如果用户名和密码正确,则跳转到首页(首页),并展示用户名,否则重新回到登陆页面(重定向)
-
-
Session
-
用户会话
服务器无法识别每一次HTTP请求的出处(不知道来自哪个终端),他只会接受一个请求信号,所以就存在一个问题:将用户的响应发送给别人,必须有一种技术来让服务器知道请求来自哪里,这就是会话技术。
会话:就是客户端和服务器之间发生的一系列连续的请求和响应的过程,打开浏览器进行操作到关闭浏览器的过程。
会话状态:指服务器和浏览器在会话过程中产生的状态信息,借助于会话状态,服务器能够把属于同一次会话的一系列请求和响应关联起来。
实现会话两种方式
- session
- cookie
属于同一次会话的请求都有一个相同的标识符,sessionID
session常用的方法:
- String getID()获取到当前的sessionID
- void setMaxINactiveInterval(int interval)设置session的失效时间单位为秒
- int getMaxIncativeInterval() 获取session的失效时间
- void invalidate() 设置session立即失效
- void serAttribute(String key,Object value) 通过键值对的形式来存储数据
- Object getAtrribute(String key) 通过键值获取对应的数据
- void removeAtrribute(String key) 通过键值删除对应的数据
-
Cookie
-
Cookie是服务端在HTTP响应中附带传给浏览器的一个小文本文件,一旦浏览器保存了某个Cookie,在之后的请求和响应过程中会将Cookie来回传递,这样就可以通过Cookie这个载体完成客户端和服务器的数据交互。
Cookie
- 创建Cookie
Cookie cookie = new Cookie("name", "lisi"); 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) { //out.write(cookie.getName() + ":" + cookie.getValue()); 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
allication作用域:对应的内置对象是application
-
page<request<session<appllication
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)中保存的数据,前提是一定先setArribute,EL就相当于在简化getArrtibute()
${变量名} 变量名就是setAttrribute对应的key值.
1. EL对于4种域对象的默认查找顺序:
pageContext->request->session->application
按照上述的顺序进行查找,找到就立即返回,在application中无法找到,则返回null
-
指定作用域进行查找
${内置对象Scope.name}
例如:${sessionScope.name}
数据级联:
<% // pageContext.setAttribute("name", "page");//优先级最高,最先查找 // request.setAttribute("name", "request"); // session.setAttribute("name","session"); // application.setAttribute("name","application"); // //request.getRequestDispatcher("el2.jsp").forward(request,response); User user = new User(1,"张三",98.5,new Address(1,"欻大")); pageContext.setAttribute("user",user); %> <table> <tr> <th>编号</th> <th>姓名</th> <th>成绩</th> <th>地址</th> </tr> <tr> <td>${user.id}</td> <% //((User)pageContext.getAttribute("user")).getId(); %> <td>${user.name}</td> <td>${user.score}</td> <td>${user.address.value}</td> </tr> </table>
$(user["id"])
EL执行表达式
&&||! < > <= >=
&&and ||or ! not == eq !=ne <lt >gt <=le >=ge
empty变量为null,长度为0的string,size为0的集合
JSTL
JSP Standard Tag LibraryJSP标准标签库,JSP为开发者提供一系列的标签,使用这些标签可以完成一些逻辑处理,比如循环遍历集合,让代码更加简洁,不再出现JSP脚本穿插的情况。
实际开发中EL和JSTL结合使用,JSTL侧重于逻辑处理,EL负责展示数据
JSTL的使用
-
需要导入jar包(两个jstl,jar standard.jar)
存放的位置是web/WEB-INF/lib
-
在JSP页面开始的地方导入JSTL标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
-
在需要的地方使用
<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:向域对象添加数据
<%
reuqest.setAttribute(Key,value)
%>
<c:set var="name" value="tom" scope="request"></c:set>
<%
User user = new User(1,"张三",56.2,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 = 1/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="1" step="2" end="5" varStatus="sta"> <%--{sta.index} - ${str}<br/>--%> ${sta.count} - ${str}<br/> </c:forEach>
格式化标签库常用的标签:
<% request.setAttribute("data", new Date()); %> <fmt:formatDate value="${data}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate> <fmt:formatNumber value="32145.23434" maxFractionDigits="3" maxIntegerDigits="2"></fmt:formatNumber>
函数标签库
<% request.setAttribute("ignfo", "Java,C"); %> ${fn:contains(ignfo, "Python") }<br/> ${fn:startsWith(ignfo, "Java")}<br/> ${fn:endsWith(ignfo, "C")}<br/> ${fn:indexOf(ignfo, "va")}<br/> ${fn:replace(ignfo,"C", "Python")}<br/> ${fn:substring(ignfo, 2,3 )}<br/> ${fn:split(ignfo, "," )[0]}-${fn:split(ignfo, ",")[1]}<br/>
-
过滤器
-
Filter
功能:
- 用来拦截传入的请求和传出的响应
- 修改或以某种方式处理正在客户端和服务端之间交换的数据流
如何使用?
与使用Servlet类似,Fiter是Java WEB提供的一个几口,开发者只需要自定义一个类并且实现该接口即可。
public class CharacterFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8");
filterChain.doFilter(servletRequest,servletResponse);
}
}
web.xml进行配置Filter
<filter>
<filter-name>character</filter-name>
<filter-class>com.gopan.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>character</filter-name>
<url-pattern>/login</url-pattern>
<url-pattern>/text</url-pattern>
</filter-mapping>
注意:Filter处理完业务逻辑之后,一定要添加filterChain.doFilter(servletRequest,servletResponse);
Filter生命周期
当Tomcat启动时,通过反射机制调用Filter的无参构造函数创建实例化对象,同时调用init实现初始化,doFilter方法调用多次,当Tomcat服务关闭的时候,调用destroy来销毁Filter对象
无参构造函数:只调用一次,当Tomcat启动时调用(Filter一定要进行配置)
init方法:只调用一次Filter实例化对象创建完成后调用
doFilter:调用多次,访问Filter的业务逻辑都写在Filter中
destory:只调用一次mTomcat关闭时调用
同时配置多个Filter,Filter的调用顺序由web.xml中的配置顺序来决定,写在上面的配置先调用,因为web.xml是由上到下读取数据的
<filter>
<filter-name>character</filter-name>
<filter-class>com.gopan.filter.CharacterFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>character</filter-name>
<url-pattern>/login</url-pattern>
<url-pattern>/text</url-pattern>
</filter-mapping>
<filter>
<filter-name>myfilter</filter-name>
<filter-class>com.gopan.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>/login</url-pattern>
<url-pattern>/text</url-pattern>
</filter-mapping>
也可以通过注解的方式来简化web.xml的配置
@WebFilter("/login")
public class Myfilter implements Filter{
}
实际开发中的Filter的使用场景
-
统一处理中文乱码
-
屏蔽,敏感词
@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"); System.out.println(name); name = name.replaceAll("敏感词","***"); System.out.println(name); servletRequest.setAttribute("name", name); filterChain.doFilter(servletRequest,servletResponse); } } @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(name); } }
-
控制资源的访问权限
文件上传下载
-
JSP
- input的type设置为file
- form表单的method设置为post,get请求会将文件名传给服务端,而不是文件本身
- form表单的enctype值设置为multipart/form-data,以二进制的形式传输数据
-
Servlet
fileupload组件可以将所有的请求信息都解析成FileIteam对象,可以通过FileItem对象的操作完成上传,面向对象的思想。
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /* //输入流 req.setCharacterEncoding("UTF-8"); ServletInputStream 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();*/ /*int temp = 0; while ((temp = inputStream.read())!=-1){ System.out.println(temp); }*/ DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(); ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory); try { 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 fileNmae = fileItem.getName(); long size = fileItem.getSize(); System.out.println(fileNmae+ ":"+size+"Byte"); InputStream inputStream = fileItem.getInputStream(); String path = req.getServletContext().getRealPath("file/"+fileNmae); OutputStream outputStream =new FileOutputStream(path); int temp = 0; while((temp = inputStream.read())!=-1){ outputStream.write(temp); } outputStream.close(); inputStream.close(); System.out.println("上传成功..."); } } } catch (FileUploadException e) { e.printStackTrace(); } }
<form enctype="multipart/form-data" action="/upload" method="post"> <input type="text" name="desc"><br/> <input type="file" name="file"><br/> <input type="submit" value="上传"> </form>
文件下载
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String type= req.getParameter("type");
String fileName = "";
switch (type){
case "png":
fileName = "123.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
asnchronous javascript and XML 异步的JavaScript和XML
AJAX不是新的编程,指的是一种交互方式,异步加载,客户端和服务器的数据交互更新在局部页面的技术,不需要刷新整个页面(局部刷新)
优点:
- 局部刷新,效率更高
- 用户体验更好
基于jQuery的AJAX
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-1.7.2.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) {
$("#id").val(data.id);
$("#name").val(data.name);
$("#score").val(data.score);
},
error:function () {
alert("服务器正在维护中...")
},
complete:function () {
alert("请求完成!")
}
});
});
})
</script>
</head>
<body>
编号:<input type="text" id="id"/><br/>
姓名:<input type="text" id="name"/><br/>
成绩:<input type="text" id="score"/><br/>
<input type="button" value="提交" id="btn">
</body>
</html>
不能用表单的提交方式,改用JjQuery方式动态绑定事件来提交。
Servlet不能跳转到JSP,只能将数据返回
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String id =req.getParameter("id");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
String str = "HRllo";
resp.getWriter().write(str);
}
传统的WEB数据交互 VS AJAX的数据交互
-
客户端请求方式不同
- 传统:浏览器发送同步请求(Form,a)
- AJAX:异步引擎对象发送异步请求
-
服务器响应方式不同
- 传统:响应一个完整的JSP页面
- JAJAX:响应需要的数据
-
客户端处理方式不同
- 传统:需要等待服务器完成响应并且重新加载整个页面之后,用户才能进行后续的操作
- AJAX:动态更新页面中的局部内容,不影响用户的其他操作
AJAX原理
基于jQuery的AJAX语法
$.ajax({属性})
- 常用的属性参数:
- url 请求的后端服务地址
- type请求的范式,默认get
- data请求的参数
- dataType服务器返回的数据类型text/json
- success请求成功的回调函数
- error请求失败的回调函数
- complete请求完成的回调函数(无论成功还是失败,都会调用)
JSON
JavaScript Object Notion 一种轻量级数据交互格式,完成js与Java等后端开发语言对象数据之间的转换
客户端和服务器之间传递对象数据,需要用到JSON格式
public class User {
private Integer id;
private String name;
private Double score;
public User(Integer id, String name, Double score) {
this.id = id;
this.name = name;
this.score = 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;
}
}
User user = new User(1, "张三", 56.2);
var user = {
id:1,
name:"张三",
score:45.5
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
User user = new User(1, "张三", 56.2);
resp.setCharacterEncoding("UTF-8");
// resp.getWriter().write(user.toString());
//需要将Java对象转换成JSON格式
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-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
var btn = $("#btn");
btn.click(function () {
$.ajax({
url:'/test',
type:'post',
data:'id=1',
dataType:'json',
success:function (data) {
$("#id").val(data.id);
$("#name").val(data.name);
$("#score").val(data.score);
},
error:function () {
alert("服务器正在维护中...")
},
complete:function () {
alert("请求完成!")
}
});
});
})
</script>
</head>
<body>
编号:<input type="text" id="id"/><br/>
姓名:<input type="text" id="name"/><br/>
成绩:<input type="text" id="score"/><br/>
<input type="button" value="提交" id="btn">
AJAX
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/jquery-1.7.2.js"></script>
<script>
$(function () {
//修改城市
$("#province").change(function () {
var id = $(this).val()
$.ajax({
url:"location",
type:"POST",
data:"id="+id+"&type=province",
dataType:"JSON",
success:function (data) {
console.log(data)
var content = "";
var cities = data.cities;
for (var i=0; i<cities.length;i++){
content += "<option>"+ cities[i] + "</option>";
}
$("#city").html(content);
var 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>
@WebServlet("/location")
public class LocationServlet extends HttpServlet {
private static Map<String, List<String>> cityMap;
private static Map<String, List<String>> procinceMap;
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("临渭区");
areas.add("新城区");
cityMap.put("渭南市", areas);
areas = new ArrayList<>();
areas.add("高新A区");
areas.add("临渭B区");
areas.add("新城C区");
cityMap.put("惠州市", areas);
areas = new ArrayList<>();
areas.add("陈仓A区");
areas.add("渭滨B区");
areas.add("新城C区");
cityMap.put("潮州市", areas);
/* areas = new ArrayList<>();
areas.add("雁塔A区");
areas.add("莲湖B区");
areas.add("新城C区");
cityMap.put("宝鸡市",areas);*/
procinceMap = new HashMap<>();
List<String> cites = new ArrayList<>();
cites.add("西安市");
cites.add("宝鸡市");
cites.add("深圳市");
procinceMap.put("陕西省",cites);
cites = new ArrayList<>();
cites.add("南宁市");
cites.add("广州市");
cites.add("珠海市");
procinceMap.put("河南省",cites);
cites = new ArrayList<>();
cites.add("惠州市");
cites.add("潮州市");
cites.add("香港市");
procinceMap.put("江苏省",cites);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
String type = req.getParameter("type");
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> citis = procinceMap.get(id);
String city = citis.get(0);
List<String> cityAreas = cityMap.get(city);
Location location =new Location();
location.setAreas(cityAreas);
location.setCities(citis);
JSONObject jsonObject = JSONObject.fromObject(location);
resp.getWriter().write(jsonObject.toString());
int i = 0;
break;
}
}
}
JDBC
Java Database Connectivity 是一个独立于特定数据库的管理系统,通用的SQL数据库存取和操作的公共接口。
定义了一组标准,为访问不同的数据库提供了不同数据库提供了统一的途径。
JDBC体系结构
JDBC接口包括两个层面:
- 面向应用的API,提供程序员调用
- 面向数据库API,供厂商开发数据库的驱动程序
JDBC API
提供者:Java官方
内容:共开发者调用的接口
java.sql和jjavax.sql
- DriverManager类
- Connection接口
- Statement接口
- ResultSet接口
DriverManager
提供者:Java官方
作用:管理不同的JDBC驱动
JDBC驱动
提供者:数据库厂商
作用:负责连接不同的数据库
JDBC的使用
- 加载数据库驱动,Java程序和数据库之间的桥梁
- 获取Connection,Java程序与数据库的一次链接
- 创建Statement对象,由Connection产生,执行SQL语句
- 如果需要接收返回值,创建ResultSet对象,保存Statement执行之后的所查询到的结果。
PreparedStatement
Statement的子类,提供了SQL占位符的功能
使用Statement进行开发有两种问题:
- 需要频繁拼接String字符串,出错频率较高
- 存在SQL注入的风险
SQL注入:利用某些系统没有对用户输入的信息进行充分检测,在用户输入的数据中注入非法的SQL语句,从而利用系统的SQL引擎完成恶意行为的做法
数据库连接池
JDBC开发流程:
- 加载驱动(只需要加载一次)
- 建立数据库连接(Connection)
- 执行sql语句(Statement)
- ResultSet接收结果集(查询)
- 断开连接,释放资源
数据库连接对象是通过DriverManager来获取的,每次获取都需要向数据库申请获取连接,验证用户和密码
执行完SQL语句后断开连接,这种方式会造成资源的浪费,数据库资源没有得到很好的重复利用。
可以用数据库连接池解决这一问题
数据库连接池,就是为数据库建立一个缓冲池,预先向缓冲池中放入一定数量的连接对象,当需要获取数据库链接的时候,只需要从缓冲池取出一个对象,用完之后再放回到缓冲池中,供下一次请求使用,做到了资源的重复利用,允许程序重复使用一个现有的数据库连接对,而不需要重新创建。
当数据库连接池中没有空闲的连接时,新的请求就会进入等待队列,等待其它线程释放连接。
数据库连接池
JDBC的数据库连接池使用java.sql.DataSourse接口来完成的,DataSourse是Java官方提供的接口,使用的时候开发者并不需要自己来实现该接口,可以用第三方工具,C3P0是一个第三方实现,实际开发中直接,使用C3P0ji'wan'cheng2是菊科连接池的操作。
-
导入jar架包。
传统方式拿到的Connection
com.mysql.cj.jdbc.ConnectionImp1@557caf28
C3P0拿到的Connection
com.mchange.v2.c3p0.impl.NewPeoxyConnection@4988d8b8
-
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://127.0.0.1:3306/test?characterEncoding=UTF-8"); dataSource.setUser("root"); dataSource.setPassword("123456"); Connection conn = dataSource.getConnection(); System.out.println(conn); //返回到数据库池中 conn.close(); } catch (PropertyVetoException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }
实际开发中,将c3p0的配置信息定义在xml文件中,Java程序只需要加载配置文件即可完成数据库连接池的初始化操作
- 配置文件的名字必须是c3p0-config.xml
- 初始化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">123456</property> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/test</property> <!-- 初始化连接池连接数量 --> <property name="initialPoolSize">5</property> <!-- 数据库连接池最小的数据库连接数 --> <property name="minPoolSize">5</property> <!-- 数据库连接池最大的数据库连接数 --> <property name="maxPoolSize">10</property> <!-- 连接数不足,一次向数据库服务器申请多少个链接 --> <property name="acquireIncrement">5</property> </named-config> </c3p0-config>
public class DataSourceTest { public static void main(String[] args) { try { //创建C3P0 ComboPooledDataSource dataSource = new ComboPooledDataSource("testc3p0"); Connection conn = dataSource.getConnection(); System.out.println(conn); //返回到数据库池中 conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
DBUtils
DBUtils可以帮助开发者完成数据的封装(结果集到Java对象的映射)
-
导入架包
ResultHandler接口是用来处理结果集,可以将查询到的结果集转换成java对象,提供了4
中实现类
- BeanHander 讲结果集映射成java对象Student
- BeanListHandler 将结果集映射成List集合List
- MapHandler 将结果集映射成Map对象
- MapListHandler 将结果集映射成MapLsit结合