JavaWeb
Java Web
1、基本概念
1.1、前言
web开发:
-
web,网页的意思,www.baidu.com
-
静态web
-
html , css
-
提供给所有人看的数据始终不会发生变化!
-
-
动态web
-
淘宝,几乎所有的网站:
-
提供给所有人看的数据始终会发生变化,每个人在不同的时间,不同的地点看到的信息各不相同!
-
技术栈:Servlet/JSP , ASP , PHP
-
在Java中,动态web资源开发的技术统称为Javaweb;
1.2、web应用程序
web应用程序:可以提供浏览器访问的程序;
-
a.html、b.html …..多个web资源,这些web资源可以被web访问
-
你们能访问到的任何一个页面或者资源,都存在于这个世界上的某一个角落的计算机上。
-
URL
-
这些统一的web资源会被放在同一个文件夹上,web应用程序– –>Tomcat :服务器
-
一个web应用由多部分组成(静态web,动态web)
-
html,css,js
-
jsp,servlet
-
Java程序
-
jar包
-
配置文件(Properties)
-
web应用程序编写完毕后,若想它提供给外界访问:需要一个服务器来统一管理;
#获得物理IP
ping www.baidu.com
1.3、静态web
-
.htm,.html,这些都是网页的后缀,如果服务器上一直存在这些东西,我们就可以直接进行读取。通网;
-
静态web存在的缺点
-
web页面无法更新,所有用户看到的都是同一个页面
-
轮播图,点击特效:伪动态
-
JavaScript(实际开发中,它用的最多)
-
VBScript
-
-
它无法和数据库交互(数据无法持久化,用户无法交互)
1.4、动态web
页面动态展示:“web页面的展示效果因人而异”
缺点
-
加入服务器的动态web资源出现了错误,我们需要重新编写我们的后台程序,重新发布;
-
停机维护
-
-
优点:
-
web页面可以更新,所有用户看到的都不是同一个页面
-
它可以与数据库交互(数据持久化:注册,商品信息,用户信息….)
-
2、web服务器
2.1、技术讲解
ASP
-
微软:国内最早流行的就是ASP;
-
在HTML中嵌入了VB的脚本,ASP + COM;
-
在ASP开发中,基本一个页面都有几千行的业务代码,页面极其换乱
-
维护成本高
-
C#
-
IIS
<h1>
<h1><h1>
<h1>
<h1>
<h1>
<h1>
<%
System.out.println("hello")
%>
<h1>
<h1>
<h1><h1>
<h1>
php
-
PHP开发速度很快,功能很强大,跨平台,代码很简单(70%,WP)
-
无法承载大访问量的情况(局限性)
JSP/Servlt:
B/S:浏览器和服务器
C/S:客户端和服务器
-
sun公司主推的B/S架构
-
基于Java语言的(所有的大公司,或者一些开源的组件,都是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 应用服务器,属于轻量级应用
Tomcat 实际上运行JSP 页面和Servlet。 Tomcat最新版本为10.0.5。
工作3~5年之后,可以尝试手写Tomcat服务器:
下载Tomcat:
1.安装 or 解压
2.了解配置文件及目录结构
3.这个东西的作用
3、Tomcat
3.1、安装Tomcat
Tomcat官网:https://tomcat.apache.org/
3.2、Tomcat启动和配置
文件夹作用:
启动、关闭Tomcat
可能遇到的问题:
-
Java环境变量没有配置
-
闪退问题:需要配置兼容性
-
乱码问题:配置文件中设置
3.3、配置
命令行启动Tomcat(前提:是在Tomcat中bin目录下执行:cd bin):
启动:sh startup.sh
关闭:sh shutdown.sh
可以配置启动的端口
-
tomcat的默认端口号:8080
-
mysql默认端口号:3306
-
http:80
-
https:443
<Connector port="8081" protocol="HTPP/1.1"
connectionTimeout="20000"
redirectPort="8443"/>
可以配置主机的名称
-
默认的主机名为:lcoalhost- ->127.0.0.1
-
默认网站应用存放的位置为:webapps
<Host name="www.wuwei.com" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题:
请你谈一谈网站是如何进行访问的!
1.输入一个域名:回车
2.检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名映射;
-
有:直接返回对应的ip地址,这个地址中,有我们访问的web程序,可以直接访问
127.0.0.1 www.wuwei.com
-
没有:去DNS服务器找,找到的话就返回,找不到就返回找不到;
4.可以配置一下环境变量(可选性)
3.4发布一个web网站
不会先模仿
-
将自己写的网站,放到服务器(Tomcat)中指定的web应用的文件夹(webapps)下,就可以访问了
网站应该有的结构
-- webapps : Tomcat服务器的web目录
-- ROOT
-- kuangstudy:网站的目录名
- classes : java程序
- lib : web应用程序所依赖的jar包
- web.xml 网站配置文件
- index.html 默认的首页
- static
- css
-style.css
-js
-img
-.......
4、HTTP
4.1、什么是HTTP
HTTP(超文本传输协议)是一个简单的请求-响应协议,它主要运行在TCP之上。
-
文本:html,字符串,~…
-
超文本:图片,音乐,视频,定位,地图….
-
80
Https:安全的
-
443
4.2、两个时代
-
http1.0
-
HTTP/1.0:客户端可以与web服务器连接,只能获取一个web资源,断开连接
-
-
http2.0
-
HTTP/1.1:客户端可以与web服务器连接,只能获取多个web资源。
-
4.3、Http请求
-
客户端- -发请求(Request) - - 服务器
百度:
Request URL: https://www.baidu.com/ 请求地址
Request Method: GET get方法/post方法
Status Code: 200 OK 状态码:200
Remote(远程) Address: 110.242.68.3:443
Accept: text/html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9 语言
Cache-Control: max-age=0
Connection: keep-alive
1、请求行
-
请求行中的请求方式:GET
-
请求方式:Get,Post,HEAD,DELETE,PUT,TRACT…
-
get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但很高效
-
post:请求能够携带的参数没有限制,大小没有限制,不会在浏览器的URL地址栏显示数据内容,安全,但不很高效
-
2、消息头
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持那种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language 告诉浏览器:他的语言环境
Cache-Control 缓存控制
Connection 告诉浏览器,请求完成是断开还是保持连接
HOST:主机.../.
4.4、Http响应
-
服务器- - 响应- - 客户端
百度:
Cache-Control: private 缓存控制
Connection: keep-alive 连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 类型
1.响应体
Accept:告诉浏览器,它所支持的数据类型
Accept-Encoding:支持那种编码格式 GBK UTF-8 GB2312 ISO8859-1
Accept-Language 告诉浏览器:他的语言环境
Cache-Control 缓存控制
Connection 告诉浏览器,请求完成是断开还是保持连接
HOST:主机.../.
Refresh:告诉客户端,多久刷新一次;
Location:让网页重新定位;
2、响应状态码
200:请求响应成功 200
3**:请求重定向
-
重定向:你重新到我给你的新位置去;
4xx:找不到资源 404
-
资源不存在;
5xx:服务器代码错误 500 502:网关错误
常见面试题:
当你的浏览器中地址栏并输入地址并回车的一瞬间页面能够展示回来,经历了什么?
1. 域名解析
2. 发起TCP的三次握手
3. 建立起TCP连接后发起http请求
4. 服务器响应http请求,浏览器得到html代码
5. 浏览器解析html代码,并请求html代码中的资源(css JavaScript 图片)
6. 浏览器对页面进行渲染呈现
5、Maven
我们为什么要学习这个技术?
-
在Javaweb开发中,需要导入大量的jar包,我们手动去导入;
-
如何让一个东西自动帮我们导入和配置这个jar包。
由此Maven诞生了!
5.1、Maven项目架构管理工具
我们目前就是来导jar包的!
Maven的核心思想:约定大于配置
-
有约束,不要去违反。
Maven会规定你该如何去编写我们的Java代码,必须按照这个规范来;
5.2、下载安装Maven
下载完成后,解压即可;
建议:电脑上的所有环境放在一个文件夹下,方便管理;
5.3、配置环境变量
在我们的系统环境变量中
配置如下配置:
-
M2_HOME maven目录下的bin目录
-
MAVEN_HOME maven目录
-
在系统的path中配置 %MAVEN_HOME%\bin
测试Maven是否安装成功,保证必须配置完成!
5.4、阿里云镜像
-
镜像:mirrors
-
作用:加速我们的下载
-
-
国内建议使用阿里云的镜像
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
配置jdk环境:
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
</profiles>
5.5、本地仓库
在本地的仓库,远程仓库;
建立一个本地仓库:localRepository
<localRepository>/usr/local/apache-maven-3.8.4/maven-repo</localRepository>
5.6、IDEA中启动Maven
1、启动IDEA
2、创建一个Mavenweb项目
3、等待项目初始化完毕
4、观察maven仓库中多了什么东西?
5、Maven中的IDEA设置
注意:IDEA项目创建成功后,看一眼Maven配置
6、到这里,Maven在IDEA中的配置和使用就OK了
5.7、创建一个maven项目
这个只有在web应用下才会有!
5.8、标记文件夹功能
5.9、在IDEA中配置Tomcat
解决警告问题
必须要的配置:为什么会有这个问题:我们访问一个网站,需要指定一个文件夹的名字;
5.10、pom文件
pom.xml是Maven的核心配置文件
在SpringBoot甚至之后的学习全面的问题解决,maven资源导出问题:
<build>
<defaultGoal>install</defaultGoal>
<finalName>JavaDevPlatform</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<outputDirectory>${basedir}/target/jar</outputDirectory>
<resources>
<resource>
<directory>src/main/resources/com/szboanda</directory>
<targetPath>${basedir}/target/jar/com/szboanda</targetPath>
</resource>
<resource>
<directory>src/main/resources/sql</directory>
<targetPath>${basedir}/target/jar/sql</targetPath>
</resource>
<resource>
<directory>src/main</directory>
<includes>
<include>web-fragment.xml</include>
</includes>
<targetPath>${basedir}/target/jar/META-INF</targetPath>
</resource>
<resource>
<directory>src/main/webapp</directory>
<excludes>
<exclude>WEB-INF/classes/**</exclude>
<exclude>WEB-INF/lib/**</exclude>
<exclude>WEB-INF/logs/**</exclude>
<exclude>WEB-INF/sql/**</exclude>
<exclude>WEB-INF/web.xml</exclude>
</excludes>
<targetPath>${basedir}/target/jar/META-INF/resources</targetPath>
</resource>
</resources>
<plugins>
<!-- 为了使项目结构更为清晰,Maven区别对待Java代码文件和资源文件,maven-compiler-plugin用来编译Java代码 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version> 3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!--
为了使项目结构更为清晰,Maven区别对待Java代码文件和资源文件,maven-compiler-plugin用来编译Java代码,
maven-resources-plugin则用来处理资源文件,默认的主资源文件目录是src/main/resources,
很多用户会需要添加额外的资源文件目录,这个时候就可以通过配置maven-resources-plugin来实现。
-->
<plugin>
<!--<groupId>org.apache.maven.plugins</groupId>-->
<artifactId>maven-resources-plugin</artifactId>
<version> 3.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<!-- 打包源码的插件 -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version> 3.0.1</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
<!-- 进行package命令时就可以将源码同时进行打包
所以我们需要绑定source插件到我们default生命周期的package阶段 -->
<executions>
<execution>
<phase>package</phase>
<!-- <phase>compile</phase> -->
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
maven由于它的约定大于配置,我们之后可能会遇到我们写的配置文件,无法被导出或者生效的问题,解决方案:
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<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>
5.12、IDEA目录树
5.13、解决遇到的问题
1.Maven 3.6.2
解决方案:降级为3.6.1
2.Tomcat闪退
3.IDEA中每次都要重复配置Maven
在IDEA中的全局默认配置中去配置
4.Maven项目中Tomcat无法配置
5.maven 默认web项目中web.xml版本问题
6.替换为iwebapp5.0版本和tomcat一致
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
metadata-complete="true">
7.maven仓库的使用
6、Servlet
6.1、Servlet简介
-
Servlet就是sun公司开发动态web的一门技术
-
Sun在这些API中提供一个接口叫做:Servlet,如果你想开发Servlet程序,只需要完后两个步骤:
-
编写一个类,实现Servlet接口
-
把开发好的Java类部署到web服务器中。
-
把实现了Servlet接口的Java程序叫做,Servlet
6.2、HelloServlet
Servlet接口在Sun公司有两个默认的实现类:HttpServlet
1.构建一个普通Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Module;这个空的工程就是Maven的主工程;
2.关于Maven父子工程的理解;
父项目中会有
<modules>
<module>servlet-01</module>
</modules>
子项目中
<parent>
<artifactId>javaweb-02-servlet</artifactId>
<groupId>com.kuang</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
父项目中的java子项目可以直接使用
son extends father
3.Maven环境优化
-
修改web.xml为最新的
-
将maven的结构搭建完整
4.编写一个Servlet程序
-
编写一个普通类
-
实现Servlet接口,这里我们直接继承HttpServlet
public class HelloServlet extends HttpServlet {
//由于get或者post只是请求实现的不同方式,可以互相调用,业务逻辑都一样
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// ServletOutputStream outputStream = resp.getOutputStream();
PrintWriter writer = resp.getWriter();//响应流
writer.print("Hello,Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
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>
6.配置tomcat
注意:配置项目发布的路劲就可以了
7.启动测试:OK!
6.3、Servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器请求之后,会:
6.4、Mapping问题
1.一个Servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
2.一个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-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello5</url-pattern>
</servlet-mapping>
3.一个Servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
4.默认请求路径
<!--默认请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
5.指定一些后缀或者前缀等等…
<!--可以自定义后缀实现请求映射
注意点:*前面不能加项目映射的路径
-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.qinjiang</url-pattern>
</servlet-mapping>
6.优先级问题
指定了固有的映射路径优先级最高,如果找不到就会走默认的处理请求;
<!--404-->
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
6.5、ServletContext
web容器在启动的时候,他会为每个web程序都创建一个对应的ServletContext对象,他代表了当前的web应用;
1、共享数据
我在这个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 servletContext = this.getServletContext();
String username = "qinjiang";//数据
servletContext.setAttribute("username",username);//讲一个数据保存在ServletContext中,名字为username,值 username
// PrintWriter writer = resp.getWriter();
// writer.print("hello");
}
}
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String username = (String) servletContext.getAttribute("username");
resp.getWriter().print("名字:"+username);
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
<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>
测试访问结果;
2、获取初始化参数
<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>
public class ServletDemo03 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 {
doPost(req, resp);
}
}
public class ServletDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// RequestDispatcher requestDispatcher = servletContext.getRequestDispatcher("/sd");//转发的请求路径
// requestDispatcher.forward(req,resp);//调用forword实现请求转发
servletContext.getRequestDispatcher("/sd").forward(req,resp);
}
3.请求转发
4.读取资源文件
Properties
-
在Java目录下新建properties
-
在resources目录下新建properties
发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath;
思路:都需要一个文件流;
username=root
password=123456
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 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 {
doPost(req, resp);
}
访问测试即可OK!
6.6、HttpServletResponse
web服务器接收客户端的http请求,针对这个请求,分别创建一个代表请求的HttpServletRequuest对象,代表响应的一个HttpServletResponse;
-
如果要获取客户端响应过来的参数,找HttpServletRequuest
-
如果要给客户端响应一些信息:找HttpServletResponse
1、简单分类
负责向浏览器发送数据的方法
//平时的流使用他
ServletOutputStream getOutputStream() throws IOException;
//写中文用它,随意使用会造成字符串损坏或者注释!
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void 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;
2、下载文件
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 = "/Users/mac/IdeaProjects/javaweb-02-servlet/response/src/main/resources/1.png";
System.out.println("下载文件的路径:"+realPath);
// 2.下载的文件名是啥?
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3.设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"utf-8"));
// 4.获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
// 5.创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6.获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
// 7.将FileOutputStream流写入到buffer缓冲区 ,使用OutputStream将缓冲区中的数据输出到客户端!
while ((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
3、验证码功能
验证怎么来的?
-
前端实现
-
后端实现,需要用到java的图片类,生成一个图片
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//如何让浏览器5秒自动刷新一次;
resp.setHeader("refresh","3");
//在内存中创建一个图片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D g = (Graphics2D) image.getGraphics();//笔
//设置图片的背景颜色
g.setColor(Color.white);
g.fillRect(0,0,80,20);
//给图片写数据
g.setColor(Color.BLUE);
g.setFont(new Font(null,Font.BOLD,20));
g.drawString(makeNum(),0,20);
//告诉浏览器,这个请求用图片的方式打开
resp.setContentType("image/jpeg");
//网站存在缓存,不让浏览器缓存
resp.setDateHeader("Expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器
ImageIO.write(image,"jpg", resp.getOutputStream());
}
//生成随机数
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999) + "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-num.length(); i++) {
sb.append("0");
}
num = sb.toString() + num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
4.实现重定向
B一个web资源收到客户端A请求后,B他会通知客户端A去访问另一个web资源C,这个过程叫做重定向
常见场景:
-
用户登录
void sendRedirect(String var1) throws IOException;
测试:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
resp.setHeader("Location","/r/img");
resp.setStatus(302);
*/
resp.sendRedirect("/r/img");//重定向
}
面试题:请你聊聊重定向与转发的区别?
相同点
-
页面都会实现跳转
不同点
-
请求转发的时候,url不会发生变化
-
重定向的时候,url地址栏会发生变化
表单的请求与响应
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//处理请求
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
//重定向的时候一定要注意,路径问题,否则404
resp.sendRedirect("/r/success.jsp");
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Success</h1>
</body>
</html>
6.7、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过Http协议访问浏览器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息;
获取参数,请求转发
@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("=====================");
System.out.println(req.getContextPath());
//通过请求转发
//这里的 / 代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
面试题:请你聊聊重定向与转发的区别?
相同点
-
页面都会实现跳转
不同点
-
请求转发的时候,url不会发生变化 307
-
重定向的时候,url地址栏会发生变化 302
7、Cookie、Session
7.1、会话
会话:用户打开一个浏览器,点击了很多超链接,访问了很多web资源,关闭浏览器,这个过程可以称之为会话
有状态会话::一个同学来过教室,下次再来教室,我们会知道这个同学,曾经来过
你能怎么证明你是西开的学生?
你 西开
-
发票 西开给你发票
-
学校登记 西开标记你来过了
一个网站,怎么证明你来过了?
客户端 服务端
1.服务端给客户端一个信件,客户端下次访问服务端带上信件就可以了;cookie
2.服务器登记你来过了,下次你来的时候我来匹配你;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中的值
new Cookie("lastLoginTime",System.currentTimeMillis()+""); //新建一个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 ;
编码解码:
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:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//得到Session
HttpSession session = req.getSession();
//给Session中存东西
session.setAttribute("name",new Person("秦疆",1));
//得到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);
}
//得到Session
HttpSession session = req.getSession();
Person person = (Person) session.getAttribute("name");
System.out.println(person.toString());
HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销Session
session.invalidate();
会话自动过期:web.xml中配置
<!--设置Session默认失效时间-->
<session-config>
<!--15分钟后Session自动失效,以分钟为单位-->
<session-timeout>15</session-timeout>
</session-config>
8、JSP
8.1、什么是JSP
Java Server Pages:Java服务器端页面,也和Servlet一样,用于动态web技术!
最大的特点:
-
写JSP就像在写HTML
-
区别:
-
HTML只给用户提供静态的数据
-
JSP页面中可以嵌入Java代码,为用户提供动态的数据;
-
8.2、JSP原理
思路:JSP到底怎么执行的 !
-
代码层面没有任何问题
-
服务器内部工作
tomcat中有一个work目录;
IDEA中使用Tomcat的会在IDEA的Tomcat中生产一个work目录
地址:
/usr/local/ApacheTomcat/work/Catalina/localhost/ROOT/org/apache/jsp
发现页面转变为Java程序!
浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet !
JSP最终会被转换成为一个Java类!
JSP本质上就是一个Servlet
//初始化
public void jspInit() {
}
//销毁
public void jspDestroy() {
}
//JSPService
public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this._jspService(request, response);
}
1.判断请求
2.内置了一些对象
final jakarta.servlet.jsp.PageContext pageContext; //页面上下文
jakarta.servlet.http.HttpSession session = null; //Session
final jakarta.servlet.ServletContext application; //applicationContext
final jakarta.servlet.ServletConfig config; //config
jakarta.servlet.jsp.JspWriter out = null; //out
final java.lang.Object page = this; //page;当前页
HttpServletRequest request //请求
HttpServletResponse response //响应
jakarta.servlet.jsp.JspWriter _jspx_out = null;
jakarta.servlet.jsp.PageContext _jspx_page_context = null;
3.输出页面前增加的代码
response.setContentType("text/html; charset=UTF-8"); //设置响应的页面类型
pageContext = _jspxFactory.getPageContext(this, request, response,
null, false, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
out = pageContext.getOut();
_jspx_out = out;
4.以上的这些个对象我们可以在JSP页面中直接使用!
在JSP页面中:
只要是Java代码就会原封不动的输出;
如果是HTML代码,就会被转换为:
out.write("<html>\r\n");
这样的格式,输出到前端 !
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.print("<h1>Sum="+sum+"</h1>");
%>
脚本片段的在实现
<%
int x =10;
out.println(x);
%>
<p>这是一个JSP文档</p>
<%
int y =2;
out.println(y);
%>
<hr>
<%--在代码中嵌入HTML元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1>Hello,Word! <%=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代码即可!
<%%>
<%=%>
<%!%>
<--注释-->
JSP的注释,不会在客户端显示,HTML就会 !
8.4、JSP指令
<%@ page ....%>
<%@include file=""%>
<%-- @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"/>
8.5、9大内置对象
-
PageContext 存东西
-
Request 存东西
-
Response
-
Session 存东西
-
Application 【ServletContext】 存东西
-
config 【ServletConfig】
-
out
-
page 不用
-
exception
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--内置对象--%>
<%
pageContext.setAttribute("name1","秦疆1号");//保存的数据只在一个页面中有效
request.setAttribute("name2","秦疆2号");//保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","秦疆3号");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","秦疆4号");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%--脚本片段中的代码,会被原封不动的生成到.JSP.java
要求:这里面的代码,必须保证Java语法的正确性
--%>
<%
//从pageContext取出,我们通过寻找的方式来
//从底层到高层(作用域):page-->request-->session-->application
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5");//不存在
%>
<%--使用EL表达式输出 ${} --%>
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3> <%=name5%> </h3>
</body>
</html>
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用的!
session:客户端向服务器发送请求,产生的数据,用户看完一会还有用的,比如:购物车;
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;
8.6、JSP标签、JSTL标签、EL表达式
<!-- 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>
EL表达式:${ }
-
获取数据
-
执行运算
-
获取web开发的常用对象
-
调用Java方法
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 name="age" value="12"/>
</jsp:forward>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;他自定义许多标签,可以供我们使用,标签的功能和Java代码一样!
格式化标签
SQL标签
XML标签
核心标签(掌握部分)
JSTL标签库使用步骤
-
引入对应的taglib
-
使用其中的方法
-
在Tomcat也需要引入jstl的包,否则会报错:JSTL报错
c:if c:out
<body>
<h4>if测试</h4>
<hr>
<form action="coreif.jsp" method="get">
<%--
EL表达式获取表单中的数据
${param.参数名}
--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" name="登录">
</form>
<%--判断如果是提交的用户名是管理员,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎您!"/>
</c:if>
<%--自闭合标签--%>
<c:out value="${isAdmin}"/>
</body>
c:choose c:when
<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>
c:forEach
<%
ArrayList<String> people = new ArrayList<>();
people.add(0,"张三");
people.add(1,"李四");
people.add(2,"王五");
people.add(3,"赵六");
people.add(4,"田七");
request.setAttribute("list",people);
%>
<%--
var , 每一次遍历出来的变量
items , 要遍历的对象
begin , 从哪里开始
end , 到哪里结束
step , 步长
--%>
<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="2">
<c:out value="${people}"/> <br>
</c:forEach>
9、JavaBean
实体类
JavaBean有特定的写法:
-
必须有一个无参构造
-
属性必须私有化
-
必须有对应的get/set方法;
一般用来和数据库的字段做映射 ORM;
ORM:对象关系映射
-
表- ->类
-
字段- ->属性
-
行记录- ->对象
people表
id | name | age | address |
---|---|---|---|
1 | Jacker1号 | 1 | 上海 |
2 | Jacker2号 | 2 | 北京 |
3 | Jacker3号 | 3 | 广州 |
class People{
private int id;
private String name;
private int age;
private String address;
}
class A{
new People(1,"Jacker1号",1,"上海");
new People(2,"Jacker2号",2,"北京");
new People(3,"Jacker3号",3,"广州");
}
10、MVC三层架构
什么是MVC:Model view Controller 模型、视图、控制器
10.1、早些年
用户直接访问控制层,控制层可以直接操作数据库;
servlet-->CRUD-->数据库
弊端:程序十分臃肿,不利于维护
servlet的代码中:处理请求、响应、视图跳转、处理JDBC、处理业务代码、处理逻辑代码
架构:没有什么是加一层解决不了的!
程序猿调用
|
JDBC
|
Mysql Oracle sqlServlet
10.2、MVC三层架构
Model
-
业务处理:业务逻辑(Service)
-
数据持久层:CRUD(Dao)
View
-
展示数据
-
提供链接发起Servlet请求(a,form,img…)
Controller
-
接收用户的请求:(req:请求参数、Session信息…)
-
交给业务层处理对应的代码
-
控制视图的跳转
登录--->接收用户的登录请求--->处理用户的请求(获取用户登录的参数,username,password)--->交给业务层处理登录业务(判断用户名密码是否正确:事务)--->Dao层查询用户名和密码是否正确--->数据库
11、Filter(重点)
Filter:过滤器,用来过滤网站的数据;
-
处理中文乱码
-
登录验证…
Filter开发步骤:
1.导包
2.编写过滤器
1.导包不要错
实现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>
<!--只要是在/servlet下的所有请求,会经过这个过滤器-->
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
12、监听器
实现一个监听器的接口:(有N种)
1.实现监听器的接口:
//统计网站在线人数:统计 Session
public class OnlineCountListener implements HttpSessionListener {
//创建session监听:看你的一举一动
//一旦创建session就会触发一次这个事件!
public void sessionCreated(HttpSessionEvent se) {
System.out.println(se.getSession().getId());
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监听!
//一旦创销毁session就会触发一次这个事件!
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext ctx = se.getSession().getServletContext();
Integer onlineCount = (Integer) ctx.getAttribute("OnlineCount");
if (onlineCount==null){
onlineCount = new Integer(0);
}else {
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
ctx.setAttribute("OnlineCount",onlineCount);
}
/*
session销毁:
1.手动销毁 :getSession().invalidate();
2.自动销毁:web.xml配置
*/
}
2.在web.xml中配置监听器
<!--注册监听器-->
<listener>
<listener-class>com.kuang.listener.OnlineCountListener</listener-class>
</listener>
3.看情况是否使用
13、过滤器、监听器常见应用
监听器:GUI编程中经常使用:
public class TestPanel {
public static void main(String[] args) {
Frame frame = new Frame("JAVA编程") ;
Panel panel = new Panel(null);//面板
frame.setLayout(null);//设置窗体的布局
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(0,0,255));
frame.setBounds(50,50,300,300);
panel.setBackground(new Color(0,255,2));//设置背景颜色
frame.add(panel);
frame.setVisible(true);
//监听事件,监听关闭事件
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
}
});
}
}
1.用户登录之后才能进去主页!用户注销后就不能进去主页了!
2.进入主页的时候要判断用户是否已经登录;要求:在过滤器中实现!
package com.kuang.filter;
import com.kuang.util.Constant;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
/*
if(request.getSession().getAttribute(Constant.USER_SESSION).level==VIP1){
response.sendRedirect("/vip1/index.jsp");
}
if(request.getSession().getAttribute(Constant.USER_SESSION).level==VIP1){
response.sendRedirect("/vip1/index.jsp");
}
if(request.getSession().getAttribute(Constant.USER_SESSION).level==VIP1){
response.sendRedirect("/vip1/index.jsp");
}
*/
//ServletRequest HttpServletRequest
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
Object user_session = request.getSession().getAttribute(Constant.USER_SESSION);
if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
response.sendRedirect("/error.jsp");
}
chain.doFilter(request,response);
}
public void destroy() {
}
}
14、JDBC
什么是JDBC:Java连接数据库
需要jar包的支持:
-
java.sql
-
javax.sql
-
mysql-conneter-java…连接驱动(必须要导入)
实验环境搭建
CREATE TABLE `user`(
`id` INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO `user`(`id`,`name`,`password`,`email`,`birthday`)
VALUES(1,'张三','123456','zs@qq.com','2000-01-01');
INSERT INTO `user`(`id`,`name`,`password`,`email`,`birthday`)
VALUES(2,'李四','123456','ls@qq.com','2000-01-01');
INSERT INTO `user`(`id`,`name`,`password`,`email`,`birthday`)
VALUES(3,'王五','123456','ww@qq.com','2000-01-01');
导入数据库依赖
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
IDEA连接数据库
JDBC固定步骤:
-
加载驱动
-
连接数据库,代表数据库
-
向数据库发送SQL的对象:CRUD
-
编写SQL(根据业务,不同的SQL)
-
执行SQL
-
关闭连接
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "mysqlstart";
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向数据库发送SQL的对象 Statement , prepareStatement :CRUD
Statement statement = connection.createStatement();
//4.编写SQL
String sql = "select * from users ";
//5.执行查询SQL,返回一个 ResultSet : 结果集
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 ClassNotFoundException, SQLException {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "mysqlstart";
//1.加载驱动
Class.forName("com.mysql.cj.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);//给第一个占位符?的值赋值为1
preparedStatement.setString(2,"狂神说Java");//给第二个占位符?的值赋值为狂神说Java
preparedStatement.setString(3,"123456");//给第三个占位符?的值赋值为123456
preparedStatement.setString(4,"24323243@qq.com");//给第四个占位符?的值赋值为24323243@qq.com
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));//给第五个占位符?的值赋值为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单元测试
依赖
<dependencies>
<!--Junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
简单使用
@Test注解只在方法上有效,只要加了这个注解的方法,就可以直接运行!
public class TestJdbc3 {
@Test
public void test() {
Connection connection = null;
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "mysqlstart";
//1.加载驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//2.连接数据库,代表数据库
connection = DriverManager.getConnection(url, username, password);
//3.通知数据库开启事务,false 开启
connection.setAutoCommit(false);
String sql = "update account set money = money - 100 where name ='A'";
connection.prepareStatement(sql).executeUpdate();
String sql2 = "update account set money = money + 100 where name ='B'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();//以上两条SQL都执行成功了,就提交事务!
System.out.println("sucess");
} catch (Exception e) {
e.printStackTrace();
}
try {
connection.rollback();
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
SMBMS
数据库:
数据库SQL:
CREATE TABLE `smbms_address` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`contact` varchar(15) DEFAULT NULL COMMENT '联系人姓名',
`addressDesc` varchar(50) DEFAULT NULL COMMENT '收货地址',
`postCode` varchar(15) DEFAULT NULL COMMENT '邮编',
`tel` int(20) DEFAULT NULL COMMENT '联系人电话',
`createdBy` varchar(20) DEFAULT NULL COMMENT '创建者',
`creationDate` datetime DEFAULT NULL COMMENT '创建时间',
`modifyBy` bigint(20) DEFAULT NULL COMMENT '修改者',
`modifyDate` datetime DEFAULT NULL COMMENT '修改时间',
`userId` bigint(20) DEFAULT NULL COMMENT '用户ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `smbms_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`userCode` varchar(15) DEFAULT NULL COMMENT '用户编码',
`userName` varchar(15) DEFAULT NULL COMMENT '用户名字',
`userPassword` varchar(20) DEFAULT NULL COMMENT '用户密码',
`gender` int(10) DEFAULT NULL COMMENT '性别',
`birthday` date DEFAULT NULL COMMENT '出生日期',
`phone` varchar(20) DEFAULT NULL COMMENT '电话',
`address` varchar(30) DEFAULT NULL COMMENT '地址',
`userRole` bigint(20) DEFAULT NULL COMMENT '用户角色',
`createdBy` bigint(20) DEFAULT NULL COMMENT '创建者',
`creationDate` datetime DEFAULT NULL COMMENT '创建时间',
`modifyBy` bigint(20) DEFAULT NULL COMMENT '更新者',
`modifyDate` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `smbms_provider` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`proCode` varchar(15) DEFAULT NULL COMMENT '供应商编码',
`proName` varchar(15) DEFAULT NULL COMMENT '供应商名称',
`proDesc` varchar(50) DEFAULT NULL COMMENT '供应商描述',
`proContact` varchar(15) DEFAULT NULL COMMENT '供应商联系人',
`proPhone` varchar(20) DEFAULT NULL COMMENT '供应商电话',
`proAddress` varchar(30) DEFAULT NULL COMMENT '供应商地址',
`proFax` varchar(20) DEFAULT NULL COMMENT '供应商传真',
`createdBy` bigint(20) DEFAULT NULL COMMENT '创建者',
`creationDate` datetime DEFAULT NULL COMMENT '创建时间',
`modifyBy` bigint(20) DEFAULT NULL COMMENT '更新者',
`modifyDate` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `smbms_role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`roleCode` varchar(30) DEFAULT NULL COMMENT '角色编码',
`roleName` varchar(15) DEFAULT NULL COMMENT '角色名称',
`createdBy` bigint(20) DEFAULT NULL COMMENT '创建者',
`creationDate` datetime DEFAULT NULL COMMENT '创建时间',
`modifyBy` bigint(20) DEFAULT NULL COMMENT '更新者',
`modifyDate` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `smbms_bill` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`billCode` varchar(30) DEFAULT NULL COMMENT '账单编码',
`productName` varchar(20) DEFAULT NULL COMMENT '商品名称',
`productDesc` varchar(50) DEFAULT NULL COMMENT '商品描述',
`productUnit` varchar(60) DEFAULT NULL COMMENT '商品单位',
`productCount` decimal(20,2) DEFAULT NULL COMMENT '商品数量',
`totalPrice` decimal(20,2) DEFAULT NULL COMMENT '总金额',
`isPayment` int(10) DEFAULT NULL COMMENT '是否支付',
`providerId` int(100) DEFAULT NULL COMMENT '供应商ID',
`createdBy` bigint(20) DEFAULT NULL COMMENT '创建者',
`creationDate` datetime DEFAULT NULL COMMENT '创建时间',
`modifyBy` bigint(20) DEFAULT NULL COMMENT '更新者',
`modifyDate` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
项目如何搭建?
考虑使用不使用Maven?依赖,jar
项目搭建准备工作
1.搭建一个maven web项目
2.配置Tomcat
3.测试项目是否能够跑起来
4.导入项目中会遇到的jar包:
jsp,servlet,mysql驱动,jstl,stand…
5.创建项目包结构
6.编写实体列;
ORM映射:表-类映射
7.编写基础公共类
1.数据库配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8
username=root
password=123456
2.编写数据库的公共类
package com.kunag.dao;
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[] params,ResultSet resultSet,PreparedStatement preparedStatement) throws SQLException {
//预编译的SQL在后面直接执行就可以了
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
//setObject,占位符从1开始,但是我们的数组从0 开始!
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 {
//预编译的SQL在后面直接执行就可以了
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
//setObject,占位符从1开始,但是我们的数组从0 开始!
preparedStatement.setObject(i+1,params[i]);
}
int updateRows = preparedStatement.executeUpdate();
return updateRows;
}
public static boolean closeResources(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.编写字符编码过滤器
8.导入静态资源:https://pan.baidu.com/s/12MmpF9msJVjLT1U77XYfRw 提取码:11fv
登录功能实现
1.编写前端页面
2.设置首页
<!--设置欢迎页面-->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
3.编写dao层用户登录的接口
//得到要登录的用户
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 = null;
if (connection != null) {
String sql = "select * from smbms_user where userCode=?";
Object[] params = {userCode};
rs = BaseDao.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.setCreateBy(rs.getInt("createBy"));
user.setCreationDate(rs.getTimestamp("creationDate"));
user.setModifyBy(rs.getInt("modifyBy"));
user.setModifyDate(rs.getTimestamp("modifyDate"));
}
BaseDao.closeResources(null, pstm, rs);
}
return user;
}
}
5.业务层接口
public interface UserService {
//用户登录
public User login(String userCode,String password);
}
6.业务层实现类
public class UserServiceImpl implements UserService{
//业务层都会调用dao层,所以我们要引入Dao层;
private UserDao userDao;
public UserServiceImpl(){
userDao = new UserDaoImpl();
}
public User login(String userCode, String password) {
Connection connection = null;
User user = null;
try {
connection = BaseDao.getConnection();
//通过业务层调用对应的具体的数据库操作
user = userDao.getLoginUser(connection, userCode);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.closeResources(connection,null,null);
}
return user;
}
}
7.编写Servlet
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.kunag.servlet.user.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
9.测试访问,确保以上功能成功!
登录功能优化
注销功能:
思路:移除Session,返回登录页面
public class LoginoutServlet 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);
}
}
注册xml
<servlet>
<servlet-name>LoginoutServlet</servlet-name>
<servlet-class>com.kunag.servlet.user.LoginoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginoutServlet</servlet-name>
<url-pattern>/jsp/logout.do</url-pattern>
</servlet-mapping>
登录拦截优化
编写一个过滤器,并注册
public class SysFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//过滤器,从Session中获得用户。
User user = (User) request.getSession().getAttribute(Constants.USER_SESSION);
if (user==null){//已经被移除或者注销了,或者未登录
response.sendRedirect("/smbms/error.jsp");
}else {
chain.doFilter(req,resp);
}
}
public void destroy() {
}
}
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.kunag.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/jsp/*</url-pattern>
</filter-mapping>
测试,登录,注销,权限,都要保证OK!
密码功能修改
1.导入前端素材
<li><a href="${pageContext.request.contextPath }/jsp/pwdmodify.jsp">密码修改</a></li>
2.写项目,建议从底层向上写
3.UserDao 接口
//修改当前用户密码
public int updatePwd(Connection connection,int id,int password)throws SQLException;
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 = BaseDao.execute(connection, pstm, sql, params);
BaseDao.closeResources(null,pstm,null);
}
return execute;
}
5.UserService层
//根据用户ID修改密码
public boolean updatePwd(int id,int pwd);
6.UserService实现类
public boolean updatePwd(int id, int pwd) {
Connection connection = null;
boolean flag = false;
try {
connection = BaseDao.getConnection();
if (userDao.updatePwd(connection,id,pwd)>0){
flag = true;
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
BaseDao.closeResources(connection,null,null);
}
return flag;
}
7.Servlet记得实现复用,需要提取出方法!
@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);
}
}
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 && newpassword!=null && newpassword.length()!=0){
// if (o!=null && !StringUtils.isNullOrEmpty(newpassword)){
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();
}
}
8.测试
优化密码修改使用Ajax;
1.阿里巴巴的fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.4</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");
boolean flag = false;
//if (o!=null && newpassword!=null && newpassword.length()!=0){
if (o!=null && !StringUtils.isNullOrEmpty(newpassword)){
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中有用户的密码
private void pwdmodify(HttpServletRequest req, HttpServletResponse resp) {
//从Session里面拿ID;
Object o = (User) req.getSession().getAttribute(Constants.USER_SESSION);
String oldpassword = req.getParameter("oldpassword");
//万能的Map
Map<String, String> resultMap = new HashMap<String,String>();
if (o==null){//session过期了,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();
//JSONArray 阿里巴巴的JSON工具类,转换格式
/*
resultMap = ["result","sessionerror","result","error"]
Json格式: {key,value}
*/
writer.write(JSONArray.toJSONString(resultMap));
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
3.测试
用户管理实现
思路:
1.导入分页的工具类
2.用户列表页面导入
userlist.jsp rollpage.jsp
1.获取用户数量
1.UserDao
//根据用户名或者角色查询用户总数
public int getUserCount(Connection connection,String username,int userRole)throws SQLException;
2.UserDaoImpl
//根据用户名或者角色查询用户总数
public int getUserCount(Connection connection, String username, int userRole) throws SQLException {
PreparedStatement pstm = null;
ResultSet rs = null;
int count = 0;
if (connection!=null){
StringBuffer sql = new StringBuffer();
sql.append("select count(1) as count from smbms_user u,smbms_role r\n" +
"where u.userRole = r.id");
ArrayList<Object> list = new ArrayList<Object>();//存放我们的参数
if (!StringUtils.isNullOrEmpty(username)){
sql.append(" and u.userName like ?");
list.add("%"+username+"%");//index:0
}
if (userRole>0){
sql.append(" and u.userRole = ?");
list.add(userRole);//index:1
}
//怎么把list转换为数组
Object[] params = list.toArray();
System.out.println("UserDaoImpl->getUserCount"+sql.toString());//输出最后完整的SQL语句
rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
if (rs.next()){
count = rs.getInt("count");//从结果集中获得最终的数量
}
BaseDao.closeResources(null,pstm,rs);
}
return count;
}
3.UserService
//查询记录数
public int getUserCount(String username,int userRole);
4.UserServiceImpl
//查询记录数
public int getUserCount(String username, int userRole) {
Connection connection =null;
int count = 0;
try {
connection = BaseDao.getConnection();
count = userDao.getUserCount(connection,username,userRole);
} catch (SQLException e) {
e.printStackTrace();
}
finally {
BaseDao.closeResources(connection,null,null);
}
return count;
}
@Test
public void test(){
UserServiceImpl userService = new UserServiceImpl();
int userCount = userService.getUserCount(null, 1);
System.out.println(userCount);
}
2.获取用户列表
1.userDao
//通过条件查询-userlist
public List<User> getUserList(Connection connection,String username,int userRole,int currentPageNo,int pageSize)throws SQLException;
2.userDaoImpl
public List<User> getUserList(Connection connection, String username, int userRole, int currentPageNo, int pageSize) throws SQLException {
// TODO Auto-generated method stub
PreparedStatement pstm = null;
ResultSet rs =null;
List<User> userList = new ArrayList<User>();
if (connection!=null){
StringBuffer sql = new StringBuffer();
sql.append("select u.*,r.RoleName as userRoleName from smbms_user u,smbms_role r where u.userRole = r.id");
ArrayList<Object> list = new ArrayList<Object>();
if (!StringUtils.isNullOrEmpty(username)){
sql.append(" and u.username like ?");
list.add("%"+username+"%");
}
if (userRole>0){
sql.append(" and u.userRole = ?");
list.add(userRole);
}
sql.append(" order by creationDate DESC limit ?,?");
currentPageNo = (currentPageNo-1)*pageSize;
list.add(currentPageNo);
list.add(pageSize);
Object[] params = list.toArray();
System.out.println("sql---->"+sql.toString());
rs = BaseDao.execute(connection, pstm, rs, sql.toString(), params);
while (rs.next()){
User user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setGender(rs.getInt("gender"));
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setUserRole(rs.getInt("userRole"));
user.setUserRoleName(rs.getString("userRoleName"));
userList.add(user);
}
BaseDao.closeResources(null,pstm,rs);
}
return userList;
}
3.userService
//根据条件查询用户列表
public List<User> getUserList(String queryUserName,int queryUserRole,int currentPageNo,int pageSize)
4.userServiceImpl
public List<User> getUserList(String queryUserName, int queryUserRole, int currentPageNo, int pageSize) {
Connection connection =null;
List<User> userlist = null;
System.out.println("queryUserName--->"+queryUserName);
System.out.println("queryUserRole--->"+queryUserRole);
System.out.println("currentPageNo--->"+currentPageNo);
System.out.println("pageSize---->"+pageSize);
try {
connection = BaseDao.getConnection();
userlist = userDao.getUserList(connection,queryUserName,queryUserRole,currentPageNo,pageSize);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.closeResources(connection,null,null);
}
return userlist;
}
3.获取角色列表
为了我们职责统一,可以把角色的操作单独放在一个包中,和POJO类对应
RoleDao
public interface RoleDao {
//获取角色列表
public List<Role> getRoleList(Connection connection)throws SQLException;
}
RoleDaoImpl
package com.kunag.dao.role;
import com.kunag.dao.BaseDao;
import com.kunag.pojo.Role;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class RoleDaoImpl implements RoleDao{
//获取角色列表
public List<Role> getRoleList(Connection connection) throws SQLException {
PreparedStatement pstm = null;
ResultSet resultSet = null;
ArrayList<Role> roleArrayList = new ArrayList<Role>();
if (connection!=null){
String sql = "select * from smbms_role";
Object[] params = {};
resultSet = BaseDao.execute(connection, pstm, resultSet, sql, params);
while (resultSet.next()){
Role _role = new Role();
_role.setId(resultSet.getInt("id"));
_role.setRoleCode(resultSet.getString("roleCode"));
_role.setRoleName(resultSet.getString("roleName"));
roleArrayList.add(_role);
}
BaseDao.closeResources(null,pstm,resultSet);
}
return roleArrayList;
}
}
RoleService
public interface RoleService {
//获取角色列表
public List<Role> getRoleList() ;
}
RoleServiceImpl
package com.kunag.servlet.role;
import com.kunag.dao.BaseDao;
import com.kunag.dao.role.RoleDao;
import com.kunag.dao.role.RoleDaoImpl;
import com.kunag.pojo.Role;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.Callable;
public class RoleServiceImpl implements RoleService{
//引入Dao
private RoleDao roleDao;
public RoleServiceImpl() {
roleDao = new RoleDaoImpl();
}
public List<Role> getRoleList() {
Connection connection = null;
List<Role> roleList = null;
try {
connection = BaseDao.getConnection();
roleList = roleDao.getRoleList(connection);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.closeResources(connection,null,null);
}
return roleList;
}
}
4.用户显示的Servlet
1.获取用户前端的数据
2.判断请求是否执行,看参数的值判断
3.为了实现分页,需要计算出当前页面和总页面,页面大小…
4.用户列表展示
5.返回前端
//重点、难点
public void query(HttpServletRequest req, HttpServletResponse resp) {
//查询用户列表
//从前端获取数据:
String queryUserName = req.getParameter("queryname");
String temp = req.getParameter("queryUserRole");
String pageIndex = req.getParameter("pageIndex");
int queryUserRole = 0;
//获取用户列表
UserServiceImpl userService = new UserServiceImpl();
List<User> userList = null;
//第一次走这个请求,一定是第一页,页面大小是固定的
int pageSize = 5;//可以把这个写在配置文件中,方便后期修改
int currentPageNo = 1;
if (queryUserName==null){
queryUserName = "";
}
if (temp!=null && !temp.equals("")){
queryUserRole = Integer.parseInt(temp);//给查询赋值!0,1,2,3
}
if (pageIndex!=null){
currentPageNo = Integer.parseInt(pageIndex);
}
//获取用户的总数(分页:上一页,下一页的情况)
int totalCount = userService.getUserCount(queryUserName, queryUserRole);
//总页数支持
PageSupport pageSupport = new PageSupport();
pageSupport.setCurrentPageNo(currentPageNo);
pageSupport.setPageSize(pageSize);
pageSupport.setTotalCount(totalCount);
int totalPageCount = ((int)(totalCount/pageSize))+1;
// int totalPageCount = pageSupport.getTotalCount();
//控制首页和尾页
//如果页面要小于1了,就显示第一页的东西
if (totalPageCount<1){
currentPageNo = 1;
}else if (currentPageNo>totalPageCount){//当前页面大于最后一页
currentPageNo = totalPageCount;
}
//获取用户列表展示
userList = userService.getUserList(queryUserName, queryUserRole, currentPageNo, pageSize);
req.setAttribute("userList",userList);
RoleServiceImpl roleService = new RoleServiceImpl();
List<Role> roleList = roleService.getRoleList();
req.setAttribute("roleList",roleList);
req.setAttribute("totalCount",totalCount);
req.setAttribute("currentPageNo",currentPageNo);
req.setAttribute("totalPageCount",totalPageCount);
req.setAttribute("queryUserName",queryUserName);
req.setAttribute("queryUserRole",queryUserRole);
//返回前端
try {
req.getRequestDispatcher("userlist.jsp").forward(req,resp);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@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);
}else if (method.equals("pwdmodify")&&method!=null){
this.pwdmodify(req, resp);
}else if (method.equals("query")&&method!=null){
this.query(req, resp);
}
}