目录
1、Servlet
1.1、Servlet简介
-
Servlet是Sun公司开发动态web的一门技术
-
Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个步骤:
-
编写一个类吗,实现Servlet接口
-
把开发好的Java类部署到web服务器
-
实现了Servlet接口的Java程序叫做Servlet
1.2、HelloServlet
Servlet接口Sun公司有两个默认实现类:HttpsServlet,GenericServlrt
-
构建一个Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel,这个空的工程就是Maven主工程
-
关于Maven父子工程的理解:
父项目pom.xml中会有:
<modules> <module>Servlet-01</module> </modules>
子项目pom.xmi中会有:
<parent> <artifactId>javaweb-02-servlet</artifactId> <groupId>com.Jun</groupId> <version>1.0-SNAPSHOT</version> </parent
父项目中的java包子项目可以直接使用
-
Maven环境优化
-
修改web.xml为最新版本
-
将Maven的结构搭建完整
-
-
编写一个Servlet程序
-
编写一个普通类
-
实现Servlet接口,继承HttpsServlet类,
-
public class HelloServlet extends HttpServlet {
//由于get和post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter(); //响应流
writer.print("Hello, Servlet!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
-
编写Servlet的映射
为什么需要映射:我们写的是Java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要再web服务器中注册我们写的Servlet,还需要给它一个浏览器能够访问的路径。
<!--注册Servlet-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.Jun.servlet.HelloServlet</servlet-class>
</servlet>
<!-- Servlet的请求路径-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
-
配置tomcat
注意:配置项目的发布路径
-
启动测试
1.3、Servlet原理
Servlet是由Web服务器调用,web服务器在收到浏览器请求之后,会:
1.4、Mapping问题
-
一个Servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
一个Servlet可以指定多个映射路径
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping>
-
一个Servlet可以指定通用映射路径
<servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
-
指定一些后缀或者前缀(*前面不能加项目映射的路径)
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>*.jun</url-pattern>
</servlet-mapping>
-
Mapping优先级
指定固有的映射路径优先级最高,如果找不到就会走默认的处理请求
1.5、ServletContext
Web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,它代表当前的web应用
1、 共享数据
-
我在这个servlet中保存的数据,可以在另外一个servlet中拿到
HelloServlet类设置数据,存储到ServletContext:
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//this.getInitParameter() 初始化参数
//this.getServletInfo(); Servlet配置
//this.getServletContext(); Servlet上下文
ServletContext Context = this.getServletContext();
String username = "马俊"; //数据
Context.setAttribute("username",username); //将一个数据保存在ServletContext
}
}
GetServlet类获取ServletContext已存储的数据,并响应输出:
public class GetServlet extends HelloServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String)context.getAttribute("username");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html");
resp.getWriter().print("名字"+username);
}
测试步骤:
-
先运行HelloServlet在ServletContext中存储数据
-
再运行GetServlet读取ServletContext中的数据并响应输出
测试结果:
2、获取初始化参数
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306</param-value>
</context-param>
public class ServletDemo03 extends HelloServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}}
3、请求转发
请求转发工作流程:
4、读取资源文件
Properties
-
在Java目录下新建properties
-
在resources目录下新建properties
发现:都被打包到同一个路径下:classes,我们俗称这个路径为classpath
思路:需要一个文件流
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
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().print(user+":"+pwd);
}
1.6、HttpServletResponse
web服务器接收到客户端的Http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse
-
如果要获取客户端请求过来的参数:找HttpServletRequest
-
如果要给客户端响应一些信息:找HttpServletResponse
1、方法简单分类
负责向浏览器发送数据的方法:
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法:
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setBufferSize(int var1);
负责设置状态码:
2、下载文件
-
向浏览器输出消息
-
下载文件
-
要获取下载文件的路径
-
下载的文件名是啥
-
设置想办法让浏览器能够支持下载我们需要的东西
-
获取下载文件的输入流
-
创建缓冲区
-
获取outputStream对象
-
将FileoutputStream流写入到buffer缓冲区
-
使用outputStream将缓冲区中的数据输出到客户端
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String realPath = "E:\\JavaWeb Preject\\javaweb-02-servlet\\Servlet-03\\target\\classes\\1.png"; System.out.println("下载文件的路径:"+realPath); String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1); resp.setHeader("Content-disposition","attachment;filename"+fileName); resp.setContentType("png;charset=utf-8"); FileInputStream in = new FileInputStream(realPath); int len = 0; byte[] buffer = new byte[2048]; ServletOutputStream out = resp.getOutputStream(); while ((len=in.read(buffer))>0) { out.write(buffer, 0, len); } out.close(); in.close(); }
-
3、验证码功能
验证怎么来的?
-
前端实现
-
后端实现,需要用到Java的图片类,产生一张图片
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器5秒自动刷新一次
resp.setHeader("refresh","3");
//在内存中创建一个图片
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(makeNum(),0,20);
//告诉浏览器,这个请求用图片形式打开
resp.setContentType("image/jpeg");
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Paragma","no-cache");
//把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
private String makeNum(){
Random random = new Random();
String num = random.nextInt(99999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i <7-num.length() ; i++) {
sb.append("0");
}
String s = sb.toString() + num;
return num;
}
4、实现重定向
一个web资源(B)收到客户端(A)请求后,他会通知客户端(A)去访问另外一个web资源(C),这个过程叫做重定向
常见场景:
-
用户登录
void sendRedirect(String var1) throws IOException;
面试题:重定向和请求转发的区别?
相同点:
-
页面都会实现跳转
不同点:
-
请求转发的时候:url不会产生变化
-
重定向的时候:url会产生变化
1.7、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获取一些客户端请求信息
获取参数、请求转发
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobby");
System.out.println("=====================");
//后台接收乱码问题
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
System.out.println("=====================");
System.out.println(req.getContextPath());
//请求转发
resp.setCharacterEncoding("utf-8");
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
2、Cookie、Session
2.1、会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程称之为会话
有状态会话:
客户端 服务器端
-
服务器端给客户端一个信件,客户端下次访问服务端带上信件就可以 cookie
-
服务器登记你来过,下次你来的时候我匹配你 session
2.2、保存会话的两种技术
cookie
-
客户端技术(响应,请求)
session
-
服务器技术,利用这个技术,可以保存用户的会话信息
常见应用:网站登录之后,你下次不用再登录,第二次访问直接就进去了
2.3、Cookie
-
从请求中拿到cookie信息
-
服务器相应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得cookie
cookie.getName() //获得cookie中的key
cookie.getValue() //获得cookie中的value
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+""); //创建一个新的cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //相应给客户端一个cookie
cookie:一般会保存在本地用户目录下appdata
删除cookie:
-
不设置有效期,关闭浏览器,自动失效
-
设置有效期时间为0
编码解码:
URLEncoder.encode("马俊","utf-8");
URLDecoder.decode(cookie.getValue(),"utf-8");
2.4、Session(重点)
什么是Session:
-
服务器会给每一个用户(浏览器)创建一个Seesion对象
-
一个Session独占一个浏览器,只要浏览器没有关闭,这个session就存在
-
用户登录之后,整个网站都可以访问——保存用户的信息,保存购物车的信息
Session和Cookie的区别:
-
Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
-
Session把用户的数据写到用户独占的Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
-
Session对象由服务器创建
Session会话自动过期:web.xml配置
<session-config>
<!--15分钟后Session自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
3、JSP
3.1、什么是JSP
Java Server pages:Java服务器端页面,也和Servlet一样,用于动态Web开发技术!
最大的特点:
-
写JSP就像在写Html
-
区别:
-
HTML只给用户提供静态的数据
-
JSP页面中可以嵌入Java代码,为用户提供动态数据
-
3.2、JSP原理剖析
思路:JSP到底怎么样执行的!
-
代码层面就类似Html页面
-
服务器内部工作:
-
tomcat中有一个work目录
-
Idea中使用Tomcat的会在Idea的tomcat中产生一个work目录
发现页面转变成了Java程序:
-
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
JSP本质上就是一个Java类
JSP内部工作过程:
-
判断请求
-
内置一些对象
-
输出页面前增加的代码
-
内置的对象可以在JSP页面中直接使用
JSP工作实现原理:
在JSP页面中:
只要是Java代码就会被原封不动的输出
如果是HTML代码,就会被转换成;
out.write("<html>\r\n");
这样的方式在前端输出
3.3、JSP基础语法
任何语言都有自己的语法。JSP作为Java技术的一种应用,它拥有一些自己扩充的语法,Java所有语法都支持!
JSP表达式
<%--JSP表达式 作用:将程序的输出,输出到客户端--%>
<%= new java.util.Date()%>
JSP脚本片段
<%--JSP脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <=100 ; i++) {
sum+=i;
}
out.println("<h1>总数为"+sum+"</h1>");
%>
脚本片段的再实现
<%--在代码中嵌入HTML元素--%>
<%
for (int i = 0; i <5 ; i++) {
out.write("<h1>majun</h1>");
%>
<h1>Hello,world <%=i%></h1>
<%
}
%>
JSP声明
<%!
static {
System.out.println("Loading Servlet");
}
private int globalVar = 0;
public void jun(){
System.out.println("进入了方法Jun");
}
%>
JSP声明:会被编译到JSP生成的Java类中!其他的,就会被生成到jspService方法中!
JSP的注释,不会在客户端显示,HTML的在查看网页源代码时就会显示
3.4、JSP指令
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file=" "%>
<jsp:include page="/common/header.jsp"/>
include file=" ":将多个页面整合为一个页面
jsp:include:拼接页面,页面的组合数没有变化
3.5、JSP内置对象及作用域
-
PageContext
-
Request
-
Response
-
Session
-
Application
-
Config 【ServletConfig】
-
out
-
page
-
exception
pageContext.setAttribute("name1","马俊1"); //保存的数据只在一个页面中有效
request.setAttribute("name2","马俊2"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","马俊3"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","马俊4"); //保存的数据只在服务器中有效,从打开服务器到关闭服务器
3.6、JSP标签、JSTL标签、EL表达式
EL表达式:${}
-
获取数据
-
执行运算
-
获取web开发的常用对象
JSP标签:
<%--jsp:include--%>
<jsp:forward page="jsp2.jsp">
<jsp:param name="name" value="majun"/>
<jsp:param name="age" value="18"/>
</jsp:forward>
JSTL表达式:
JSTL标签库的使用就是为了弥补HTML标签的不足,它自定义许多标签,标签的功能和Java代码一样
-
核心标签
-
格式化标签
-
SQL标签
-
XML标签
JSTL标签库使用步骤:
-
引入对应的taglib
-
使用其中的方法
-
在Tomcat中也需要引入jstl的包,否则会报错:JSTL解析错误