目录
1.Maven
1.1在IDEA中使用Maven
- 启动IDEA
- 创建一个MavenWeb项目






- 等待项目初始化完毕


-
观察maven仓库中多了什么东西?
-
IDEA中的Maven设置
注意:IDEA项目创建成功后,看一眼maven的配置
1.2 创建一个普通的maven项目



这个只有在web应用下才会有:

1.3 在IDEA中标记文件夹功能




1.4 在IDEA中配置Tomcat



解决警告问题
必须要的配置:为什么会有这个问题:我们访问一个网站,需要指定一个文件夹的名字;




1.5 pom文件
pom.xml是Maven的核心配置文件

2.Servlet
2.1 servlet简介
-
Servlet就是sun公司开发动态web的一门技术
-
Sun在这些API中提供一个接口叫做:Servlet, 如果你想开发一个servlet程序,只需要完成两个小步骤:
1. 编写一个类,实现servlet接口。 2. 把开发好的java类部署到web服务器中。
把实现了servlet接口的java程序叫做: Servlet
2.2 HelloServlet
Servlet接口Sun公司有两个默认的实现类: HttpServlet,GenericServlet
-
构建一个普通的Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立module,这个空工程就是maven的主工程。
-
关于Maven父子工程的理解:
父项目中会有
<modules>
<module>servlet</module>
</modules>
子目录中会有
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.kuang</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的java子项目可以直接使用
2.3 Maven环境优化
1.修改web.xml为最新的
2.将Maven的结构搭建完整
2.4 编写一个Servlet程序
1.编写一个普通类
2. 实现servlet接口,这里我们直接继承HttpServlet
package com.kuang.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//
PrintWriter writer = resp.getWriter();
writer.print("hello servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
2.5 编写Servlet的映射
为什么需要映射: 我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务器中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径;
<!--注册Servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
2.6 配置Tomcat
注意:配置项目发布的路径就可以了
2.7 启动测试, OK!
3. Servlet运行原理
servlet由web服务器调用,web服务器在收到浏览器请求之后,会:


4 . Mapping 问题
- 一个Servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定多个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello4</url-pattern>
</servlet-mapping>
- 一个Servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
- 默认请求路径
<!-- 默认路径 -->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*<url-pattern>
</servlet-mapping>
- 指定一些后缀或者前缀等等…
<!-- 可以自定义后缀实现请求映射
注意点: *前面不能加项目映射的路径
hello/sajdlkajda.qinqiang
-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.qinqiang</url-pattern>
<servlet-mapping>
-
优先级问题
指定了固有的映射路径优先级最高(精确匹配),如果找不到就会走默认的处理请求;
5、ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用; (这个对象在整个应用程序的生命周期内保持不变。每个Web应用程序都有一个唯一的 ServletContext 对象,可以通过 Servlet API 中的 getServletContext() 方法来访问)
5.1 共享数据
我在这个servlet中保存的数据,可以在另外一个servlet中拿到;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("hello");
//this.getInitParameter() : 初始化参数
//this.getServletConfig() : Servlet配置
//this.getServletContext() : Servlet上下文
ServletContext context = this.getServletContext();
String username = "秦疆";
context.setAttribute("username",username); //将一个数据保存在了ServletContext中,名字为:username,值为“”
}
}
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
//解决乱码问题
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().print("名字" + username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.kuang.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
测试访问结果;
5.2 获取初始化参数
- 设置参数
<!--配置一些web应用初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
</context-param>
- 使用ServletContext对象获取初始化参数值
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
- 在web.xml配置中改servlet
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
5.3 请求转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo04");
// RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");
// requestDispatcher.forward(req, resp);
context.getRequestDispatcher("/gp").forward(req, resp);
}

5.4 读取资源文件
Properties类
- 在java目录下新建properties
- 在resources目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath:
思路: 需要一个文件流
username=root
password=12345
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties properties = new Properties();
properties.load(is);
String user = properties.getProperty("username");
String pwd = properties.getProperty("password");
resp.getWriter().print(user +":" + pwd);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
<servlet>
<servlet-name>sd5</servlet-name>
<servlet-class>com.kuang.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sd5</servlet-name>
<url-pattern>/sd5</url-pattern>
</servlet-mapping>
访问测试即OK;
6 . HtttpServletResponse
web服务器收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse对象;
-
如果要获取客户端请求过来的参数:找HttpServletRequest;
HttpServletRequest是ServletRequest的子接口,它提供了用于处理HTTP请求的方法和属性,包括访问请求参数、请求头、会话信息等。在JSP中,request对象可以直接使用,而且通常用于从客户端接收数据、处理表单提交等HTTP相关的任务。所以,request对象提供了更多的HTTP请求相关功能,而不仅仅是ServletRequest的通用功能。 -
如果要给客户端响应一些信息:找HttpServletResponse;
HttpServletResponse是ServletResponse的子接口,它提供了用于处理HTTP响应的方法和属性,包括设置响应的内容类型、响应头、状态码等。在JSP中,你可以使用response对象来向客户端发送HTTP响应,包括HTML内容、重定向、设置响应头等操作。所以,response对象提供了更多与HTTP响应相关的功能,而不仅仅是ServletResponse的通用功能。
6.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 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);
响应的状态码
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;
6.2 常见应用
1.向浏览器输出消息
2.下载文件
1.要获取下载文件的路径
2.下载的文件名是啥?
3.设置想办法让浏览器能够支持下载我们需要的东西
4.获取下载文件的输入流
5.创建缓冲区
6.获取OutputStream对象
7.将FileOutputStream流写入到buffer缓冲区
8.使用OutputStream将缓冲区中的数据输出到客户端!
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.要获取下载文件的路径
String realPath = " D:\\CodeWarehouse\\maven_code\\javaweb-02-servlet\\response\\target\\classes\\1.jpg";
System.out.println("获取到的路径为:" + realPath);
//2.下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
System.out.println(fileName);
//3.设置让浏览器能够支持(Content-disposition)下载我们需要的东西
resp.setHeader("Content-disposition","attachment;filename"+fileName);
//4.获取下载文件的输入流
//5.创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
//6.获取OutputStream对象
//ServletOutputStream类提供一个输出流用于向客户端发送二进制数据
ServletOutputStream out = resp.getOutputStream();
FileInputStream in = new FileInputStream(realPath);
//7.将FileOutputStream流写入到buffer缓冲区
while ((len = in.read(buffer)) > 0){
out.write(buffer, 0, len);
}
//8.
in.close();
out.close();
}
3.实现重定向

一个web资源B收到客户端A的请求后,他会通知客户端A去访问另一个web资源C,这个过程叫重定向。
常见场景:
- 用户登录
void sendRedirect(String var1) throws IOException;
面试题:请求转发和重定向的区别:
相同点:
- 页面都会实现跳转
不同点:
- 请求转发的时候,url不会产生变化 307
- 重定向的时候,url地址栏会发生变化; 302
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html lang = "en">
<head>
<meta charset=UTF-8">
</head>
<body>
<form action="${pageContext.request.contextPath}/login" method="get">
用户名: <input type="text" name="username"> <br>
密码: <input type="password" name="password"> <br>
<input type="submit">
</form>
</body>
</html>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
//重定向时候一定要注意路径问题
resp.sendRedirect("/success.jsp");
System.out.println(username + ": " + password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Success</h2>
</body>
</html>
7.HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息会被封装到HttpServletRequest, 通过这个HttpServletRequest的方法,获得客户端的所有信息;
注:HttpServletRequest的对象就是JSP的九大内置对象中的request。


7.1 获取前端传递的参数

重点是第一个(返回类型为字符串)和第四个(返回类型为字符数组)。
@Override
protected void doPost(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("hobbys"); //使用的是方法四
System.out.println("=============================================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys ));
System.out.println("=============================================");
//通过请求转发
req.getRequestDispatcher("/success.jsp").forward(req, resp);
}
7.2 请求转发
8 . Cookie、Session
8.1 会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话。
有状态会话:
你能怎么证明你是南师大的学生?
你 南师大
- 校园卡 南师大给你发放的校园卡
- 学校教务系统登记 南师大的教务系统数据库中记录有你的信息
一个网站,怎么证明你来过?
客户端 服务器
1.服务端给客户端一个信件,客户端下次访问服务器带上信件就可以了: cookie
2.服务端登记你来过了,下次你来的时候我来匹配你;session
8.2 保存会话的两种技术
cookie
- ** **客户端技术(响应、请求)
session
- 服务器技术,利用这个技术,可以保存用户的会话信息。 我们可以把信息或者数据放在Session中!
常见技术:网站登录后,你下次不用再登录了,第二次访问直接就登录上了!
8.3 Cookie

- 从请求中拿到cookie信息。
- 服务器响应给客户端cookie。
Cookie[] cookies = req.getCookies(); //获得cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获取cookie中的value
new Cookie("lastLoginTime", System.currentTimeMills()+""); //新建一个cookie
cookie.setMaxAge(24 * 60 * 60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
cookie一般保存在本地的用户目录下 appdata;
一个网站cookie是否存在上限?
- 一个cookie只能保存一个信息;
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
- Cookie大小有限制4kb;
- 300个cookie浏览器上限。
如何删除cookie?
- 不设置有效期,关闭浏览器,自动失效;
- 设置有效期时间为0;
问题:Cookie是在服务端产生并发送(响应)给客户端(浏览器)的,那么为什么getCookie的操作是HttpServletRequest的对象完成的,而不是由HttpServletResponse的对象完成的?
答:HttpServletRequest对象代表从客户端(浏览器)发送到服务器的HTTP请求,它包含了请求的信息,例如请求的URL、请求的参数、请求的头部等等。当客户端发送HTTP请求时,浏览器会在请求头中附带之前保存的Cookie信息,这些Cookie会通过HttpServletRequest对象的方法来获取。
一旦Cookie被发送到客户端(浏览器),之后的请求都会自动带上该Cookie信息。当客户端发送新的HTTP请求时,浏览器会自动在请求头中带上之前保存的Cookie,这不需要开发者手动干预。
因此,HttpServletRequest对象提供了方法来获取客户端发送的Cookie信息,例如getCookies()方法,这样开发者就可以从中获取客户端浏览器携带的Cookie信息,并做相应的处理。
相比之下,HttpServletResponse对象主要用于向客户端(浏览器)发送HTTP响应。开发者可以使用HttpServletResponse对象设置响应头、响应内容以及发送Cookie等。
总结起来,获取Cookie的操作在HttpServletRequest对象完成是因为Cookie是由客户端发送到服务器的,而获取Cookie就是从客户端请求中获取信息。而设置Cookie的操作通常是通过HttpServletResponse对象来完成,因为要把Cookie发送给客户端浏览器保存。
package com.kuang.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
//保存用户上一次访问的时间
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器告诉你你来的时间,把这个时间封装成为一个信件, 你下次访问的时候带来,服务器就知道你来过了
//解决中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter(); //PrintWriter是个打印流,属于字符输出流
Cookie[] cookies = req.getCookies(); //返回的是数值,说明Cookie可能存在多个
//判断Cookie是否存在
if(cookies != null){
//如果存在怎么办?
out.write("你上一次访问的时间是:");
for (int i = 0; i < cookies.length ; i++) {
Cookie cookie = cookies[i];
//获取cookie的名字
if (cookie.getName().equals("lastLoginTime")){
//获取cookie中的值
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime); //创建指定毫秒数的Date对象
out.write(date.toLocaleString());
}
}
}else{
out.write("这是您第一次访问本站");
}
//服务器给客户端响应一个cookie;
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
8.4 Session(重点)

什么是Session?
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就存在;
- 用户登录之后,整个网站它都可以访问! —>保存用户的信息;保存购物车的信息…
Session和Cookie的区别:

Session和cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到用户独占的Session中,服务端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器自动创建(而不用我们创建)。
使用场景:
- 保存一个登录用户的信息;
- 购物车信息;
- 在整个网站中经常会使用的数据,我们将它保存在session中。
package com.kuang.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class SessionDemo03 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取Session
HttpSession session = req.getSession();
session.removeAttribute("name"); //从session删除指定名称的绑定对象
session.invalidate(); //这里注销后sessionId就没了,但是它会立马生成一个新的。
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
会话自动过期: web.xml配置
<!--设置Session默认的失效时间-->
<session-config>
<!--15分钟后Session自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
销毁session,removeAttribute()和invalidate()的区别

疑问?


问题1: 为什么cookie需要生成,而session不用生成就存在了?
Cookie和Session都是在Web开发中用来管理用户状态的技术,但它们的工作原理略有不同。
Cookie: Cookie是存储在用户浏览器中的小文本文件,由服务器通过HTTP响应头发送给浏览器,然后浏览器将其保存下来。服务器可以在响应中设置一个或多个Cookie,这些Cookie可以包含一些数据,比如用户的身份信息、偏好设置等。当用户再次访问同一个网站时,浏览器会通过HTTP请求头将之前保存的Cookie发送回服务器。这样服务器就可以根据Cookie中的信息识别用户,并根据需要进行响应。
Session: Session是服务器端的一种机制,用于在服务器上存储用户状态信息。当用户第一次访问网站时,服务器会为该用户创建一个唯一的Session ID,并将相关的用户信息存储在服务器的内存或数据库中。然后,服务器会将这个Session ID 发送给浏览器,通常是通过Cookie的形式。随后,用户每次请求都会携带这个Session ID。服务器根据Session ID 来查找存储在服务器上的用户信息,从而实现用户状态的管理。
所以,虽然Session不需要显式地生成,但实际上服务器会在用户第一次访问时自动创建Session,并将Session ID 传递给客户端,从而实现后续的状态管理。而Cookie是用来存储在客户端的数据,需要服务器主动设置并发送给浏览器。两者在实现用户状态管理时都起到了重要的作用,但机制略有不同。
问题2:cookie是由谁创建的,session又是怎么来的呢?

tip:Servlet和HTTP请求之间的关系是,Servlet是用来处理HTTP请求的,它们紧密联系,使得服务器能够根据客户端请求执行相应的业务逻辑。
9 . JSP
9.1 什么是JSP
Java Server Pages : Java服务端页面,也和Servlet一样,用于动态Web技术!
最大的特点:
-
写JSP就像在写HTML
-
区别:
HTML只给用户提供静态的数据 JSP页面中可以嵌套Java代码,为用户提供动态数据;
9.2 JSP原理
思路:JSP到底怎么执行的!
-
代码层面没有任何问题
-
服务器内部工作
tomcat中有一个work目录; IDEA中使用Tomcat的话,会在IDEA的tomcat中生成一个work目录(IDEA的空间在C盘)
在本机上的地址:
C:\Users\14205\.IntelliJIdea2017.2\system\tomcat\Unnamed_javaweb-session-cookie_2\
work\Catalina\localhost\ROOT\org\apache\jsp
发现页面转变成了java程序!

浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet!
JSP最终也会被替换成一个java类!
JSP本质上就是一个Servlet!
//初始化
public void _jspInit() {
}
//
public void _jspDestroy() {
}
//JSPService
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse 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; //config
javax.servlet.jsp.JspWriter out = null; //out
final java.lang.Object page = this; //page: 当前页
HttpServletRequest request //请求
HttpServletResponse response //响应
exception
- 输出页面前增加的代码
response.setContentType("text/html"); //设置响应的页面类型
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页面中直接使用!

在JSP页面中;
只要是JAVA代码就会原封不动的输出;
如果是HTML代码,就会被转换为:
out.write("<html>\r\n);
这样的格式,输出到前端!
附:index_jsp.java代码如下:
// index_jsp.java
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.0.33
* Generated at: 2023-08-11 10:53:14 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
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;
out.write("<html>\n");
out.write("<body>\n");
out.write("<h2>Hello World!</h2>\n");
out.write("</body>\n");
out.write("</html>\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
9.3 JSP基础语法
任何语言都有自己的语法,java中有,JSP作为java技术的一种应用,它拥有一些自己扩充的语法(了解,知道即可!),java所有语法都支持!
JSP表达式
<%--JSP表达式
作用: 用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%= new java.util.Date()%>
jsp脚本片段
<%--jsp脚本片段--%>
<%
int sum = 0;
for(int i = 0; i < 100; i++){
sum += i;
}
out.println("<h1>sum=" + sum + "<h1>");
%>
脚本片段的再实现
<%
int x = 10;
out.println(x);
%>
<p>这是一个JSP文档</p>
<%
int y = 20;
out.println(y);
%>
<%--在代码中嵌入HTML元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1>Hello, World ! <%= i %></h1>
<%
}
%>
JSP声明
<%!
static{
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void kuang(){
System.out.println("进入了方法kuang!");
}
%>
JSP声明:会被编译到JSP生成Java的类中!
其他的,就会被生成到_jspService方法中!
在JSP中,嵌入java代码即可!
<%%> : 中写脚本程序(我的理解就是java代码)
<%=%> : 中写表达式(变量或表达式)
<%!%> : JSP声明的语法格式
<%--注释-->
JSP的注释,不会在客户端显示; 但HTML的注释会!
补充:不使用模板方式创建web项目eg:





9.4 JSP指令
<%@page args...%>
<%@include file=""%>
<%-- "/"代表当前项目(即web项目,web这个文件夹)--%>
<%--@include会将两个页面合二为一--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>
<hr>
<%--jsp标签--%>
<%--jsp:include: 拼接页面,本质上还是三个 --%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>
9.5 九大内置对象
- PageContext : 页面上下文
- Request : 请求
- Response : 响应
- Session : 会话
- Application [ServletContext] : 存东西
- config [ServletConfig]
- page : 当前页
- out :
- exception :
pageContext.setAttribute("name1", "凯旋①号"); //保存的数据只在一个页面中有效
request.setAttribute("name2", "凯旋②号"); //保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3", "凯旋③号"); //保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4", "凯旋④号"); //保存的数据在服务器中有效,从打开服务器到关闭服务器
request : 客户端向服务器发送请求,产生的数据,用户看完就没用了,比如: 新闻, 用户看完没用的!
session: 客户端向服务器发送请求,产生的数据,用户用完一会儿还有用,比如: 购物车;
application: 客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如: 聊天数据;
9.6 JSP标签、JSTL标签、EL表达式
<!--jstl标签库-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库-->
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表达式作用:
- 获取数据
- 执行运算
- 获取web开发的常用对象
JSP标签
<%--jsp:include--%>
<%--http://localhost:8080/jsptag.jsp?name=kuangshen&age=12
--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="kuangshen"></jsp:param>
<jsp:param name="age" value="3"></jsp:param>
</jsp:forward>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义了许多标签,可以供我们使用,标签的功能和java代码一样!
核心标签(掌握部分)

JSTL标签库使用步骤:
- 引入对用的taglib
- 使用其中的方法
- 在Tomcat中也需要引入jstl的包,否则会报jstl解析错误
C:\Users\14205.m2\repository\javax\servlet\jsp\jstl\jstl-api\1.2
coreif、 corewhen、 coreforeach的例子如下:
coreif:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入JSTL核心标签库,我们才能使用JSTL标签core--%>
<%@taglib prefix="c" uri = "http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>if测试</h4>
<hr>
<form action="coreif.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
<%--判断如果提交的用户名是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin"> <br/>
<c:out value="管理员欢迎您!"/>
</c:if>
</form>
<%--这是个自闭和标签--%>
<c:out value="${isAdmin}"/>
</body>
</html>
corewhen:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--定义一个变量score,值为85--%>
<c:set var="score" value="85"/>
<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:choose>
</body>
</html>
coreforeach:
<%@ page import="java.util.ArrayList" %>
<%--在 jsp 标签库中使用 taglib 指令引入标签库--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
var: 每一次遍历出来的变量
items: 要遍历的对象
begin: 哪里开始
end: 到哪里
step: 步长
--%>
<%
ArrayList<String> people = new ArrayList<>();
people.add("润泽");
people.add("大冰");
people.add("凯旋");
people.add("爱萍");
people.add("小婉");
request.setAttribute("list", people);
%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br/>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="1">
<c:out value="${people}"/> <br/>
</c:forEach>
</body>
</html>
10 . JavaBean
实体类
JavaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射 ORM;
ORM:对象映射关系
- 表——> 类
- 字段——>属性
- 元组——>对象
| id | name | age | address |
| — | — | — | — |
| 1 | 凯旋①号 | 17 | 临汾 |
| 2 | 凯旋②号 | 16 | 太原 |
| 3 | 凯旋③号 | 18 | 南京 |
class People{
private int id;
private String name;
private int age;
private String address;
}
class A{
new People(1, "凯旋①号", 17, "临汾");
new People(2, "凯旋②号", 16, "太原");
new People(3, "凯旋③号", 18, "南京");
}
11 . MVC三层架构
什么是MVC: Model View Controller 模型、视图、控制器

用户直接访问控制层,控制层就可以直接操作数据库;
servlet——> CRUD ——> 数据库
弊端: 程序十分臃肿,不利于维护
servlet的代码中: 处理请求、响应、试图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
11.2 MVC三层架构

Model:
- 业务处理: 业务逻辑(Service)
- 数据持久层: CRUD(Dao)
View:
- 展示数据
- 提供链接发起Servlet请求(a, form, img…)
Controller:
- 接收用户的请求: (req:请求参数、 Session信息)
- 交给业务层处理对应的代码
- 控制视图的跳转
登录——> 接收用户的登录请求——>处理用户的请求(获取用户登录的参数, username, password)——> 交给
业务层处理登录业务(判断用户名密码是否正确:事务)——> Dao层查询用户名和密码是否正确——> 数据库
12 . Filter
Filter:过滤器, 用来过滤网站的数据;
- 处理中文乱码
- 登录验证…

Filter开发步骤:
-
导包
-
编写过滤器
1.导包不要导错

2.实现Filter接口,重写对应的方法即可
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就已经初始化了,随时等待过滤器对象出现!
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncodingFilter初始化");
}
//chain: 链
/*
* 1.过滤器中的所有代码,在过滤特定请求的时候都会执行
* 2.必须要让过滤器继续通行
* chain.doFilter(request, response);
* */
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("CharacterEncodingFilter执行前....");
chain.doFilter(request,response); //固定的代码(让程序继续往下走的)
System.out.println("CharacterEncodingFilter执行后....");
}
//销毁:web服务器关闭的时候,过滤会销毁
public void destroy() {
System.out.println("CharacterEncodingFilter销毁");
}
}
3.在web.xml中配置Filter
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.kuang.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是/servlet的任何请求,会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.kuang</groupId>
<artifactId>javaweb-filter</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--Servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--JSP依赖-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<!--JSTL表达式的依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--mysql驱动-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
</project>
13、监听器
实现一个监听器的接口; (有n种)
1.编写一个监听器
实现监听器的接口…
public class OnlineCountListener implements HttpSessionListener {
//创建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{
int count = onlineCount.intValue();
onlineCount = new Integer(count + 1);
}
ctx.setAttribute("OnlineCount", onlineCount);
}
//销毁session监听
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
}
}
- web.xml中注册监听器
<!--注册监听器-->
<listener>
<listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
3.看情况是否使用!
14、过滤器、监听器常见应用

SMBMS

数据库

项目如何搭建?
考虑使不使用Maven ? 找依赖 : 导jar包
项目搭建:
-
搭建一个maven web项目
-
配置tomcat
-
测试项目是否能够跑起来
-
导入项目中会遇到的jar包
servlet、jsp、mysql驱动,jstl、standard
-
创建包结构;

-
编写实体类;
ORM映射: 表—类 映射




-
编写基础公共类
1. 数据库配置文件(resources目录下写文件就可以了)
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8
username=root
password=672836466
2.编写数据库的公共类
//BaseDao文件
package com.kuang.dao;
import com.mysql.fabric.xmlrpc.base.Param;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
//操作数据库的公共类
public class BaseDao {
private static String driver;
private static String url;
private static String username;
private static String password;
//静态代码块,类加载的时候就初始化了
static {
Properties properties = new Properties();
//通过类加载器读取对应的资源
InputStream is = BaseDao.class.getClassLoader().getResourceAsStream("db.properties");
try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
}
//获取数据库的连接
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
//编写查询公共方法
public static ResultSet execute(Connection connection, String sql, Object[] param, ResultSet resultSet,PreparedStatement preparedStatement ) throws SQLException {
preparedStatement = connection.prepareStatement(sql); //存在的异常:sql语句可能是无效的
for (int i = 0; i < param.length; i++) {
//setObject, 占位符从1开始, 但是我们的数组是从0开始的!
preparedStatement.setObject(i+1, param[i]);
}
resultSet = preparedStatement.executeQuery();
return resultSet;
}
//编写增删改公共方法
public static int execute(Connection connection, String sql, Object[] param, PreparedStatement preparedStatement) throws SQLException {
preparedStatement = connection.prepareStatement(sql); //存在的异常:sql语句可能是无效的
for (int i = 0; i < param.length; i++) {
//setObject, 占位符从1开始, 但是我们的数组是从0开始的!
preparedStatement.setObject(i+1, param[i]);
}
int updateRows = preparedStatement.executeUpdate();
return updateRows;
}
//释放资源
public static boolean closeResource(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
boolean flag = true;
if (resultSet != null){
try {
resultSet.close();
resultSet = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (preparedStatement != null){
try {
preparedStatement.close();
preparedStatement = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (connection != null){
try {
connection.close();
connection = null;
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
return flag;
}
}
3.编写字符编码过滤器
- 导入静态资源


登录功能实现

1.编写前端页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>系统登录-超市订单管理系统</title>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/statics/css/style.css">
<script>
</script>
</head>
<body class="login_bg">
<section class="loginBox">
<header class="loginHeader">
<h1>超市订单管理系统</h1>
</header>
<section class="loginCont">
<form class="loginForm" action="${pageContext.request.contextPath}/login.do" name="actionForm" id="actionForm" method="post">
<div class="info">${error}</div>
<div class="inputbox">
<label>用户名:</label>
<input type="text" class="input-text" id="userCode" name="userCode" placeholder="请输入用户名" required/>
</div>
<div class="inputbox">
<label>密码:</label>
<input type="password" id="userPassword" name="userPassword" placeholder="请输入密码" required/>
</div>
<div class="subBtn">
<input type="submit" value="登录"/>
<input type="reset" value="重置"/>
</div>
</form>
</section>
</section>
</body>
</html>
2.设置首页
<!--设置欢迎页面-->
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
3.编写Dao层登录用户登录的接口
public interface UserDao{
//得到要登录的用户
public User getLoginUser(Connection connection, String userCode) throws SQLException;
}
4.编写Dao层接口的实现类
public class UserDaoImpl implements UserDao{
public User getLoginUser(Connection connection, String userCode) throws SQLException{
PreparedStatement pstm = null;
ResultSet rs = null;
User user = new User();
if(connection != null){
String sql = "select * from smbms_user where userCode=?";
//创建一个对象数组
Object[] params = {userCode};
rs = BaseDao.execute(connection, sql, params, rs, pstm); //到这一步已经拿到结果集了,即已经执行了sql语句了。
//处理得到的结果集
if(rs.next()){
user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setUserPassword(rs.getString("userPassword"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setAddress(rs.getString("address"));
user.setUserRole(rs.getInt("userRole"));
user.setCreatedBy(rs.getInt("createdBy"));
user.setCreationDate(rs.getTimestamp("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getTimestamp("modifyDate"));
}
BaseDao.closeResource(null, pstm, rs); //connection可能存在业务,需要到事务层调业务的时候再去关闭。
}
return user;
}
}
- 业务层接口
public interface UserService {
//用户登录
public User login(String userCode, String password);
}
- 业务层实现
public class UserServiceImpl implements UserService{
//业务层都会调用dao层,所以我们要引入Dao层。
private UserDao userDao;
public UserServiceImpl(){
}
public User login(String userCode, String password) {
Connection connection = null;
User user = null;
try {
connection = BaseDao.getConnection();
//通过业务层调用对应的具体数据库操作
userDao.getLoginUser(connection, userCode);
} catch (SQLException e) {
e.printStackTrace();
} finally {
BaseDao.closeResource(connection, null, null);
}
return user;
}
}
7.编写Servlet
package com.kuang.servlet.user;
import com.kuang.pojo.User;
import com.kuang.service.user.UserServiceImpl;
import com.kuang.util.Constants;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet{
//Servlet: 控制层,调用业务层代码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LoginServlet--strat");
//获取用户名和密码
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
//和数据库中的密码进行对比,调用业务层;
UserServiceImpl userService = new UserServiceImpl(); //创建UserServiceImpl对象的时候(调用空参的构造方法)就
//自动创建出了一个UserDaoImpl对象名为userDao
User user = userService.login(userCode, userPassword);
if(user != null){ //查有此人,可以登录
//将用户的信息放到session中
req.getSession().setAttribute(Constants.USER_SESSION, user);
//使用重定向跳转到主页
resp.sendRedirect("jsp/frame.jsp");
}else{ //查无此人
//转发回登录页面,顺带提示它,用户名或者密码错误;
req.setAttribute("error", "用户名或者密码不正确");
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 注册servlet
<!--注册Servlet-->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.kuang.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern> //前端form表单中指定了发送到哪里
</servlet-mapping>

- 测试访问, 确保以上功能成功!
登录功能优化
注销功能:
思路:移除Session, 返回登录页面
public class LogoutServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//移除用户的Constants.USER_SESSION
req.getSession().removeAttribute(Constants.USER_SESSION);
resp.sendRedirect("/login.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--登录优化-->
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.kuang.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/logout.do</url-pattern>
</servlet-mapping>
有关session的知识点回顾:
为什么ServletRequest对象获取不到Session, 而HttpServletRequest对象可以获取到session?
答:ServletRequest是一个更通用的接口,它表示了一个Http请求。这个接口并没有直接提供获取会话的方法。(如果只使用ServetRequest, 需要将其强制转换为HttpServletRequest才能访问会话。)
ServletRequest request = request;
HttpSession session = ((HttpServletRequest) request).getSession();
两个接口之间的关系:
‘HttpServletRequest’ 继承自’ServletRequest’, 它是一个专门用于处理HTTP请求的接口。 ‘HttpServletRequest’ 直接提供了获取会话的方法,如’getSession() ', 因此可以直接通过’HttpServletRequest’对象来获取会话。
HttpServletRequest request = request;
HttpSession session = request.getSession();
JavaEE规范Servlet和jdbc的区别:

登录拦截优化
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
//首先获取session(HttpServletRequest对象才能拿到session)
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//获取器,从session中获取用户
User user = (User)request.getSession().getAttribute(Constants.USER_SESSION);
if (user == null){ //如果user为空,就说明已经被移除或者是注销了,或者未登录。
response.sendRedirect("/error.jsp");
}else{
chain.doFilter(req, resp);
}
}
@Override
public void destroy() {
}
}
<!--登录拦截优化-->
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.kuang.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>
密码修改
1.导入前端素材
<li><a href="${pageContext.request.contextPath }/jsp/pwdmodify.jsp">密码修改</a></li>
- 写项目,建议从底层往上写

- UserDao接口
public int updatePwd(Connection connection, int id, String password) throws SQLException;
- UserDao实现类
//修改当前用户密码
@Override
public int updatePwd(Connection connection, int id, String password) throws SQLException {
PreparedStatement preparedStatement = null;
int execute = 0;
if (connection != null) {
String sql = "update smbms_user set userPassword = ? where id = ?";
Object params[] = {password, id};
execute = BaseDao.execute(connection, sql, params, preparedStatement);
BaseDao.closeResource(null, preparedStatement, null);
}
return execute;
}
5.UserService接口
//根据用户ID修改密码
public boolean updatePwd(int id, String pwd);
6.UserService实现类
@Override
public boolean updatePwd(int id, String pwd) {
Connection connection = null;
boolean flag = false;
//修改密码
try {
connection = BaseDao.getConnection();
if (userDao.updatePwd(connection, id, pwd) > 0){ //此处有sql异常
flag = true;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关流
BaseDao.closeResource(connection, null, null);
}
return flag;
}
- UserServlet实现类
public class LoginServlet extends HttpServlet{
//Servlet: 控制层,调用业务层代码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LoginServlet--start");
//获取用户名和密码
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
//和数据库中的密码进行对比,调用业务层;
UserServiceImpl userService = new UserServiceImpl(); //创建UserServiceImpl对象的时候(调用空参的构造方法)就
//自动创建出了一个UserDaoImpl对象名为userDao
User user = userService.login(userCode, userPassword);
if(user != null){ //查有此人,可以登录
//将用户的信息放到session中
req.getSession().setAttribute(Constants.USER_SESSION, user);
//使用重定向跳转到主页
resp.sendRedirect("jsp/frame.jsp");
}else{ //查无此人
//转发回登录页面,顺带提示它,用户名或者密码错误;
req.setAttribute("error", "用户名或者密码不正确");
req.getRequestDispatcher("login.jsp").forward(req, resp);
}
}
7.记得实现复用(Servlet复用),需要提取出方法!
package com.kuang.servlet.user;
import com.kuang.pojo.User;
import com.kuang.service.user.UserServiceImpl;
import com.kuang.util.Constants;
import com.mysql.jdbc.StringUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if(method.equals("savepwd") && method != null ){
this.updatePwd(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
public void updatePwd(HttpServletRequest req, HttpServletResponse resp){
//从session里面拿id
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
//获取前端传递的参数:新密码,因为是做修改密码的操作,所以要拿到前端输入的新密码去替换数据库中的旧密码。
String newpassword = req.getParameter("newpassword");
boolean flag = false;
if (o != null && !StringUtils.isNullOrEmpty(newpassword)){
//调用service层
UserServiceImpl userService = new UserServiceImpl();
flag = userService.updatePwd(((User) o).getId(), newpassword);
if (flag){
req.setAttribute("message", "密码修改成功,退出请使用新密码登录");
//密码修改成功你,移除当前Session
req.getSession().removeAttribute(Constants.USER_SESSION);
}else{
req.setAttribute("message", "密码修改失败");
}
}else{
req.setAttribute("message", "新密码有问题");
}
//请求转发
try {
req.getRequestDispatcher("pwdmodify.jsp").forward(req, resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 测试
优化密码修改使用Ajax
- 阿里巴巴的fastjson
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
- 后台代码修改


2431

被折叠的 条评论
为什么被折叠?



