控制浏览器行为技术:HTML、CSS、JavaScript
控制硬盘上数据库行为技术:MySql数据库服务器管理使用(SQL重点),JDBC规范
控制服务端Java行为技术:Http服务器,Servlet,JSP
互联网通信流程开发规则:MVC
两台计算机通过网络实现文件共享行为
(1)客户端软件专门安装在客户端计算机上
(2)帮助客户端计算机向指定服务端计算机发送请求,索要资源文件
(3)帮助客户端计算机将服务端计算机发送回来 二进制数据 解析为 文字、数字、图片、视频、命令、
(1)服务器软件专门安装在服务端计算机上
(2)服务器软件用于接收来自于特定的客户端软件发送请求
(3)服务器软件在接收到请求之后自动的在服务端计算机上定位被访问的资源文件
(4)服务器软件自动的将定位的文件内容解析为 二进制数据 通过网络发送回发起请求的客户端软件上
个人娱乐:微信,电商,视频网站;企业办公领域应用少
(1)浏览器,安装在客户端计算机软件
(2)可以向任意服务器发送请求,索要资源文件
(3)可以将服务器返回的 二进制数据 解释为 文字、数字、图片、视频、命令
(1)服务器软件专门安装在服务端计算机上
(2)可以接受任何浏览器发送请求
(3)自动的在服务端计算机上定位被访问的资源文件
(4)自动的将定位的资源文件内容以二进制形式发送会发送请求浏览器上
既适用于个人,更适用于企业
(1)静态资源文件
(2)动态资源文件
(1)如果文件内容是固定的,就被称为静态资源文件
(2)如果文件存放的是命令,这些命令只能在浏览器编译与执行,也被称为静态资源文件(.html、.css、.js)
静态资源文件被索要时,Http服务器直接通过输出流将静态文件内容或者命令以二进制形式推送给发起请求的浏览器
动态资源文件被索要时,Http服务器需要创建当前class文件的实例对象,通过实例对象调用对应的方法处理用户请求,通过输出流将运行结果以二进制形式推送给发起请求的浏览器
Http服务器上保存静态资源文件和动态资源文件
<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"
metadata-complete="true">
web-app>
关于 Mapping 的问题
<servlet-mapping>
<servlet-name>HelloServletservlet-name>
<url-pattern>/servlet/*url-pattern>
servlet-mapping>
2.默认请求路径(会把index页面取代,少用)
<servlet-mapping>
<servlet-name>HelloServletservlet-name>
<url-pattern>/servlet/*url-pattern>
servlet-mapping>
3.自定义后缀,注意:不能在*前面加上映射路径。
<servlet-mapping>
<servlet-name>HelloServletservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
4.优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求。
ServletContext是一个全局的储存信息的空间,服务器开始就存在,服务器关闭才释放。
在web容器启动的时候,服务器会为每个web程序创建对应的一个ServletContext,代表当前的web应用。
一个web应用对应一个ServletContext。
this.getServletContext();
this.getServletConfig().getServletContext()
//添加属性:
setAttribute(String name, Object obj);
//得到值:
getAttribute(String name),这个方法返回Object
//删除属性:
removeAttribute(String name)
//ServletContext中的属性的生命周期从创建开始,到服务器关闭结束。
1、多个Servlet可以通过ServletContext对象来实现数据间的共享
(可用Session或者request的方法将其取代)
类似于Session,通过ServletContext对象我们也可以实现数据共享,但值得注意的是,Session是只能在一个客户端中共享数据,而ServletContext中的数据是在所有客户端中都可以实现数据共享的。
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Hello");
resp.setContentType("text/html;utf-8");
//获得当前的ServletContext
//ServletContext可以实现数据共享
ServletContext context = this.getServletContext();
String username = "text";
//在web容器启动的时候,服务器会为每个web程序创建对应的一个ServletContext。代表当前的web应用。一个web应用对应一个ServletContext
//将数据保存在本程序对应的ServletContext中,键值对的形式保存
context.setAttribute("username",username);
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
ServletContext context = this.getServletContext();
//获取资源
String username = (String) context.getAttribute("username");
//在页面输出
resp.getWriter().println(""
+"名字"+username+"");
}
2、0.获取全局初始化参数
//获取初始化参数
public abstract String getInitParameter(String s)
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
ServletContext context = this.getServletContext();
//获得初始化参数
resp.getWriter().println(context.getInitParameter("texturl"));
}
<context-param>
<param-name>texturlparam-name>
<param-value>jdbc:mysql://localhost:3306/mybatisparam-value>
context-param>
2、1.获取当前Servlet的配置参数(局部)
<servlet>
<servlet-name>ServletDemoservlet-name>
<servlet-class>com.vigil.servlet.ServletDemoservlet-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
servlet>
String encoding = this.getServletConfig().getInitParameter("encoding");
3、请求转发
(一般用request实现)
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//请求路径
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/Demo0");
//调用forward实现请求转发
requestDispatcher.forward(req,resp);
}
这种转发效果与通过request对象的getRequestDispatcher("/url").forward(req,resp)方法一样
//效果一样的转发方式
request.getRequestDispatcher("/url").forward(req, resp);
//
this.getServletContext().getRequestDispatcher("/url").forward(req, resp)
4、读取资源文件
(尽量用类加载和反射实现这一目的)
如何确定资源地址(getResourceAsStream(url))是一个重点
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 这种方法的默认读取路径就是Web应用的根目录
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
// 创建属性对象
Properties prop = new Properties();
prop.load(is);
String user = prop.getProperty("username");
String pwd = prop.getProperty("password");
resp.getWriter().println(user + ":" + pwd);
}
username=root
password=123456
涉及到不同用户共享数据,而这些数据量不大,同时又不希望写入数据库中,我们就可以考虑使用ServletContext实现。
例如:1. 网站计数器 2. 网站的在线用户显示
注意:因为存在ServletContext中的数据在服务器中会长时间,这样就会占用很多内存,因此在使用ServletContext时,建议不要往里面添加过大的数据!
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HTTPServletRequest对象,代表响应的HttpServletResponse
(1)负责像浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
(2)负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
(3)响应状态码
int SC_CONTINUE = 100;
int SC_SWITCHING_PROTOCOLS = 101;
int SC_OK = 200;
int SC_CREATED = 201;
int SC_ACCEPTED = 202;
int SC_NON_AUTHORITATIVE_INFORMATION = 203;
int SC_NO_CONTENT = 204;
int SC_RESET_CONTENT = 205;
int SC_PARTIAL_CONTENT = 206;
int SC_MULTIPLE_CHOICES = 300;
int SC_MOVED_PERMANENTLY = 301;
int SC_MOVED_TEMPORARILY = 302;
int SC_FOUND = 302;
int SC_SEE_OTHER = 303;
int SC_NOT_MODIFIED = 304;
int SC_USE_PROXY = 305;
int SC_TEMPORARY_REDIRECT = 307;
int SC_BAD_REQUEST = 400;
int SC_UNAUTHORIZED = 401;
int SC_PAYMENT_REQUIRED = 402;
int SC_FORBIDDEN = 403;
int SC_NOT_FOUND = 404;
int SC_METHOD_NOT_ALLOWED = 405;
int SC_NOT_ACCEPTABLE = 406;
int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
int SC_REQUEST_TIMEOUT = 408;
int SC_CONFLICT = 409;
int SC_GONE = 410;
int SC_LENGTH_REQUIRED = 411;
int SC_PRECONDITION_FAILED = 412;
int SC_REQUEST_ENTITY_TOO_LARGE = 413;
int SC_REQUEST_URI_TOO_LONG = 414;
int SC_UNSUPPORTED_MEDIA_TYPE = 415;
int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
int SC_EXPECTATION_FAILED = 417;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_NOT_IMPLEMENTED = 501;
int SC_BAD_GATEWAY = 502;
int SC_SERVICE_UNAVAILABLE = 503;
int SC_GATEWAY_TIMEOUT = 504;
int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
(1)向浏览器输出消息
(2)下载文件
//关于字符串url
1、要获取下载的文件路径
2、下载的文件名
3、设置想办法让浏览器能够支持下载我们需要的东西
4、获取下载的文件输入流
//以下为Java io学习
5、创建缓冲区
6、获取OutputStream对象
7、将FileOutputStream流写入到buffer缓冲区
8、使用OutputStream将缓冲区中的数据输入到客户端
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、要获取下载的文件路径(java io 基础,这里写死了一个地址,仅作练习)
String realPath = "D:\\javadownload\\ideaworkplace\\javaweb-02-servlet\\response01\\src\\main\\resources\\1.jpg";
System.out.println("下载文件的路径:" + realPath);
// 2、下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
// 3、设置(响应头)想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码
resp.setHeader("Content-Disposition","attachment;filename"+ URLEncoder.encode(fileName,"UTF-8"));
// 4、获取下载的文件输入流(将文件变成流)
FileInputStream in = new FileInputStream(realPath);
// 5、创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6、获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
// 7、将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输入到客户端
while((len = in.read(buffer))>0) {
out.write(buffer,0,len);
}
// 8、关闭流
in.close();
out.close();
}
(3)验证码功能
前端实现:jsp
后端实现:需要使用Java的图片,产生一个图片
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器5s自动刷新一次
resp.setHeader("refresh","5");
//在内存中创建图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D g = (Graphics2D) image.getGraphics();//笔
//设置图片颜色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.blue);//换色
g.setFont(new Font(null,Font.BOLD,20));//设置字体
g.drawString(getNum(),0,20);
//告诉浏览器,这个请求用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,设置不让浏览器缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
//生成随机数
private String getNum() {
Random r = new Random();
String num = r.nextInt(999999) + "";
//确保生成的随机数长度为6
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 6 - num.length(); i++) {
sb.append(""+r.nextInt(10));
}
return sb.toString() + num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
B一个web资源,收到客户端A请求后,B会通知A客户端去访问另一个web资源C,这个过程叫做重定向。
重定向的时候一定要注意路径问题,否则会有404错误
常见:用户登录
void sendRedirect(String var1) throws IOException;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
r01是本程序的projectName
resp.setHeader("Location","r01/image");
resp.setStatus(302);
*/
resp.sendRedirect("r01/image");//重定向
}
面试题:请你聊聊重定向和转发的区别(手动搜索)
相同点:页面都会实现转换
不同点:请求转发的时候,url不会产生变化,重定向时候,url地址栏会发生变化
HTTPServletRequest代表客户端的请求,用户通过Http协议访问服务器,HTTP请求中的所有信息会被封装到HTTPServletRequest,通过这个HTTPServletRequest的方法,获得客户端的所以信息。
String getAuthType();
Cookie[] getCookies();
long getDateHeader(String var1);
String getHeader(String var1);
Enumeration getHeaders(String var1);
Enumeration getHeaderNames();
int getIntHeader(String var1);
String getMethod();
String getPathInfo();
String getPathTranslated();
String getContextPath();
String getQueryString();
String getRemoteUser();
Principal getUserPrincipal();
String getRequestedSessionId();
String getRequestURI();
StringBuffer getRequestURL();
String getServletPath();
HttpSession getSession(boolean var1);
HttpSession getSession();
//LoginServlet
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobbys");
System.out.println("================================");
System.out.println(username+":"+password);
System.out.println(Arrays.toString(hobbys));
System.out.println("================================");
//通过请求转发
//这里的 / 代表当前web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);//处理Post请求时,转到doGet方法中
}
<%--index页面--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Logintitle>
head>
<body>
<h1>登录h1>
<div style="text-align: center">
<%--以post方式提交表单到login页面--%>
<form action="${pageContext.request.contextPath}/login" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
爱好:
<input type="checkbox" name="hobbys" value="唱歌">唱歌
<input type="checkbox" name="hobbys" value="代码">代码
<input type="checkbox" name="hobbys" value="跳舞">跳舞
<input type="checkbox" name="hobbys" value="电影">电影
<br>
<input type="submit">
form>
div>
body>
html>
<%--登录成功的页面--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>successtitle>
head>
<body>
<h1>登陆成功h1>
body>
html>
request.setAttribute():在request范围一次传参数,速度快,缺点是参数只能取一次。
request.getSession().setAttribute():取得当前HttpSession,在HttpSession范围保存参数,就一直在,随时可以取来用。缺点是比较占用资源。
session.setAttribute()和session.getAttribute()配对使用,作用域是整个会话期间,在所有的页面都使用这些数据的时候使用。
request.setAttribute()和request.getAttribute()配对使用,作用域是请求和被请求页面之间。request.setAttribute()是只在此action的下一个forward需要使用的时候使用;request.getAttribute()表示从request范围取得设置的属性,必须要先setAttribute设置属性,才能通过getAttribute来取得,设置与取得的为Object对象类型。其实表单控件中的Object的 name与value是存放在一个哈希表中的,所以在这里给出Object的name会到哈希表中找出对应它的value。setAttribute()的参数是String和Object。
request.getParameter()表示接收参数,参数为页面提交的参数。包括:表单提交的参数、URL重写(就是xxx?id=1中的id)传的参数等,因此这个并没有设置参数的方法(没有setParameter()),而且接收参数返回的不是Object,而是String类型。
request.getSession().setAttribute(“adminid”,adminForm.getAdminid())把adminForm.getAdminid())返回值保存到session当前会话中,名称为adminid,只要当前会话不过期, 任何地方都可以访问到 ;request.setAttribute(“adminid”,adminForm.getAdminid())把adminForm.getAdminid())的返回值保存到request当前请求中,名称为adminid,只在当前请求中访问到,其他请求中无法访问。
request.setAttribute这个的生命周期就是request级别的
request.getSession().setAttribute这个的生命周期是session级别的
request.getParameter() 和request.getAttribute() 区别
(1)request.getParameter()取得是通过容器的实现来取得通过类似post,get等方式传入的数据,request.setAttribute()和getAttribute()只是在web容器内部流转,仅仅是请求处理阶段。
(2)request.getParameter()方法传递的数据,会从Web客户端传到Web服务器端,代表HTTP请求数据。request.getParameter()方法返回String类型的数据。
request.setAttribute()和getAttribute()方法传递的数据只会存在于Web容器内部
还有一点就是,HttpServletRequest类有setAttribute()方法,而没有setParameter()方法。
request.getAttribute()与request.setAttribute()
request.getAttribute(“nameOfObj”)可得到JSP页面一表单中控件的Value。其实表单控件中的Object的 name与value是存放在一个哈希表中的,所以在这里给出Object的name会到哈希表中找出对应它的value。
而不同页面间传值使用request.setAttribute(position, nameOfObj)时,只会从a.jsp到b.jsp一次传递,之后这个request就会失去它的作用范围,再传就要再设一个 request.setAttribute()。而使用session.setAttribute()会在一个过程中始终保有这个值。
P.S:JavaScript与JSP中不能相互传值,因为JavaScript运行在客户端,而JSP运行在服务器端。若想使它们之间可以相互传递参数,可以在JSP中设置一个hidden控件,用它的value结合上面所说的用法来传递所需的数值。
用户通过浏览器(客户端),点击一个网页的超链接等去访问多个web资源,直到关闭浏览器的过程。
一个网站如何知道一个客户端?第一次会给客户端一个cookie,在服务器端创建相应的session,下一次,客户端只要有相应的cookie和服务器端的session匹配即可。(也即是SessionID匹配)
cookie 客户端技术(响应,请求)
session 服务器技术,利用这个技术,可以把信息或者数据放在session上
//保存用户本次登录的时间,并输出上一次和本次的登录时间
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
//从请求中获得cookie,为什么这么说,是因为客户端向服务器请求会提交客户端本地的cookie
Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
String nowTime = getTime();//获得当前时间
//判断cookie是否存在
if (cookies != null) {
int flag = 0;
//遍历cookie数组
for (Cookie cookie : cookies) {
if ("lastLoginTime".equals(cookie.getName())) {
out.println("你上一次登录的时间是:"
+ cookie.getValue() +
"现在的时间是:"
+ nowTime + "");
flag = 1;
}
}
if(flag == 0)
out.println("这是你第一次访问本站
现在的时间是:"
+ nowTime + "");
} else {
out.println("这是你第一次访问本站
现在的时间是:"
+ nowTime + "");
}
//服务器给客户端发送cookie
Cookie cookie = new Cookie("lastLoginTime", nowTime);
//设置有效期
cookie.setMaxAge(1*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
//获得时间
private String getTime() {
SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
Date date = new Date(System.currentTimeMillis());
return formatter.format(date);
}
//重要方法
Cookie[] cookies = req.getCookies();//获得cookie对象
cookie.getName()//获得cookie中的key
cookie.getValue()//获得cookie的value
Cookie cookie = new Cookie("lastLoginTime", newTime);//新建一个cookie对象
cookie.setMaxAge(1*60*60);//设置cookie的有效期
resp.addCookie(cookie);//响应给服务器
(间接删除,新建同名的cookie,此同名不是变量名同名,是指cookie.getName()返回的名是一致的,也即是cookie初始化对象传进去的第一个参数)
//手动删除cookie
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//服务器给客户端发送cookie,名字和要被删去的cookie一致
Cookie cookie = new Cookie("lastLoginTime","text");
//设置有效期为0,马上过期
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
Cookie处理中文时编码问题:cookie里面保存的数据类型为ASCII码,并不能直接保存中文。相应的报错为:Control character in cookie value or attribute.
利用工具类对中文编码保存,解码使用 (URLEncode)
//重要方法
URLEncoder.encode("测试","UTF-8")//编码
URLDecoder.decode(cookie.getValue(),"UTF-8")//解码
//中文传输的乱码问题
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
//从请求中获得cookie,为什么这么说,是因为客户端向服务器请求会提交客户端本地的cookie
Cookie[] cookies = req.getCookies();//这里返回数组,说明cookie可能存在多个
if(cookies != null) {
for (Cookie cookie : cookies) {
if("name".equals(cookie.getName())) {
out.println(URLDecoder.decode(cookie.getValue(),"UTF-8"));
System.out.println(cookie.getValue());
}
}
}
resp.addCookie(new Cookie("name", URLEncoder.encode("测试","UTF-8")));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
推荐再看:JavaWeb学习总结(十二)——Session
什么是Session
Session和Cookie的区别
使用场景:
Session方法使用
//SessionDemo01
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//得到Session
HttpSession session = req.getSession();
//给Session中存东西
session.setAttribute("Person", new Person(9,"测试"));
//获得Session的ID
String id = session.getId();
//判断Session是不是新创建的
if (session.isNew()) {
resp.getWriter().println("Session创建成功,ID为:" + id);
} else {
resp.getWriter().println("Session已经在服务器中存在,ID为:" + id);
}
}
//SessionDemo02
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//得到Session
HttpSession session = req.getSession();
Person person = (Person) session.getAttribute("Person");
if(person != null) {
resp.getWriter().println(person.toString());
System.out.println(person.toString());
} else {
resp.getWriter().println("no person");
}
}
//手动注销session
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("Person");
session.invalidate();//注销session
}
<!--设置Session的默认失效时间-->
<session-config>
<!--10分钟后session自动失效,一分钟为单位-->
<session-timeout>10</session-timeout>
</session-config>
Java服务器端页面,和Servlet一样用于实现动态页面的技术
最大的特点:写JSP就像写HTML,区别是
1、HTML只给用户提供静态的数据
2、JSP页面中可以嵌入Java代码,为用户提供动态数据
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
JSP本质是一个Servlet,他最终会被转化为一个Java类
public void _jspInit() {
}//初始化
public void _jspDestroy() {
}//销毁
//服务,有两个传入的对象!!request和response
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) {
}
是_jspService(req,resp){}方法独有的(八个常用的,最后两个对象略略略)
//jsp的十个内置对象(八个常用的,最后两个对象略略略)
request //请求
response //响应
final javax.servlet.jsp.PageContext pageContext; //页面上下文
javax.servlet.http.HttpSession session = null; //session
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //配置
javax.servlet.jsp.JspWriter out = null; //输出
final java.lang.Object page = this; //当前页
exception 对象
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
response.setContentType("text/html;charset=UTF-8");//页面输出配置
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
在JSP页面中,只要是Java代码就会原封不动的输出,但是如果是HTML代码就会被转成类似下面这种在输出到前端
out.write("\r\n");
out.write("\r\n");
要写JSP首先要配好环境,下面是pom.xml所缺少的代码
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
dependency>
<dependency>
<groupId>javax.servlet.jspgroupId>
<artifactId>javax.servlet.jsp-apiartifactId>
<version>2.3.3version>
dependency>
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
dependencies>
<%--JSP表达式
作用:用于将程序的输出到客户端
<%= 变量或者表达式%>
--%>
<%= 1+2 %>
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
out.println("sum="
+sum+"");
%>
<%--JSP脚本片段的实现
重点理解就是说,这些Java代码和HTML代码的转化,都是用out.print方法输出到前端
--%>
<%--在Java代码嵌入HTML元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h3>Hello <%=i %></h3>
<%
}
%>
<%--JSP声明,是属于类的,与前面的区别在于多了一个 !--%>
<%!
private int num = 0;
public void show() {
System.out.println("run the show method" + num);
}
static {
System.out.println("loading servlet");
}
%>
<% %>
<%= %>
<%! %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page errorPage="error/error500.jsp" %>
<%@ page isErrorPage="true" %>
(jsp中静态包含和动态包含的区别与联系)
因为包含的位置不是完全相同的,对于变量的两者规范不一,jsp:include包含的话,多个页面之间存在的变量名可以一样且多次出现,但是<%@include%>包含的话只允许变量在页面中与被包含页面只出现一次。
<%--@include会将两个页面合二为一,是在_jspService方法中初始化--%>
<%@include file="index.jsp" %>
<%--JSP标签
jsp:include:拼接页面,但他不会将其他的页面直接在_jspService方法中初始化--%>
<jsp:include page="index.jsp"></jsp:include>
<error-page>
<error-code>404</error-code>
<location>/error/error404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/error500.jsp</location>
</error-page>
<%--内置对象--%>
<%
pageContext.setAttribute("name0","测试0");//保存的数据只在一个页面中有效
request.setAttribute("name1","测试1");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name2","测试2");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name3","测试3");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%--通过pageContext取出我们保存的值--%>
<%
//通过寻找的方式
//从底层找起,pageContext-->request-->session-->application
String name0 = (String) pageContext.findAttribute("name0");
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
%>
<%--使用EL表达式输出 ${
} --%>
<h1>取出的值有:</h1>
<h3>${
name0}</h3>
<h3>${
name1}</h3>
<h3>${
name2}</h3>
<h3>${
name3}</h3>
<h3>${
name4}</h3>
<%-- pageContext-->request-->session-->application --%>
<%
pageContext.setAttribute("name0","测试0");//保存的数据只在一个页面中有效
request.setAttribute("name1","测试1");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name2","测试2");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name3","测试3");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
再说一遍,maven中,关于JSTL表达式要导入的包
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>taglibsgroupId>
<artifactId>standardartifactId>
<version>1.1.2version>
dependency>
<%-- 转发 --%>
<jsp:forward page="jsp4.jsp">
<jsp:param name="name" value="text"/>
<jsp:param name="age" value="12"/>
</jsp:forward>
JSP 标准标签库(JSTL)
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义许多标签,可供我们使用,标签的功能和Java代码一样
JSTL标签库使用方法
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<form action="jstlDemo01.jsp" method="get">//提交给本页面
<input type="text" name="name" value="${param.name}">//EL表达式获得提交的对应值
<input type="submit" value="登录">
</form>
<c:if test="${'admin'.equals(param.name)}" var="isAdmin">
<c:out value="欢迎你管理员"></c:out>
</c:if>
<c:out value="${isAdmin}"></c:out>
<c:set var="score" value="85"></c:set>
<c:choose>
<c:when test="${score>=90}">
你的成绩为优秀
</c:when>
<c:when test="${score>=80}">
你的成绩为良好
</c:when>
<c:when test="${score>=70}">
你的成绩为一般
</c:when>
<c:when test="${score>=60}">
你的成绩为合格
</c:when>
<c:when test="${score<60}">
你的成绩为不合格
</c:when>
</c:choose>
<%
ArrayList people = new ArrayList();
people.add(0,"李四");
people.add(1,"张三");
people.add(2,"王五");
people.add(3,"田七");
people.add(4,"吴孟达");
request.setAttribute("peopleliset",people);
%>
<%--var,每一次遍历出来的对象
item,遍历的对象数组
begin,开始的位置
end,结束的位置(包含的)
step步长
--%>
<c:forEach var="people" items="${peopleliset}">
<c:out value="${people}"></c:out>
<br>
</c:forEach>
<hr>
<c:forEach var="people" items="${peopleliset}" begin="1" end="3" step="2">
<c:out value="${people}"></c:out>
<br>
</c:forEach>
<%
people people = new people();
people.setAddress("西安");
people.setAge(21);
people.setId(1);
people.setName("李三");
out.print(people.getName());
out.print(people.getAge());
out.print(people.getId());
out.print(people.getAddress());
%>
<br>
<%=people.getName()%>
<%=people.getId()%>
<%=people.getAge()%>
<%=people.getAddress()%>
<%--jsp使用--%>
<jsp:useBean id="people" class="com.vigil.pojo.people" scope="page" />
<jsp:setProperty name="people" property="address" value="西安" />
<jsp:setProperty name="people" property="id" value="1" />
<jsp:setProperty name="people" property="age" value="21" />
<jsp:setProperty name="people" property="name" value="李三" />
姓名:<jsp:getProperty name="people" property="name"/>
年龄:<jsp:getProperty name="people" property="age"/>
ID:<jsp:getProperty name="people" property="id"/>
地址:<jsp:getProperty name="people" property="address"/>
JavaBean
一般用于和数据库的字段做映射 ORM:对象关系映射
public class people {
private int id;
private int age;
private String name;
private String address;
public people() {
}
public people(int id, int age, String name, String address) {
this.id = id;
this.age = age;
this.name = name;
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "people{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
<%
people people = new people();
people.setAddress("西安");
people.setAge(21);
people.setId(1);
people.setName("李三");
out.print(people.getName());
out.print(people.getAge());
out.print(people.getId());
out.print(people.getAddress());
%>
<br>
<%=people.getName()%>
<%=people.getId()%>
<%=people.getAge()%>
<%=people.getAddress()%>
<%----%>
<jsp:useBean id="people" class="com.vigil.pojo.people" scope="page" />
<jsp:setProperty name="people" property="address" value="西安" />
<jsp:setProperty name="people" property="id" value="1" />
<jsp:setProperty name="people" property="age" value="21" />
<jsp:setProperty name="people" property="name" value="李三" />
姓名:<jsp:getProperty name="people" property="name"/>
年龄:<jsp:getProperty name="people" property="age"/>
ID:<jsp:getProperty name="people" property="id"/>
地址:<jsp:getProperty name="people" property="address"/>
public class CharacterEncodingFilter implements Filter {
//初始化,web服务器启动时就初始化了,随时等待过滤
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("run the CharacterEncodingFilter");
}
//chain:链
/*
1.过滤中的所有的代码,在过滤特定请求的时候都会执行
2.必须要让过滤器继续执行
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("CharacterEncodingFilter doFiter run before");
chain.doFilter(request,response);//让我们的请求继续走,如果不写,程序到此被拦截结束。
System.out.println("CharacterEncodingFilter doFiter run after");
}
//销毁,web服务器关闭的时候,过滤器会销毁
public void destroy() {
System.out.println("destroy the CharacterEncodingFilter");
}
}
值得注意的不可缺少的一行代码
chain.doFilter(request,response);//让我们的请求继续走,如果不写,程序到此被拦截结束。
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>com.vigil.filter.CharacterEncodingFilterfilter-class>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/textFilter/*url-pattern>
filter-mapping>
//原理:统计网站在线人数:统计session
public class OnlineCountListener implements HttpSessionListener {
//创建session监听
//一旦创建Session就会触发一次这个事件
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if(onlineCount == null) {
onlineCount = new Integer(1);
} else {
onlineCount++;
}
ctx.setAttribute("OnlineCount",onlineCount);
}
//销毁session监听
//一旦销毁Session就会触发一次这个事件
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if(onlineCount == null) {
onlineCount = new Integer(0);
} else {
onlineCount--;
}
ctx.setAttribute("OnlineCount",onlineCount);
}
}
<!--注册监听器-->
<listener>
<listener-class>com.vigil.listener.OnlineCountListener</listener-class>
</listener>
(监听器:GUI编程中常用)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login</title>
</head>
<body>
<h1>登录</h1>
<form action="/servlet/LoginSerevlet" method="post">
<input type="text" name="username">
<input type="submit">
</form>
</body>
</html>
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获得前端数据
String username = (String) req.getParameter("username");
if("admin".equals(username)) {
//登陆成功
req.getSession().setAttribute("USER_NAME",username);
System.out.println(username + "=username");
System.out.println("getUSER_NAME=" + req.getAttribute("USER_NAME"));
System.out.println("getUSER_NAME=" + req.getSession().getAttribute("USER_NAME"));
resp.sendRedirect("/sys/succeed.jsp");
} else {
//登陆失败
resp.sendRedirect("/errorname.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>error</title>
</head>
<body>
<h1>错误</h1>
<h3>无权限</h3>
<p><a href="login.jsp">返回登录页面</a></p>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--<%--%> 页面实现过滤器功能的jsp脚本片段
<%-- Object user_name = request.getSession().getAttribute("USER_NAME");--%>
<%-- if(user_name == null) {
--%>
<%-- response.sendRedirect("/login.jsp");--%>
<%-- }--%>
<%--%>--%>
<h1> 主页</h1>
<p><a href="/servlet/LogoutSerevlet">注销</a></p>
</body>
</html>
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_name = req.getSession().getAttribute("USER_NAME");
System.out.println("getUSER_NAME=" + user_name);
System.out.println("getUSER_NAME=" + req.getAttribute("USER_NAME"));
if(user_name != null) {
req.getSession().removeAttribute("USER_NAME");
resp.sendRedirect("/login.jsp");
} else {
resp.sendRedirect("/errorname.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//ServletRequest --> HttpServletRequest
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if(req.getSession().getAttribute("USER_NAME") == null) {
resp.sendRedirect("/login.jsp");
}
chain.doFilter(req,resp);
}
public void destroy() {
}
}
<filter>
<filter-name>SysFilterfilter-name>
<filter-class>com.vigil.filter.SysFilterfilter-class>
filter>
<filter-mapping>
<filter-name>SysFilterfilter-name>
<url-pattern>/sys/*url-pattern>
filter-mapping>
需要jar包支持
实验数据库
create table users
(
id int auto_increment
primary key,
name varchar(40) null,
password varchar(40) null,
email varchar(60) null,
birthday date null
)
charset = utf8;
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
dependencies>
(3,4,5可以换成预编译格式)
public class TextJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
String utl = "jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
String username = "root";
String password = "20201123";
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、数据库,代表数据库
Connection connection = DriverManager.getConnection(utl, username, password);
//3、向数据库发送SQL的对象Statement:CRUD
Statement statement = connection.createStatement();
//4、编写SQL
String sql = "select * from users";
//5、执行查询SQL,返回一个ResultSet结果集
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()) {
System.out.println("id="+resultSet.getObject("id"));
System.out.println("name="+resultSet.getObject("name"));
System.out.println("password="+resultSet.getObject("password"));
System.out.println("email="+resultSet.getObject("email"));
System.out.println("birthday="+resultSet.getObject("birthday"));
}
//关闭连接,释放资源,!!先开的后关
resultSet.close();
statement.close();
connection.close();
}
}
public class TextJdbc2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
String utl = "jdbc:mysql://127.0.0.1:3306/jdbc?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
String username = "root";
String password = "20201123";
//1、加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2、数据库,代表数据库
Connection connection = DriverManager.getConnection(utl, username, password);
//3、编写SQL
String sql = "insert into users (id, name, password, email, birthday) VALUE (?,?,?,?,?)";
//4、预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,5);//给第一个占位符?,赋值5
preparedStatement.setString(2,"textyu");//给第一个占位符?,赋值textyu
preparedStatement.setString(3,"123456");//给第一个占位符?,赋值123456
preparedStatement.setString(4,"[email protected]");//给第一个占位符?,赋值[email protected]
preparedStatement.setString(5,"2020-11-11");//给第一个占位符?,赋值2021-1-26
//5、执行sql
int i = preparedStatement.executeUpdate();
if(i > 0) {
System.out.println("插入成功");
}
//6、关闭连接,释放资源,!!先开的后关
preparedStatement.close();
connection.close();
}
}
//关闭数据库的自动提交,自动开启事务
connection.setAutoCommit(false); //开启事务
connection.commit(); //业务完毕,提交业务
//在catch语句中,可以加上回滚操作
//不加的话,但事务程序出错,系统也会帮我们进行回滚
connection.rollback();
本质 实现了接口DataSource
有两个实现的数据库连接池
DBCP
需要的jar包:commons-dbcp-1.4、commons-pool-1.6
C3P0
需要的jar包:c3p0-0.9.5.5、mchange-java-0.2.19
配置文件为xml类型
依赖:
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
只有加了@Text注解的方法才可以不用main方法调用