1. Servlet
sun公司制定的一种用于扩展web服务器的功能的组件规范。
-
web服务器通常只能处理静态的资源(html , css , img , js…) , 为了解决一些动态的处理数据 ,就需要对 web服务器的功能进行扩展,servlet就是用于处理动态数据的组件规范。
-
组件: 符号一定规范 ,完成部分功能的软件模块。这些软件模块需要放在容器中进行运行。 比如:servlet , jsp就属于组件, tomcat就属于容器。 servlet必须放在tomcat容器中进行运行。 必须先启动tomcat, 然后才能访问到servlet , jsp.
-
容器:符号一定规范 , 能够运行组件的一种软件。 比如:tomcat …
-
servlet规范: 使用servlet的时候,自定义的类是HttpServlet的子类 ,那么就是符合servlet的规范。
2. Servlet的开发步骤
-
新建符合java web项目的工程
-
servlet 类 继承 HttpServlet
-
重写service方法
- service(HttpservletRequest request , HttpServletResponse)
- request : 请求
- response :响应
-
java web工程中的web.xml文件
- web.xml 的文件名不能修改(tomcat找web.xml)
- 将java的类 和 浏览器访问的地址做一个映射
- 浏览器没法办法直接访问java类中的方法 , 所以需要java类映射到一个浏览器能访问的url地 址。
-
打包(idea帮助完成)
- 把web项目运行需要的文件内容按指定文件结构保存。
- 部署(在idea中可以完成)
- 把打包好的web程序放到tomcat容器中,然后运行tomcat容器的时候,才能访问我们的web 程序。
-
启动容器, 然后可以通过浏览器访问访问web程序。
3. maven web项目的创建
-
选择maven项目 ,选择项目的模板为maven-archetype-webapp.
-
设置项目的名字等信息
-
设置maven的路径
4. 项目创建之后的修改
-
找到项目结构,添加java, resources目录
-
新建文件夹,设置文件夹类型
-
删除原来低版本的web.xml文件
-
增加4.0版本的web.xml
-
安装配置tomcat 服务器
java web项目运行,需要运行在支持java web项目的服务器上,常见的java web服务器: tomcat、JBoss、Resin、Jetty
-
单击右侧的add configuration , 打开配置窗口
-
选择tomcat
-
选择tomcat的路径
-
部署项目
-
修改项目的请求路径
-
项目启动成功之后,访问的url:
-
修改控制台乱码:
5. servlet & servlet的配置
- servlet
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
req.setCharacterEncoding("UTF-8");
// 设置编码方式
String name = req.getParameter("name");
String password = req.getParameter("password");
// 获取用户名与密码
BookUserDao dao = new BookUserDao();
BookUser user = dao.getUserByNameAndPassword(name,password);
PrintWriter writer = resp.getWriter();
// 输出流
String html;
if(user == null){
html = "<html><body><h2>用户名或密码错误</h2></body></html>";
}else{
html = "<html><body><h2>"+ name +",恭喜你登录成功。</h2></body></html>";
}
// 拼接html
writer.println(html);
// 输出信息
}
}
- web.xml
<servlet>
<servlet-name>atry</servlet-name>
<servlet-class>action.TryServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>atry</servlet-name>
<!--
/*:所有地址都会被匹配到
/:除了jsp和精确地址,都会被匹配到
/url:精确地址
*.xx:按后缀名进行匹配
-->
<url-pattern>/try</url-pattern>
</servlet-mapping>
-
接收前端提交的数据
- http://localhost:8080/webapp/servlet-url?key=value&k1=v1&k2=v2…
- request对象getParameter(key) , 获取请求参数
- getParameter 方法的返回值是String类型,使用的时候需要注意数据类型的转换
- 如果前端没有提交该参数, getParameter 返回值是null
- 如果前端提交的中文出现乱码, 设置编码为utf-8:request.setCharacterEncoding(“utf-8”)
-
响应结果
- 通过response对象的getWriter() 方法,得到输出流
- 通过输出流,输出字符串内容,作为响应结果
- 设置响应结果的类型 和字符编码:resp.setContentType(“text/html;charset=UTF-8”)
- text/html , 这个是浏览器能解析的html格式
- application/json , 这个是浏览器能解析的json格式 (后期在ajax中使用)
- 浏览器对不能解析的格式,就提示你下载(test/html , 就是浏览器不能解析的格式,就 提示下载。)
6. servlet的url映射方式
tomcat 优先查找servlet ,如果没有符合的servlet ,那么就找静态资源,如果也没有静态资源被找到, 就404.
-
/life : 精确地址 ,没有扩展名, 以/开始
-
/life.do: 精确地址, 有扩展名, 以 / 开始 .do , 通配符 + 扩展名, 所有以.do结尾的请求,都会被拦截, 不能以/开始。
- / , 拦截所有请求, 但不拦截jsp
- /* , 拦截所有请求
7. jsp的使用
jsp是一种运行在服务器端的页面, 它里面包含html , 嵌入一些java语言, 在服务器(tomcat)上经过 解析转换, 输出为html页面。
jsp不需要配置, 直接用它的路径和文件名进行访问。
jsp是sun公司制定的一种用于服务器动态页面的技术规范 , 也是一种组件, 依赖于tomcat进行运行。
-
servlet + html : 数据的处理和数据的显示
-
servlet + jsp: 数据处理(servlet) , 数据展示(jsp-- 嵌套java使用)
- servlet 做数据显示的时候,不方便(编写, 维护都不方便)
- jsp:让数据的处理和数据的展示进行分离
7.1 基本结构
jsp文件的扩展名:.jsp
page指令:第一行是指定页面的类型和页面的编码方式
通过jsp文件的路径,进行访问: http://localhost:8080/webemp/index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
7.2 jsp页面写Java相关内容
添加需要包,避免jsp内置对象使用的时候,不提示对应函数
7.3 jsp的运行
jsp的本质是servlet。
-
当第一个访问一个jsp页面的时候, 会将jsp文件, 对应生成一个servlet类。
-
html , js , css这种内容就用输出语句拼接。
-
其他和java相关的内容,就按java的方式转换。
7.4 jsp实例
<%@ page import="java.util.List" %>
<%@ page import="entity.Emp" %>
<%--
Created by IntelliJ IDEA.
User: yzxh
Date: 2022/9/6
Time: 17:37
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Object emps = request.getAttribute("emps");
List<Emp> list = null;
if (emps != null) {
if (emps instanceof List) {
list = (List<Emp>) emps;
}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>员工列表</title>
<style>
html,body{
padding: 0;
margin: 0;
width: 100%;
height: 100%;
min-width: 680px;
min-height: <%= 26.3*list.size() + 100 %>px;
}
body{
display: flex;
justify-content: center;
align-items: center;
}
h3{
text-align: center;
}
a{
text-decoration: none;
}
div>a{
width: 100%;
text-align: center;
display: inline-block;
}
table{
text-align: center;
}
tr td:nth-last-child(1){
width: 130px;
display: flex;
justify-content: space-evenly;
align-items: center;
}
</style>
</head>
<body>
<div>
<a href="<%=request.getContextPath()%>/jsp/addEmp.jsp">增加员工</a>
<hr>
<table border="1" cellspacing="0">
<tr>
<th>员工编号</th><th>员工姓名</th><th>工作岗位</th><th>部门经理编号</th><th>入职日期</th><th>员工工资</th><th>部门编号</th><th>操作</th>
</tr>
<%
for (Emp e : list) {
%>
<tr>
<td><%=e.getEno()%>
</td>
<td><%=e.getEname()%>
</td>
<td><%=e.getEjob()%>
</td>
<td><%=e.getEmanager()%>
</td>
<td><%=e.getEhiredate()%>
</td>
<td><%=e.getEsalary()%>
</td>
<td><%=e.getDeptno()%>
</td>
<td>
<a href="<%=request.getContextPath()%>/look.doj?eno=<%=e.getEno()%>">查看</a>
<a href="<%=request.getContextPath()%>/toUpdate.doj?eno=<%=e.getEno()%>">修改</a>
<a href="<%=request.getContextPath()%>/delete.doj?eno=<%=e.getEno()%>">删除</a>
</td>
</tr>
<% }
%>
</table>
</div>
</body>
</html>
8. 转发和重定向
- 转发
- 转发就是一个请求处理了一部分功能,然后开始另一个请求处理剩下的功能. 其本质就是一个请求
- 转发是共享request, response对象 ,因此可以把需要转发的数据保存在request对象中。
- 浏览器的地址栏地址保存不变。(显示第一个请求的地址)
req.setAttribute("emps",list);
// 添加请求参数
RequestDispatcher requestDispatcher = req.getRequestDispatcher("jsp/selectEmp.jsp");
// 获取转发的路径
requestDispatcher.forward(req,resp);
// 转发请求和响应
- 重定向
- 重定向是一个请求的功能完成了,然后开启另一个请求,做另一个功能。 本质是两个请求。(第一 个请求是我们主动发的, 第二个请求是浏览器收到302代码和重定向的url地址, 然后浏览器主动 发送的请求。)
- 重定向因为是两个不同的请求,所以是两个不同的request对象,因此不能共享数据。 浏览器地址栏的地址是显示重定向的地址。(显示第二个请求的地址)
resp.sendRedirect(req.getContextPath() + "/list.doj");
9. el表达式
jsp页面上,用于方便的获取到转发到jsp页面上的数据的一种表达式语言。
语法规则: ${变量} , ${对象.属性}
<%-- el表达式: ${reques对象中保存的key} --%>
<h1>emp:${emp}</h1>
<%-- ${emp.eno} : emp对象的属性值的获取
***** 对象.属性名, 要求,属性必须提供了正确的get方法。 (本质就是在调用get方法)
--%>
<h1>emp信息:${emp.eno} , ${emp.ename} , ${emp.esalary} </h1>
<%-- el表达式中,如果获取数据值是null, 那么就不显示内容--%>
<h1>emp1:${emp1}</h1>
<h1>list:${emps}</h1>
<h1>list中的元素:${emps[0]},${emps[1]}</h1>
<h1>age:${age}</h1>
<h1>age1:${age1}</h1>
<h1>nowtime:${nowtime}</h1>
<h1>el表达式的运算</h1>
条件运算: ${age1 > 18 }
<br> 逻辑运算: ${age1 > 18 || false}
<br> 判空: ${empty emp1}
<br> 算术运算: ${age1 + 20 }
10. jstl标签
- 导入标签库
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
- jstl标签的使用
先引入需要使用的标签库
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--taglib指令
prefix="c" , prefix 前缀 , 表示在使用的标签的前面都要加上c: ,解决命名冲突
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>jstl标签库</title>
</head>
<body>
<h1>alice:
<c:if test="${age1 >= 18 }">
成年入
</c:if>
<c:if test="${age1 < 18}">
未成年人
</c:if>
</h1>
<h1>
alice:
<c:choose>
<c:when test="${age1<6}">
儿童
</c:when>
<c:when test="${age1<18}">
青少年
</c:when>
<c:when test="${age < 36}">
青年
</c:when>
<c:otherwise>
青壮年
</c:otherwise>
</c:choose>
</h1>
<table border="1">
<tr><th>员工编号</th><th>员工名字</th><th>员工的雇佣日期</th></tr>
<c:if test="${empty emps}">
<tr><td colspan="3">当前没有员工</td></tr>
</c:if>
<c:forEach items="${emps}" var="e">
<tr>
<td>${e.eno}</td>
<td>${e.ename}</td>
<td>${e.ehiredate}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
11. cookie和session的使用
11.1 cookie的使用
-
cookie: 用于保存客户端的状态的计数。 当我们有多次请求的时候,这个多次请求被看做一个整 体,这个整体中有些数据需要保存的时候,可以使用cookie,把数据保存在浏览器中。
-
cookie使用的方式:
- 服务器端代码中,创建cookie对象,在response中添加cookie
- 客户端访问服务器的时候,会将把当前访问路径有关的cookie发送到服务器端
- 服务器端可以在request中获取到cookie数据,然后对这些数据进行使用
- 浏览器可以设置禁用cookie,或者用户可以删除cookie数据,用户可以查看到cookie数据, 所以重要数据不能直接保存在cookie中。
- cookie中存储的是string , 并且存储的数据大小也有限。
- cookie 可以设置有效期,过期之后,cookie会被浏览器清除掉
11.2 session的使用
- 状态管理
- cookie : 客户端状态管理的技术
- session:服务器端状态管理技术
- session中保存数据
- getSession(): 规则就是如果有就根据sessionid获取session对象,如果没有就直接创建一个 session对象。
- getSession(boolean) : true, 同getSession()功能, false , 如果找不到session对象,就返回null.
11.3 cookie和session的实例
package action;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
登录的时候,把用户的用户名和密码保存到浏览器的cookie中
*/
resp.setContentType("text/html;charset=UTF-8");
// 避免浏览器显示中文为乱码
resp.setCharacterEncoding("UTF-8");
// 避免接收的参数中包含中文时出现乱码
String name = req.getParameter("name");
String password = req.getParameter("password");
String save = req.getParameter("save");
// 获取参数
if("tom".equals(name) && "123".equals(password)){
HttpSession session = req.getSession();
// 获取session对象
session.setAttribute("loginname",name);
// 把数据保存在session对象中
session.setMaxInactiveInterval(30*60);
// 设置session的有效期(单位:秒),默认有效期为30分钟
Object loginname = session.getAttribute("loginname");
// 获取session中的数据,返回值是Object
System.out.println(loginname + "----loginname----");
String id = session.getId();
System.out.println(id +"------id------");
// session.removeAttribute("loginname");
// 删除session中的数据
if("1".equals(save)){
Cookie cookie = new Cookie("name",name);
cookie.setMaxAge(30*60);
Cookie cookie1 = new Cookie("password",password);
cookie1.setMaxAge(30*60);
Cookie cookie2 = new Cookie("save",password);
cookie2.setMaxAge(30*60);
resp.addCookie(cookie);
resp.addCookie(cookie1);
resp.addCookie(cookie2);
// 添加用户名和密码的cookie
}else{
Cookie[] cookies = req.getCookies();
for (Cookie c : cookies) {
if(c.getName().equals("name") || c.getName().equals("password")){
c.setMaxAge(0);
resp.addCookie(c);
}
}
// 删除用户名和密码的cookie
}
resp.getWriter().println("登录成功");
}else{
Cookie[] cookies = req.getCookies();
for (Cookie c : cookies) {
if(c.getName().equals("name") || c.getName().equals("password")){
c.setMaxAge(0);
resp.addCookie(c);
}
}
// 删除用户名和密码的cookie
resp.sendRedirect(req.getContextPath() + "/login.jsp");
// 重定向到login.jsp
}
// 判断用户的用户名和密码是否正确
// 如果正确,则显示登录成功,并根据实际情况决定是否添加cookie,
// 如果不正确,返回登录界面
}
}
12. 过滤器与监听器
12.1 过滤器
过滤器类型: 过滤器是sun提供一个组件, 需要依赖于tomcat容器运行。
过滤器的执行过程: 访问请求的时候,先根据过滤器的配置,符号过滤器路径的请求,则先进入到过滤器中执行,执行结束之后,再根据情况,看是否需要进入到servlet中。
- 过滤器代码
package action;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LoginFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String requestURI = request.getRequestURI();
if(requestURI.contains("login")){
chain.doFilter(request,response);
return ;
}
// login这个地址,单独处理,不需要判断session
HttpSession session = request.getSession();
Object login = session.getAttribute("loginname");
if(login != null){
// 调用下一个过滤器的doFilter方法,如果没有下一个过滤器,就调用servlet的方法
chain.doFilter(request,response);
}else{
response.sendRedirect(request.getContextPath() + "/login.jsp");
}
}
}
- 过滤器配置
<filter>
<filter-name>alf</filter-name>
<filter-class>action.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>alf</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
12.2 监听器
监听器在后台工作,可以设置需要监听的内容
// 在web.xml文件中,进行监听器的配置
public class CountListener implements ServletRequestListener {
@Override // 每次请求, 统计一次 , 统计的次数保存起来。
public void requestInitialized(ServletRequestEvent sre) {
ServletContext servletContext = sre.getServletContext();
// *** request , session , servletContext 都有setAttribute/getAttribute 方法
// 有效期: request , 每次请求是一个单的的request对象,请求结束 ,request对象就无效。
// seesion , 每次会话期间,都是同一个session对象, 会话结束,session对象就无效。
// servletContext(appliction) , 程序启动(tomcat启动),到程序关闭期间有效(tomcat关闭), 程序关闭,servletContext对象就无效了。
//servletContext.setAttribute("count" , 1);
//servletContext.setAttribute("count");
// ** 第一次请求和其他次
Object total = servletContext.getAttribute("total");
if(total==null){
servletContext.setAttribute("total" , 1);
System.out.println("1次" );
}else{
int num = (int)total + 1;
servletContext.setAttribute("total" , num );
System.out.println(num +"次");
}
}
}
- 监听器的配置
<listener>
<listener-class>action.CountListener</listener-class>
</listener>
13. jsp的内置对象
-
request : 请求
-
session : 会话
-
out : 输出语句
-
response : 响应结果
-
page : 类似于this
-
pageContext : 有效范围只在当前的jsp页面上。
-
application: ServletContext
-
config : servlet的数据
-
exception: 异常
14. java web 作用域
-
pageContext :只在当前页面有效
-
request : 请求期间有效
-
session: 会话期间有效
-
application : 程序运行期间有效
-
作用域小的数据,优先被获取到
-
pageContext > request > session > application
15. ajax的使用
ajax: 异步请求, 网页的局部更新
使用jquery的ajax 函数,实现异步请求的发送,获取到数据之后,使用jquery 将数据渲染到网页上。
- 前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>爱好</title>
</head>
<body>
<h1>请选择你的爱好:</h1>
<div>
<form>
<label>名字:</label>
<input type="text" name="name"><br>
<label>爱好</label>
<input type="checkbox" name="hobby" value="看电影">看电影
<input type="checkbox" name="hobby" value="打游戏">打游戏
<input type="checkbox" name="hobby" value="看书">看书
<input type="checkbox" name="hobby" value="跑步">跑步
<input type="checkbox" name="hobby" value="葛优躺">葛优躺
</form>
<button>发送</button>
</div>
<script src="js/jquery-3.4.1.js"></script>
<script>
// 发请求
$("button").click(function (){
// ajax函数,参数是json格式
// 请求参数,请求的url,请求的方式
// 期待的响应结果格式,请求成功后,得到响应结果的处理
let data = $("form").serialize();
//key=value&key=value
console.log(data);
$.ajax({
url: "hobby", // 请求url
data: data, // 请求参数
type: "get", //请求方式
dataType: "json", // 期待的响应结果格式
success: function (res){
if(res.success){
alert("成功")
}else{
alert("失败")
}
}
// 请求成功后,得到响应结果的处理
})
})
</script>
</body>
</html>
- 后端代码
@WebServlet("/hobby")
public class HobbyServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String[] hobbies = req.getParameterValues("hobby");
// 获取参数
System.out.println(name + "------" + Arrays.toString(hobbies));
// 数据操作
resp.setContentType("application/json;charset=utf-8");
// application/json表示响应结果是json格式
resp.getWriter().println("{\"success\":true}");
// 响应结果:json格式的结果{key:value,key1:value1}
}
}
}
// 请求成功后,得到响应结果的处理
})
})
</script>
</body>
</html>
- 后端代码
@WebServlet("/hobby")
public class HobbyServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String[] hobbies = req.getParameterValues("hobby");
// 获取参数
System.out.println(name + "------" + Arrays.toString(hobbies));
// 数据操作
resp.setContentType("application/json;charset=utf-8");
// application/json表示响应结果是json格式
resp.getWriter().println("{\"success\":true}");
// 响应结果:json格式的结果{key:value,key1:value1}
}
}