JavaWeb
- 1.基本概念
-
- 1.1前言
- 1.2web应用程序
- 1.3、静态web
- 1.4、动态web
- 2、web服务器
-
- 2.2、web服务器
- 3、Tomcat
-
- 1、安装tomcat
- 2、Tomcat启动和配置
- 4、Http
-
- 什么是http
- 两个时代
- http请求
- 1、请求行
- 2、消息头
- http响应
- 响应体
- 响应状态码
- 5、Maven
-
- Maven项目架构管理工具
- 下载安装Maven
-
-
- 配置环境变量
- 阿里云镜像
- 本地仓库
- 在IDEA中使用Maven
- 创建一个普通的maven项目
- 在idea中配置tomcat
- pom文件
- idea操作
- 解决所遇到的问题
- 6、Servlet
-
- Servlet简介:
- HelloServlet
- Servlet原理
- ServletContext
- 获得初始化参数(ServletContext应用)
- 请求转发(ServletContext应用)
- 读取资源文件
- HttpServletResponse
-
- 简单分类
- 重定向
- HttpServletRequest
- 1.获取参数,请求转发
- 7、Cookie、Session
-
- 7.1会话
- 7.2 保存会话的两种技术
- 7.3 Cookie
- 7.4 Session(重点)
- 8、jsp
-
- 8.1、什么是jsp
- 8.2、JSP原理
- 8.3、JSP基础语法
- 8.4、JSP指令
- 8.5、9大内置对象
- 8.6 、JSP标签、JSTL标签、EL表达式
- 9、JavaBean
- 10、MVC三层架构
-
- 10.1 早年
- 10.2 MVC三层架构
- 11、Filter(重点)
- 12、监听器
- 13、过滤器、监听器常见应用
- 14、JDBC
-
- Junit单元测试
- 15、SMBMS
-
- 项目搭建
- 登录功能实现
- 登录功能优化
-
- 登录拦截优化
- 密码修改
-
- 优化密码修改Ajax
- 用户管理实现
-
- 1.获取用户数量
- 2.获取用户列表
- 3.获取角色操作
- 4.用户显示的Servlet
- 16.文件上传
-
1.基本概念
1.1前言
web开发:
- web,网页的意思
- 静态web
- html,css,
- 提供给所有人看的数据始终不会发送变化的
- 动态web
- 淘宝,几乎是所有的网站
- 提供给所有人看的数据始终会发送变化的,每个人在不同的时间,不同的地点看到的信息各不相同
- 技术栈:Servlet/JSP,ASP,PHP
在Java中,动态web资源开发的技术统称为JavaWeb
1.2web应用程序
web应用程序:可以提供浏览器访问的程序
- a.html、b.html…多个web资源,这些web资源可以被外界访问,对外界提供服务
- 你们能访问到的任何一个页面或者资源,都存在于这个世界的某一个角落的计算机上
- URL
- 这个统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat:服务器
- 一个web应用由多部分组成(静态web,动态web)
- html,css,js
- jsp,servlet
- java程序
- jar包
- 配置文件(Properties)
web应用程序编写完毕后,若想提供给外界访问,需要一个服务器统一管理
1.3、静态web
- .htm,.html,这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取
- 静态web存在的缺点
- web页面无法动态更新
- 轮播图,点击特效:伪动态
- JavaScript(实际开发中,它用得最多)
- VBscript
- 它无法和数据库交互(数据无法持久化,用户无法交互)
- web页面无法动态更新
1.4、动态web
页面会动态展示:“web的页面展示的效果应人而异"
缺点
- 假如服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布;
- 停机维护
优点:
-
web页面可以动态更新,所有用户看到的不是同一个画面
-
它可以和数据库交互(数据持久化:注册,商品信息,用户信息)
2、web服务器
ASP
- 微软:国内最早流行的
- 在HTML中嵌入了vb的脚本,ASP+COM;
- 在ASP开发中,基本一个页面
PHP
- PHP开发速度很快,功能很强大,跨平台,代码很简单(70%,wp)
- 无法承载大访问量的情况(局限性)
JSP/Servlet
B/S:浏览器和服务器
C/S:客户端和服务器
- sun公司主推的B/S架构
- 基于Java语言的
- 可以承载三高问题带来的影响(高可用,高性能,高并发)
- 语法像ASP,ASP–>JSP,加强市场强度
2.2、web服务器
服务器是一种被动的操作,用来处理用户的一些请求和用户一些响应信息;
IIS:
微软的;ASP…,Windows中自带的
Tomcat:Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学web来说,最佳的选择
Tomcat 实际上运行JSP 页面和Servlet。Tomcat最新版本为9.0.41**。**
下载tomcat
1.安装or解压
2.了解配置文件及目录结构
3.作用
3、Tomcat
1、安装tomcat
- tomcat官网:https://tomcat.apache.org/
2、Tomcat启动和配置
文件夹作用:
可能遇到的问题:
- Java环境变量没有配置
- 闪退问题:需要配置兼容性
- 乱码问题:配置文件中设置conf–>server.html
可以配置启动的端口号
- tomcat的默认端口号:8080
- mysql:3306
- http:80
- https:443
可以配置启动的端口号,主机的名称
- 默认的主机名为:localhost->127.0.0.1
高难度面试题
请你谈谈网站是如何进行访问的
-
输入一个域名;点击回车
-
检查本机的配置文件下有没有这个域名的映射;
- 有,直接返回对应的ip地址
- 没有,去dns服务器找,找到就返回,找不到就返回找不到
4.配置环境变量
5.发布一个web网站
- 将自己写的网站,放到服务器(tomcat)中指定的web应用的文件夹(webapps)下就可以访问了
网站应该有的结构
--webapps : tomcat服务器的web目录 -root -sh_yy :网站的目录名 - web - inf -classes :java程序 -lib :web应用所依赖的jar包 -web.xml:网站配置文件 - index.html 默认的首页### 4、http
4、Http
什么是http
超文本传输协议(HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。
- 文本:html,字符串,
- 超文本:图片,音乐,视频,定位
- 80
Https:安全的
- 443
两个时代
- http1.0
- HTTP/1.0:客户端可以与web服务器连接后,只能获取一个web资源
- http2.0
- http/1.1:客户端可以与web服务器连接后,可以获取多个web资源
http请求
- 客户端–发请求(Request)—服务器
百度:
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET get方法/post方法
Status Code: 200 OK 状态码:200
Remote(远程) Address: 36.152.44.95:443
1、请求行
- 请求行中的请求方式:GET
- 请求方式:Get,Post,HEAD,DEFAULT,PUT,TRACT
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- post:请求能够携带的参数没有限制,大小没有限制,会在浏览器的URL地址栏显示数据内容,安全,但不高效
2、消息头
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式
Accept-Language: 告诉浏览器的语言环境
Cache-control:缓存控制
Connection:告诉浏览器请求完成是断开还是连接
Host:主机
http响应
- 服务器–响应—客户端
百度:
Cache-Control: private 缓存控制
Connection: keep-alive 连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 类型
响应体
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding: 支持哪种编码格式
Accept-Language: 告诉浏览器的语言环境
Cache-control:缓存控制
Connection:告诉浏览器请求完成是断开还是连接
Host:主机
Reflush:告诉客户端,多久刷新一次
Location:让网页重新定位
响应状态码
200:请求响应成功
3**:请求重定向
- 重定向:你重新到我给你的新位置去
404:找不到资源
- 资源不存在
5xx:服务器代码错误 500 502:网关错误
常见面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么
5、Maven
我为什么要学习这个技术?
1.在javaweb开发中,需要使用大量的jar包,我们手动去导入;
2.如何能够让一个东西自动帮我们导入和配置这个jar包
Maven项目架构管理工具
我们目前用来就是方便导入jar包的!
Maven的核心思想:约定大于配置
- 有约束,不要去违反。
Maven会规定好你该如何去编写我们的Java代码,必须要按照这个规范来
下载安装Maven
电脑上的所有环境放在一个文件夹
配置环境变量
配置如下配置
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven的目录
- 在系统中的path中配置MAVEN_HOME%\bin
阿里云镜像
-
镜像:mirros
- 作用:加速我们的下载
国内建议使用阿里云的镜像
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</ur>
</mirror>
本地仓库
在本地的仓库,远程的仓库;
建立一个本地仓库:
<localRepository>D:\apache-maven\apache-maven-3.6.3\maven-repo</localRepository>
在IDEA中使用Maven
1.启动idea
2.创建一个maven项目
3.观察maven仓库中多了什么东西
4.idea中的maven设置
5.maven的配置和使用就ok
创建一个普通的maven项目
在idea中配置tomcat
pom文件
pom.xml是maven的核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!--maven 版本和头文件-->
<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>
<!--这里就是我们刚才配置的GAV-->
<groupId>org.example</groupId>
<artifactId>maven-1</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- Package :项目的打包方式
jar:java应用
war:javaweb应用
-->
<packaging>war</packaging>
<name>maven-1 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<!--配置-->
<properties>
<!-- 项目的默认构建编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 编译版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!--项目依赖-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<!--项目构建用的-->
<build>
<finalName>maven-1</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
maven由于他的约定大于配置,我们写的配置文件无法被导出或者生效
解决方案:
<!--在build中配置resources-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<exclude>**/*.properties</exclude>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
idea操作
解决所遇到的问题
maven默认的web项目中的web.xml替换和tomcat一至
<?xml version="1.0" encoding="UTF-8"?>
<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>
6、Servlet
Servlet简介:
-
Servlet就是sun公司开发动态web的一门技术
-
sun在这些api中提供一个接口:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:
- 编写一个类,实现Servlet接口
- 把开发好的类部署到web服务器中
把实现了Servlet的接口的java程序叫做,Servlet
HelloServlet
Servlet接口Sun公司有两个默认的实现类:HtppServlet,GenericServlet
1.构建一个maven项目,删掉src目录
2.关于maven父子工程的理解
父项目中会多一个
<modules>
<module>servlet-01</module>
</modules>
子项目中
<groupId>org.example</groupId>
<artifactId>servlet-01</artifactId>
<version>1.0-SNAPSHOT</version>
3.maven环境优化
1.修改xml为最新的
2.将maven结构搭建完整
4.编写一个Servlet程序
1.编写一个普通类
2.实现Servlet接口,这里直接继承HttpServlet
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同方式,可以相互调用,业务逻辑都一样
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();//响应流
writer.println("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5.编写Servlet的映射
为什么需要映射?:我们写的时java程序,但是需要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能访问的路径
<!-- 注册Servlet -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.sh.servlet.HelloServlet</servlet-class>
</servlet>
<!-- Servlet的请求路径 -->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
6.配置tomcat
7.启动测试
Servlet原理
Servlet是由web服务器调用,web服务器在收到服务器请求之后,会:
ServletContext
web容器在启动的时候,它会为每个web程序都创建一个对应的ServletContext对象,它代表了当前的web应用;
- 共享数据
- 我在这个Servlet保存的数据,可以在另外一个Servlet中拿到
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameter(); 初始化参数
// this.getServletConfig(); Servlet配置
// this.getServletContext(); Servlet上下文
ServletContext context = this.getServletContext();
String username= "舒豪";//数据
context.setAttribute("username",username);//将一个数据保存在ServletContext中
System.out.println("Hello");
}
}
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 {
doGet(req, resp);
}
}
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.sh.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.sh.servlet.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
获得初始化参数(ServletContext应用)
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String url = context.getInitParameter("url");
resp.getWriter().print(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!-- web初始化应用-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/root</param-value>
</context-param>
<servlet>
<servlet-name>gp</servlet-name>
<servlet-class>com.sh.servlet.ServletDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>gp</servlet-name>
<url-pattern>/gp</url-pattern>
</servlet-mapping>
请求转发(ServletContext应用)
public class ServletDemo4 extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
System.out.println("进入了ServletDemo4");
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//转发的请求路径
requestDispatcher.forward(req,resp);//调用forward实现请求转发;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
读取资源文件
Properties
- 在java目录下新建properties
- 在resources目录下新建properties
发现:都被打包到了同一路径:classes,我们俗称这个路径为classpath;
思路:需要一个文件流
public class ServletDemo5 extends HelloServlet{
@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);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
HttpServletResponse
web服务器接收到客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;
- 如果获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端响应一些消息:HttpServletResponse
简单分类
负责向浏览器发送数据的方法
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);
文件下载
1.向浏览器输出消息
2.下载文件
1.要获取下载文件的路径
2.下载的文件名是啥
3.想办法让浏览器能够支持下载我们需要的东西
4.获取下载文件的输入流
5.创建缓冲区
6.获取OutputStream对象
7.将FileOutputStream流写入到buffer缓冲区
8.使用outputStream将缓冲区的数据输出客户端
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.要获取下载文件的路径
String realPath = "D:\\Day0\\maven-4\\response\\target\\classes\\舒豪.jpg";
System.out.println("下载文件的路径:" + realPath);
// 2.下载的文件名是啥
String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3.想办法让浏览器能够支持下载我们需要的东西
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 outputStream = resp.getOutputStream();
// 7.将FileOutputStream流写入到buffer缓冲区,使用outputStream将缓冲区的数据输出客户端
while ((len = in.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
in.close();
outputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
验证码功能
验证怎么来的?
- 前端实现
- 后端实现,需要用到java图片类,生产一个图片
重定向
一个web资源收到客户端A请求后,B他会通知A客户端去访问另外一个web资源,这个过程叫重定向
常见场景
- 用户登录
void sendRedirect(String var1) throws IOException;
测试:
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/response_war/img");//重定向
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
面试题:请你聊聊重定向和转发的区别?
相同点
- 页面都会跳转
不同点
- 请求转发的时候,url不会发生变化
- 重定向时候,url地址栏会发生变化
HttpServletRequest
HttpServletRequest代表客户端请求,用户通过http协议访问服务器,http请求中的所有的信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有的信息
1.获取参数,请求转发
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.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("`````````````````````````");
//通过请求转发
// 这里的 / 代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
请求和转发的重要性
请求:307
转发:302
7、Cookie、Session
7.1会话
会话: 用户打开了一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话
**有状态会话:**一个同学来过教室,我们知道这个同学,曾经来过,称之为有状态会话
你能怎么正名你是东湖的学生
你 东湖
1.发票 东湖给你发票
2.学校登记 东湖标记你来过了
一个网站,怎么证明你来过?
客户端 服务端
- 服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了;cookie
- 服务器登记你来过了,下次你来的时候我来匹配你;session
7.2 保存会话的两种技术
cookie
- 客户端技术 (响应,请求)
session
- 服务端技术,利用这个技术,可以保存用户的会话信息,我们可以把信息或者技术放在Session
常见:网站登录之后,下次不用再登录了。
7.3 Cookie
1.从请求中拿到cookie信息
2.服务器响应给客户端cookie
Cookie[] cookies = req.getCookies();//获得cookie
cookie.getName();//获得cookie的key
cookie.getValue();//获得cookie的value
new Cookie("lastLoginTime", System.currentTimeMillis()+"");//新建一个cookie
cookie.setMaxAge(24*60*60);//设置cookie的有效期
resp.addCookie(cookie);//响应给客户端
cookie :一般保存在本地的用户目录下appdata;
一个网站cookie是否存在上限
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,最多存放20多个cookie
- cookie大小有限制4kb
- 300个cookie浏览器上限
删除cookie
- 不设置有效期,关闭浏览器
- 设置有效期时间为0,
编码解码
URLEncoder.encode("舒豪","utf-8")
URLDecoder.decode(cookie.getValue(),"utf-8");
7.4 Session(重点)
什么是Session:
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个session独占一个浏览器,只有这个浏览器没有关闭,这个session就存在
- 用户登录之后,整个网站它都可以访问! --》保存用户的信息,保存购物车的信息
Session和cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到用户独占Session中,服务器端保存(保存重要的信息,减少服务器资源的浪费)
- Session对象由服务器创建;
使用场景:
- 保存一个登录用户的信息;
- 购物车信息;
- 在整个网站中经常会使用的数据,我们将它保存在session中;
使用Session:
public class SessionDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = req.getSession();
//给session存东西
session.setAttribute("name",new Person("舒豪",23));
//获取session的id
String sessionId = session.getId();
//判断Session是不是新创建的
if (session.isNew()){
resp.getWriter().write("session创建成功,ID"+sessionId);
}else {
resp.getWriter().write("session已经在服务器中存在了,ID"+sessionId);
}
//session创建的时候做了什么事情
// Cookie cookie = new Cookie("JSESSIONID",sessionId);
// resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
public class SessionDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
resp.setCharacterEncoding("utf-8");
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//得到session
HttpSession session = req.getSession();
Person name = (Person) session.getAttribute("name");
System.out.println(name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
public class SessionDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销session
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
会话自动过期
<!--设置Session默认的失效时间-->
<session-config>
<!--1分钟后自动失效-->
<session-timeout>1</session-timeout>
</session-config>
8、jsp
8.1、什么是jsp
java Serrver pages: java服务端页面,也和servlet一样,用于动态web技术。
最大的特点:
- 写jsp就像在写HTML
- 区别:
- HTML只给用户提供静态的数据
- JSP页面中可以嵌入Java代码,为用户提供动态数据
8.2、JSP原理
思路:JSP到底怎么执行的
-
代码层面没有任何问题
-
服务器内部工作
tomcat中有一个work目录;
IDEA中使用tomcat的会在IDEA的tomcat中生产一个work目录
C:\Users\辣条薯片\AppData\Local\JetBrains\IntelliJIdea2020.3\tomcat\ded9e37b-16d0-4c8b-a24a-8506527e93e0\work\Catalina\localhost\servlet_02_war\org\apache\jsp
发现页面转变成了Java程序!
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
JSP最终也会被转换成一个java类
JSP本质就是一个Servlet,HTTPJspBase继承了HttpServlet
//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//JSPService
public void _jspService(HttpServletRequest request, HttpServletResponse response)
1.判断请求
2.内置一些对象
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; //out
final java.lang.Object page = this; //page:当前页
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
HttpServletRequest request //请求
HttpServletResponse response //响应
3.输出页面前增加的代码
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;
4.以上的这些对象,我们可以在jsp中直接使用!
在JSP页面中;
只要是JAVA代码就会原封不动的输出;
如果是HTML代码,就会被转换为
out.write(“name:”);
8.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>");
%>
JSP脚本片段再使用
<%
int x=10;
out.println(x);
%>
<p>这是一个jsp文档</p>
<%
int y =20;
out.println(y);
%>
<hr>
<%--在代码中嵌入HTML元素--%>
<%
for (int i = 0; i < 7; i++) {
%>
<h1>Hello,world <%=i%></h1>
<%
}
%>
JSP声明
<%!
static {
System.out.println("Loading Servlet!");
}
private int globalVar = 0;
public void sh(){
System.out.println("进入了方法sh");
}
%>
JSP声明:会被编译到JSP生成的类中!其他的会被生成到jsp_service方法中!
在JSP中,嵌入Java代码即可!
<%%>
<%=%>
<%!%>
<%--注释--%>
JSP的注释,不会在客户端显示,HTML就会
8.4、JSP指令
<%@page args...%>
<%@include file=""%>
<%--@include会将页面和二为一--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>
<hr>
<%--jsp标签
jsp:include:拼接页面,本质是3个
--%>
<jsp:include page="/common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="/common/footer.jsp"/>
8.5、9大内置对象
- pageContext 存东西
- Request 存东西
- Response
- Session 存东西
- Application [ServletContext] 存东西
- config [ServletConfig]
- out
- page 不用
- exception
pageContext.setAttribute("name1","舒豪1号");//保存的数据只在一个页面中有效
request.setAttribute("name2","舒豪2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","舒豪3号");//保存的数据只在一个会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","舒豪4号");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
request:客户端向服务器发送请求,产生的数据,用户看完了,就没用了
session:客户端向服务器发送请求,产生的数据,用户用完了一会还有用,比如购物车
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其它用户还可能使用,比如聊天
8.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 page=""--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="shuhao"/>
<jsp:param name="age" value="23"/>
</jsp:forward>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML的不足;它自定义了许多的标签,可以供我们使用,,标签的功能和Java代码一样。
格式化标签
sql标签
xml标签
核心标签(掌握部分)
JSTL标签库使用步骤
- 引入对应的taglib
- 使用其中的方法
- 在tomcat中也需要引入JSTL的包
<h4>if测试</h4>
<hr>
<form action="coreif.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断如果提交的用户名是管理员,则登录成功--%>
<c:if test ="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎您!"/>
</c:if>
<c:out value="${isAdmin}"/>
<%--定义一个变量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>
<%
ArrayList<Object> people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"田六");
request.setAttribute("list",people);
%>
<%--
var ,每一次遍历出来的变量
items,要遍历d的对象
begin,哪里开始
end, 到哪里
step,步长
--%>
<c:forEach var="people" items="${list}">
<c:out value="${people}"/> <br>
</c:forEach>
9、JavaBean
实体类
javaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库的字段做映射
- 过滤器
- 文件上传
- 邮件发送
- JDBC复习:如何使用JDBC,JDBC crud jdbc事务
10、MVC三层架构
10.1 早年
什么是mvc: Model view controller
模型 视图 控制器
用户直接访问控制层,控制层就可以直接操作数据库;
servlet--CRUD-->数据库
弊端:程序十分臃肿,不利于维护 servlet的代码中:处理请求、响应、视图跳转、处理JDBC、业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序员调用
|
JDBC
|
Mysql Oracle SqlServer
10.2 MVC三层架构
Model
- 业务处理 : 业务逻辑(service)
- 数据持久层:CRUD (Dao)
View
- 展示数据
- 提供链接发起Servlet请求(a,form,img)
Controller(Servlet)
- 接收用户的请求
- 交给业务处理对应的代码
- 控制视图跳转
登录-->接收用户的登录请求-->处理用户的请求(获取用户登录的参数,username,password)-->交给业务层处理登录业务(判断用户密码是否正确:事务)-->Dao层查询用户名和密码是否正确-->数据库
11、Filter(重点)
Shiro
Filter:过滤器,用来过滤网站的数据;
- 处理中文代码
- 登录验证。。。
Filter开发步骤
1.导包
2.编写过滤器(导包不要错)
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就已经初始化了,随时等待过滤器对象出现!
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CharacterEncoding初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//Chain :链
/*
1.过滤中的所有代码,在过滤特定的时候都会执行
2.必须要让过滤器继续同行
chain.doFilter(request,response);
*/
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("CharacterEncoding执行前");
chain.doFilter(request,response);//让我们的请求继续走
System.out.println("CharacterEncoding执行后");
}
//销毁:web服务器关闭的时候,过滤会销毁
@Override
public void destroy() {
}
}
3.在web.xml中配置Filter过滤器
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.sh.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<!--只要是 /servlet的任何请求,会经过这个过滤器-->
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
12、监听器
实现一个监听器的接口;(有n种)
1.编写监听器
实现监听器的接口
//统计网站在线人数: 统计session
public class OnlineCount implements HttpSessionListener {
//创建session监听:看你的一举一动
//一旦创建Session就会触发一次这个事件
@Override
public void sessionCreated(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
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就会触发一次这个事件
@Override
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
/*
Session销毁:
1.手动销毁 getSession().invalidate();
2.自动销毁
*/
}
2.web.xml中注册监听器
<!--注册监听器-->
<listener>
<listener-class>com.sh.listener.OnlineCount</listener-class>
</listener>
13、过滤器、监听器常见应用
**监听器:**GUI经常使用
用户登录之后进入主页,注销之后进入不了主页
1.用户登录之后,向Session中放入用户的数据
2.进入主页的时候要判断用户是否已经登录;要求在过滤器中实现
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
HttpServletResponse response1 = (HttpServletResponse) response;
if (request1.getSession().getAttribute("USER_SESSION")==null){
response1.sendRedirect("/error.jsp");
}
chain.doFilter(request,response);
}
14、JDBC
什么是JDBC:java连接数据库
需要jar包支持
- java.sql
- javax.sql
- mysql-connecter-java 连接驱动(必须要导入)
实验环境搭建
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','lis@qq.com','2000-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');
SELECT * FROM users;
导入数据库依赖
<!--mysql的驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
JDBC固定步骤
- 加载驱动
- 连接数据库,代表数据库
- 向数据库发送是SQL的对象Statement:CRUD
- 编写SQL(根据业务,不同的SQL)
- 执行SQL
- 关闭连接
public static void main(String[] args) throws Exception {
//配置信息
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username ="root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL的对象Statement
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from users";
//5.执行SQL,返回一个结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id"+rs.getObject("id"));
System.out.println("name"+rs.getObject("name"));
System.out.println("password"+rs.getObject("password"));
System.out.println("email"+rs.getObject("email"));
System.out.println("birthday"+rs.getObject("birthday"));
}
//6.关闭资源
rs.close();
statement.close();
connection.close();
}
}
预编译SQL
public class TestJDBC2 {
public static void main(String[] args) throws Exception {
//配置信息
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username ="root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.编写SQL
String sql = "insert into users(id, name, password, email, birthday) values(?,?,?,?,?)";
//4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,4);
preparedStatement.setString(2,"飒飒的");
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"2443553@qq.com");
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
//5.执行SQL
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功!");
}
//6.关闭资源
preparedStatement.close();
connection.close();
}
}
事务
要么都成功,要么都失败
ACID原则:保证数据的安全。
开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务
转账:
A:1000
B: 1000
A(900) --100--> B(1100)
Junit单元测试
依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
简单使用
@Test注解只有在方法上有效,只要加了这个注解的方法,就可以运行
搭建一个环境,测试事务
15、SMBMS
项目如何搭建
考虑是否使用maven,依赖,jar包
项目搭建
1.搭建一个maven web 项目
2.配置Tomcat
3.导入项目中遇到的jar包
4.创建项目包结构
5.编写实体类
ORM映射:表-类映射
6.编写基础公共类
1.数据库配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
2.编写数据库的公共类
package com.sh.dao;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
//操作数据库的公共类
public class BseDao {
private static String driver;
private static String url;
private static String username;
private static String password;
//静态代码块,类加载的时候就初始化了
static {
Properties properties = new Properties();
//通过类加载器读取对应的资源
InputStream is = BseDao.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[] params,ResultSet resultSet, PreparedStatement preparedStatement) throws SQLException {
preparedStatement = connection.prepareStatement(sql);
for (int i=1;i<params.length;i++){
preparedStatement.setObject(i+1,params[i]);
}
resultSet = preparedStatement.executeQuery();
return resultSet;
}
//编写增删改工具类
public static int execute(Connection connection,String sql,Object[] params,PreparedStatement preparedStatement) throws SQLException {
preparedStatement = connection.prepareStatement(sql);
for (int i=1;i<params.length;i++){
preparedStatement.setObject(i+1,params[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();
//Gc回收
resultSet = null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
if (preparedStatement!=null){
try {
preparedStatement.close();
//Gc回收
preparedStatement = null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
if (connection!=null){
try {
connection.close();
//Gc回收
connection = null;
} catch (SQLException e) {
e.printStackTrace();
flag=false;
}
}
return flag;
}
}
3.编写字节码过滤器
<!--字符编码过滤器-->
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>com.sh.filter.CharacterEncoding</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
7.导入静态资源
登录功能实现
1.编写前端页面
2.设置首页
<!--设置欢迎页面-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
3.编写Dao层登录用户登录的接口
public interface UserDao {
//得到登录的用户
public User getLoginUser(Connection connection ,String userCode) throws SQLException;
}
4.编写dao接口的实现类
package com.sh.dao.user;
import com.sh.dao.BseDao;
import com.sh.pojo.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDaoImpl implements UserDao{
@Override
public User getLoginUser(Connection connection, String userCode) throws SQLException {
PreparedStatement pstm = null;
ResultSet rs = null;
User user = null;
if (connection!=null){
String sql="select * from smbms_user where userCode=?";
Object[] params = {userCode};
rs = BseDao.execute(connection,pstm,rs,sql,params);
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("creationDate"));
user.setCreationDate(rs.getTimestamp("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getTimestamp("modifyDate"));
}
BseDao.closeResource(null,pstm,rs);
}
return user;
}
}
5.编写业务层接口
public interface UserService {
//用户登录
public User login(String userCode,String password);
}
6.编写业务层接口的实现类
package com.sh.service.user;
import com.sh.dao.BseDao;
import com.sh.dao.user.UserDao;
import com.sh.dao.user.UserDaoImpl;
import com.sh.pojo.User;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
public class UserServiceImpl implements UserService{
//业务层都会调用dao层,所以我们要引入Dao层
private UserDao userDao;
public UserServiceImpl(){
userDao = new UserDaoImpl();
}
@Override
public User login(String userCode, String password) {
Connection connection = null;
User user=null;
connection = BseDao.getConnection();
try {
user = userDao.getLoginUser(connection, userCode);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BseDao.closeResource(connection,null,null);
}
return user;
}
}
7.编写servlet
package com.sh.servlet.user;
import com.sh.pojo.User;
import com.sh.service.user.UserServiceImpl;
import com.sh.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--start...");
//获取用户名和密码
String userCode = req.getParameter("userCode");
String userPassword = req.getParameter("userPassword");
//和数据库中的密码进行对比,调用业务层:
UserServiceImpl userService = new UserServiceImpl();
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);
}
}
8.注册servlet
<!--Servlet-->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.sh.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
9.测试访问
遇到的问题:进入到登录界面,无法跳转到页面
解决:在WEB-INF下导入standard的解压包的.tld文件
登录功能优化
注销功能:
思路:移除Session,返回登录页面
package com.sh.servlet.user;
import com.sh.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 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(req.getContextPath()+"/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.sh.servlet.user.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>
登录拦截优化
编写一个过滤器并注册
package com.sh.filter;
import com.sh.pojo.User;
import com.sh.util.Constants;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
HttpServletResponse response1 = (HttpServletResponse) response;
//过滤器,从Session中获取用户
User user = (User)request1.getSession().getAttribute(Constants.USER_SESSION);
if (user==null){
response1.sendRedirect("/smbms/error.jsp");
}else {
chain.doFilter(request,response);
}
}
@Override
public void destroy() {
}
}
<!--用户登录过滤器-->
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.sh.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>
2.写项目,从底层写
3.UserDao接口
4.UserDao接口实现类
public int updatePwd(Connection connection, int id, int password) throws SQLException {
PreparedStatement pstm = null;
int execute = 0;
if (connection!=null){
String sql = "update smbms_user set userPassword = ? where id=?";
Object params[] = {password,id};
execute = BseDao.execute(connection, pstm, sql, params);
BseDao.closeResource(null,pstm,null);
}
return execute;
}
}
5.service层
public boolean updatePwd(int id, int pwd) {
Connection connection =null;
boolean flag =false;
//修改密码
try {
connection = BseDao.getConnection();
if (userDao.updatePwd(connection,id,pwd)>0){
flag=true;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
BseDao.closeResource(connection,null,null);
}
return flag;
}
}
6.servlet
package com.sh.servlet.user;
import com.mysql.jdbc.StringUtils;
import com.sh.pojo.User;
import com.sh.service.user.UserService;
import com.sh.service.user.UserServiceImpl;
import com.sh.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;
//实现servlet复用
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//从session里面拿ID;
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String newpassword = req.getParameter("newpassword");
boolean flag=false;
if (o!=null&& !StringUtils.isNullOrEmpty(newpassword)){
UserService userService = new UserServiceImpl();
boolean b = 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","新密码有问题");
}
req.getRequestDispatcher("pwdmodify.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7.实现复用,需要提取方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if ("savepwd".equals(method)){
this.updatePwd(req,resp);
}
}
优化密码修改Ajax
1. 阿里巴巴的fastjson
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
2. 后台代码修改
//修改密码
public void updatePwd(HttpServletRequest req, HttpServletResponse resp) {
//从session里面拿ID;
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String newpassword = req.getParameter("newpassword");
System.out.println("UserServlet:"+newpassword);
boolean flag = false;
if (o != null && newpassword != null) {
UserService 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();
}
}
//验证旧密码,session中有用户的密码
public void pwdmodify(HttpServletRequest req, HttpServletResponse resp){
//从Session中拿id
Object o = req.getSession().getAttribute(Constants.USER_SESSION);
String oldpassword = req.getParameter("oldpassword");
//万能的Map:结果集
Map<String, String> resultMap = new HashMap<String,String>();
if (o==null){//Session失效
resultMap.put("result","sessionerror");
}else if (StringUtils.isNullOrEmpty(oldpassword)){//输入的密码为空
resultMap.put("result","error");
}else {
String userPassword = ((User) o).getUserPassword();//Session用户中的密码
if (oldpassword.equals(userPassword)){
resultMap.put("result","true");
}else {
resultMap.put("result","false");
}
}
try {
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
//阿里巴巴的工具类,转换格式的
writer.write(JSONArray.toJSONString(resultMap));
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
用户管理实现
1.导入分页的工具类
2.用户列表页面导入
1.获取用户数量
1.UserDao
2.UserDaoImpl
3.UserService
4.UserServiceImpl
2.获取用户列表
3.获取角色操作
4.用户显示的Servlet
1.用户前端的数据(查询)
2.判断请求是否需要执行,看参数的值判断
3.为了实现分页,需要计算出当前页面和总页面,页面大小
4.返回前端
小黄鸭调试法;自言自语