Java后端进阶之路: JavaWeb

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.bhtml....等等多个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页面可以动态更新,所有用户看到的都不是同一个页面
- 可以和数据库交互(数据持久化,注册,信息可以得到保存)
2.web服务器
2.1 服务端技术
ASP:
- 微软:国内最早流星的是ASP
- 在html中嵌入VB的脚本,ASP+HTML
- 在ASP开发中,基本一个页面,大量互相嵌套的业务逻辑代码,造成维护成本过高
PHP:
- PHP将开发速度很快,功能强大,跨平台,代码简单(70%,wp)
- 无法承载大访问量的情况(局限性)
JSP/Servlet
B/S 浏览与服务器
C/S 客户端与服务器
- sun公司主推的B/S架构
- 基于java语言的(所有大公司,或者一些开源的组件,都是用java写的)
- 可以承载三高的问题带来的影响
- 语法想ASP-->JSP加强市场强度
2.2web服务器
作用:接收用户的请求给予相应的响应,是一种被动操做,用来处理用户请求给用户返回响应信息
lls
微软:ASP,,windows中自带的
tomcat:
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个java初学web来说,
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。目前Tomcat最新版本为10**。**
工作3-5年可以尝试手写tomcat服务器
下载tomcat:
- 安装 and 解压
- 了解配置文件以及目录结构
- 这个东西的作用
3,tomcat
3.1安装tomcat
下载windows 64安装包
解读tomcat的文件目录
3.2启动,关闭tomcat
访问测试url:
3.3配置
核心文件:
可能遇到的问题:
1.java环境变量没有配置
2.闪退问题,需要配置兼容性
3.乱码问题要去配置文件设置
可以配置启动的端口号
- tomcat的默认端口号为:8080
- mysql:3306
- http:80
- https:443
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
可以配置主机名称
- 默认的主机名为localhost=>127.0.0.1
- 默认网站应用存放位置为:webapps
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
高难度面试题
请你谈谈网站是如何进行访问的!
-
输入一个域名:回车
-
检查本机的C:\Windows\System32\drivers\etc\hosts配置文件下有没有这个域名的映射
-
有:直接返回对应的ip地址,这个地址中有我们访问的web程序,可以直接访问
127.0.0.1 www.qingjiang.com
-
没有:上dns服务器上找,找到的话就返回,没有的话返回你的网页走丢了
-
3.tomcat文档本地地址http://localhost:8080/examples/
3.4发布web网站
- 先写网站放到tomcat/webapps/,服务器中指定的web应用文件夹下,就可以访问了
网站该有的结构
--webapps:tomcat服务器的web目录
-root
-项目名: 网站的目录名
-web-inf
-web.xml
-classes:java
-lib:web应用所依赖的jar包
-index.html
-static
css
style
js
img
HTTP协议:面试
Maven:构建工具
- Maven安装包
Servlet
- helloword
- Servlet
- 原理
4.http
4.1什么是http
Http 超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。
- 文本:html,字符串等等
- 超文本:图片,音乐,视频,定位,地图
- 端口号:80
Https:安全的
- 端口443
4.2两个时代
- http1.0
- HTTP/1.0:客户端可以与web服务器连接,只能获得一个web资源,断开连接
- http2.0
- HTTP/1.1:客户端可以与web服务器连接后,可以获得多个web资源。
4.3http请求
- 客户端---》发送请求(Requset)---》服务器
百度:
Request URL: https://www.baidu.com/ //请求地址
Request Method: GET get方法/post方法
Status Code: 200 OK 状态码:200
Remote Address: 163.177.151.110: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/post
- 请求方式: Get/post, HEAD,DELETE,put tract
- get:请求能够携带的参数比较小,大小被限制,会在浏览器的url地址栏显示数据内容,不安全,但高效。
- post:请求能够携带的参数没有限制,没有大小限制,不会在浏览器的URL地址栏显示数据内容,安全但不高效
2.消息头
Accept 告诉浏览器,它所支持的数据类型
Accept-Encoding 支持那种编码格式 gbk,utf-8,gb2312,iso8859-1(java默认编码)
Accept-Language 语言
Cache-Control 缓存控制
Connection 告诉浏览器请求完成是断开还是保持连接
HOST:主机
4.4HTTP响应
- 服务器---》响应---》客户端
百度:
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(java默认编码)
Accept-Language 语言
Cache-Control 缓存控制
Connection 告诉浏览器请求完成是断开还是保持连接
HOST:主机
Refresh:告诉客户端,多久刷新一次
Location:让网页重新定位
2.响应状态码(重点)
200:请求响应成功
3xx:请求重定向
- 重定向:你重新到我给你的新位置去
4xx:找不到资源:404
- 资源不存在:
5xx:服务器代码错误 500 502:网关错误
常见面试题:
当你的浏览器中地址栏输入地址并回车的一瞬间到页面能够展示回来,经历了什么?
5.Maven
我为什么要学习这个基数
-
在javaweb开发中,需要使用大量的jar包,我们需要去手动去导入jar包
-
如何能够让一个东西自动帮我们导入和配置这些jar包
由此,Maven诞生了!
5.1Maven项目架构管理工具
我们目前用它来方便导入jar包
Maven核心思想:约定大于配置
- 有约束,不要去违反
Maven会规定好你该如何去编写java代码,目录结构必须要按照这个规范来
5.2下载安装Maven
官网网址:https://maven.apache.org/download.cgi
下载完成后解压即可:
建议:电脑上的所有环境都放在一个文件夹下方便管理
5.3配置环境变量
在系统环境变量之中
配置如下:
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven 的目录
- 在系统的path中配置MAVEN_HOME目录 %MAVEN_HOME%\bin
5.4阿里云镜像
- 镜像:mirrors
- 作用:加速下载
- 建议使用阿里云
2 <mirror>
3 <id>nexus-aliyun</id>
4 <mirrorOf>*</mirrorOf>
5 <name>Nexus aliyun</name>
6 <url>http://maven.aliyun.com/nexus/content/groups/public</url>
7 </mirror>
5.5本地仓库repository
本地仓库,远程仓库
建立一个本地仓库:
<localRepository>D:\apache-maven-3.6.3\maven-repo</localRepository>
5.6在idea使用maven
-
启动idea
-
创建一个maven项目
-
等待项目初始化完毕
4.观察maven仓库多了什么东西
5.idea中maven设置
注意:IDEA创建成功后看一眼maven的配置,
6.到这,maven在IDEA的配置和使用就ok了
5.7创建一个普通的maven项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZfdyIk91-1648909270901)(C:\Users\doomwstcher\AppData\Roaming\Typora\typora-user-images\image-20210329144558685.png)]
5.9在idea配置tomcat
解决警告问题
必须配置,为什么会有问题,我们访问一个网站,需要指定一个文件夹的名字;
5.10pom文件
pom.xml是Maven的核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--创建项目的时候生成的配置gav-->
<groupId>com.hyc</groupId>
<artifactId>javaweb01-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>javaweb01-maven 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>javaweb01-maven</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由于约定大于配置,会出现我们之后遇到写的配置文件无法被导出或者生效的问题,
解决方案:
<!-- 配置resouce来防止我们导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
6.Servlet
6.1什么是Servlet
-
sun公司开发动态web的一门技术
-
sun公司在api中提供了一个借口叫Servlet,你想开发Servlet程序。只需要两个小步骤
- 编写一个类,实现Servlet接口
- 把开发好的java类部署到web服务器中
把实现了Servlet接口的java程序叫做Servlet
6.2 HelloServlet
Servlet接口有两个默认的实现类:httpServlet,GenericServlet
-
构建一个普通的maven项目,删掉里面的src目录,以后我们的学习就在这里面建立moudel;这个空的工程就是maven的主工程
-
关于maven父子工程的理解:
-
父项目中会有:
<modules> <module>Servlet-01</module> </modules>
子项目中会有:
<parent> <artifactId>javaweb-maven-02</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent>
-
-
Maven环境优化
- 修改web.xml为最新的
- 将Maven的结构搭建完整
-
编写一个Servlet程序
-
编写一个普通类
-
继承接口实现类
package com.hyc.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class helloServlet extends HttpServlet { //get,post只是请求实现的不同的方式,可以相互调用,应为业务逻辑都一样 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.print("Hello,servlet"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
-
-
编写Servlet的映射
为什么需要映射呢,我们写的是java程序,通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中出册我们写的Servlet,还需要给他一个浏览器访问的url
<?xml version="1.0" encoding="ISO-8859-1"?> <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_3_1.xsd" version="3.1" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to Tomcat </description> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.hyc.servlet.helloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
-
配置tomcat
配置项目发布路径
-
启动测试
6.3servlet原理
Servlet是由web服务器调用,web服务器在收到浏览器请求之后会:
6.4Mapping
-
一个servlet可以指定一个映射路径
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.hyc.servlet.helloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
一个sevlet可以指定多个映射路径
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.hyc.servlet.helloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello1</url-pattern> </servlet-mapping>
-
一个sevlet可以指定默认映射路径(尽量不要去写)
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
-
一个sevlet可以指定前缀或者是后缀映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello1/*</url-pattern> </servlet-mapping>
6.5优先级问题
指定了固有映射路径的优先级最高,如果找不到怎么办那么就会进行默认的
<!--404-->
<servlet>
<servlet-name>err</servlet-name>
<servlet-class>com.hyc.servlet.errServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>err</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
6.6ServletContext
web容器的启动时,它会为每个web程序都创建一个对应ServletContext对象,它代表了当前的web应用。
1.共享数据
在一个servlet的数据可以从另一个servlet拿到
-
共享数据
我在这个servlet中保存的数据,可以在另外一个servlet中拿到
package com.hyc.servlet; import javax.servlet.ServletContext; 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 getServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); ServletContext context = this.getServletContext(); String name =(String)context.getAttribute("username"); resp.getWriter().print(name); } }
package com.hyc.servlet; import javax.servlet.ServletContext; 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 HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("HELLO"); ServletContext Context = getServletContext(); String username = "胡宇辰"; Context.setAttribute("username",username); } }
<?xml version="1.0" encoding="ISO-8859-1"?> <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_3_1.xsd" version="3.1" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to Tomcat </description> <servlet> <servlet-name>hello</servlet-name> <servlet-class>com.hyc.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hi</url-pattern> </servlet-mapping> <servlet> <servlet-name>get</servlet-name> <servlet-class>com.hyc.servlet.getServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>get</servlet-name> <url-pattern>/get</url-pattern> </servlet-mapping> </web-app>
测试结果
2.获取初始化参数
设置初始化参数
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost/3306/mybaties</param-value>
</context-param>
读取参数
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext context = this.getServletContext();
String name =(String)context.getAttribute("username");
String url =(String)context.getInitParameter("url");
resp.getWriter().print( url );
3.请求转发
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext context = this.getServletContext();
context.getRequestDispatcher("/get").forward(req,resp);
}
4.读取资源文件
properties
- 在java目录下新建properties文件
- 在resouesce目录下新建properties文件
发现都会打包到同一个路径下:classes,我们俗称这个路径为classpath
思路:需要一个文件流
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
ServletContext context = this.getServletContext();
InputStream is = context.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);
username=root
password = 123456
访问测试即ok
6.6 HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过HTTP协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest,通过这个HttpServletRequest的方法,获得客户端的所有信息
1.获取前端传递参数,并且请求转发
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("pwd");
String[] hobbys = req.getParameterValues("hobby");
System.out.println("====================");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
System.out.println("====================");
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
请求转发和重定向的区别
6.7HttpServletResponse
响应:web服务器接受到客户端的http请求,会针对这个请求,分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要给客户端一些响应信息:找到HttpServletResponse
1.简单分类
负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void 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,常见应用
-
向浏览器输出消息
-
下载文件,上传文件
- 要获取下载文件的路径
- 下载的文件名是什么?
- 设置让浏览器支持下载我需要的文件
- 获取下载文件的输入流
- 创建缓冲区
- 获取outinputstream对象
- 将fileoutinputstream写入buffer缓冲区
- 使用outinputstream将缓冲区中的数据输出到客户端
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
String realPath ="D:\\javaweb-maven-02\\response\\target\\classes\\梦.jpg";
//2. 下载的文件名是什么?
System.out.println("下载文件路径"+realPath);
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[] buffter = new byte[1024];
//6. 获取outinputstream对象
ServletOutputStream out = resp.getOutputStream();
//7. 将fileoutinputstream写入buffer缓冲区, 使用outinputstream将缓冲区中的数据输出到客户端
while ((len = in.read(buffter))>0){
out.write(buffter,0,len);
}
//关闭
in.close();
out.close();
}
3.验证码功能
验证码怎么来的
- 前端实现
- 后端实现,需要用到java的图片类来实现
4.实现重定向
一个web资源收到客户端请求后,他会通知客户端去访问另一个web资源这个过程叫做重定向
常见场景:
- 用户登录
void sendRedirect(String var1) throws IOException;
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// resp.setHeader("location","/r/img");
// resp.setStatus(resp.SC_MOVED_TEMPORARILY);
resp.sendRedirect("/r/img");
}
面试题:请你聊聊重定向和转发的区别?
相同点
- 页面都会实现跳转
不同点
- 请求转发的时候,url不会产生变化
- 重定向时候,url地址栏会产生变化
7.cookie,session
7.1会话
会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话
**有状态会话:**一个同学来过教室,下次再来教师,我们会知道这个同学之前来过教师,称之为有状态会话
如何证明你是学生?
对象: 你 学校
- 发票 学校给你的发票
- 学校登记 学校标记你来过了
一个网站怎么证明你来过?
客户端 服务器
- 服务器给客户端一个信件,客户端下次访问服务端带上信件就可以了;cookie
- 服务器登记你来过了,下次你来的时候匹配你;session
7.2保存会话的两种技术
cookie
- 客户端技术(响应,请求)
session
- 服务器技术利用这个技术,我们呢可以保存用户的会话信息,我们可以把信息或者数据放在session中
常见场景:网站登录之后你下次不用在登录了,第二次访问直接就上去了
7.3Cookie
- 从请求中拿到cookie信息,
- 服务器响应给客户端cookie
Cookie[] cookies = req.getCookies();//返回数组说明cookie存在多个
cookie.getName()//获取cookie的名字
cookie.getValue()//获得cookie中的value
new Cookie()//设置cookie的有效期
cookie.setMaxAge(24*60*60);//设置有效期
resp.addCookie(cookie)//响应给客户端一个cookie
cookie:一般会存在本地的用户目录下appdata:
一个网站的cookie是否存在上线,细节问题
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器多个cookie,最多存放20个cookie
- Cookie的大小有限制
- 300个cookie浏览器上限
删除cookie
- 不设置有效期,关闭浏览器,自动失效;
- 设置有效时间为0
编码解码:
URLDecoder.decode(cookie.getValue(),"utf-8")//解码
URLEncoder.encode("请将","utf-8")//编码
7.4session(重点)
什么是session:
- 服务器会给每一个用户(浏览器)创建一个session
- 一个session独占一个浏览器,只要浏览器没有关闭,这个session就存在
- 用户登陆之后,整个网站都可以访问 -->保存用户信息,保存购物车信息
<!-- 设置session默认的失效时间-->
<session-config>
<!--15分钟后session自动失效-->
<session-timeout>15</session-timeout>
</session-config>
session和cookie的区别:
- Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
- Session把用户的数据写到用户独占的session中,服务器端保存(保存重要的消息,减少服务器资源的浪费)
- session对象由服务器创建
使用场景:
- 保存一个用户登陆的信息
- 购物车信息;
- 在整个网站中经常会使用的数据
//创建session
package com.hyc.servlet;
import com.hyc.pojo.persion;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class sessionDemo extends HttpServlet {
@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");
HttpSession session = req.getSession();
session.setAttribute("name",new persion("hyc",12)) ;
String id = session.getId();
if (session.isNew()) {
resp.getWriter().write("session创建成功:"+ id);
}else {
resp.getWriter().write("session已经在服务器存在了:"+id);
}
//session的创建的时做了什么事情
Cookie cookie = new Cookie("JSESSIONID",id);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
//拿到session
package com.hyc.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import com.hyc.pojo.persion;
public class sessionDemo02 extends HttpServlet {
@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");
HttpSession session = req.getSession();
persion name = (persion) session.getAttribute("name");
System.out.println(name.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
//删除和注销session
package com.hyc.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class Sessiondemo03 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.removeAttribute("name");
//手动注销session
session.invalidate();
}
}
8.JSP
8.1 什么是jsp
java Server pages:java服务器端页面,也和servlet一样,用于开发动态web
最大的特点:
-
写jsp就像是写html
-
区别:
-
HTML只给用户提供静态的数据
-
jsp页面中可以嵌入java代码,为用户提供动态数据
-
-
jsp九个内置对象
- request:封装客户端的请求,其中包含来自GET或POST请求的参数;
-
response:封装服务器对客户端的响应;
- pageContext:通过该对象可以获取其他对象;
-
session:封装用户会话的对象;
- application:封装服务器运行环境的对象;
-
out:输出服务器响应的输出流对象;
- config:Web应用的配置对象;
-
page:JSP页面本身(相当于Java程序中的this);
- exception:封装页面抛出异常的对象。
8.2jsp原理
思路:jsp到底如何执行
-
代码层面没有任何问题
-
服务器内部工作
tomcat中有一个work目录
idea中使用tomcat的话会在idea的tomcat生成一个work目录
C:\Users\doomwstcher\AppData\Local\JetBrains\IntelliJIdea2020.2\tomcat\Unnamed_javaweb-session-cookie\work\Catalina\localhost\javaweb_session_cookie_war\org\apache\jsp
发现页面转变成了java程序
浏览器向服务器发送请求。不管访问什么资源,其实都是在访问servlet!
jsp最终也会被转换成为一个jsp类
jsp本质是一个servlet
//初始化
public void _jspInit() {
}
//销毁
public void _jspDestroy() {
}
//jsp的service
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
-
判断请求
-
内置一些对象
final javax.servlet.jsp.PageContext pageContext;//页面上下文 javax.servlet.http.HttpSession session = null;//session final javax.servlet.ServletContext application;//applicationcontext final javax.servlet.ServletConfig config;//配置 javax.servlet.jsp.JspWriter out = null;//out final java.lang.Object page = this;//当前 javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; HttpServletRequest//请求 HttpServletResponse//响应
-
输出页面前增加的代码
response.setContentType("text/html");//设置相应页面类型 pageContext = _jspxFactory.getPageContext(this, request, response,null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;
-
以上这些对象可以直接在jsp中使用
在jsp页面中:
只要是java代码就会原封不动的输出,
如果是html代码就会被转换为 out.write("\r\n");这样的格式输出到前端
8.3JSP基础语法
任何语言都有自己的语法,java中有。。,jsp作为java技术的一种应用,他拥有一些自己的扩充的语法(了解,知道即可),java的所有语法他都支持!
JSP表达式
<%-- JSP表达式
作用:用来将程序的输出结果,输出到客户端
<%=变量或者表达式%>
--%>
JSP脚本片段
<%
int sun=0;
for (int i = 0; i <5 ; i++) {
sun+=i;
}
out.print("<h1>sun="+sun+"</h1>");
%>
脚本片段的再实现
<%-- 在代码中嵌入html元素--%>
<%
for (int i = 0; i <5 ; i++) {
%>
<h1>狂神<%= i%></h1>
<%
}
%>
jsp声明
<%!
static {
System.out.println("loading Servlet!");
}
private int var = 0;
public void hu(){
System.out.println("进入了方法hu");
}
%>
JSP声明:会变一到JSP生成java的类中!其他的,就会被生成到 _jspService方法中,在jsp中嵌入java代码即可!
<%%>片段
<=%%>表达式
<%!%>定义全局方法
<%--注释--%>
JSP的注释,不会在客户端显示,html就会!
8.4JSP指令
<%@%>
<%@include file=""%>包含文件
JSP标签
<%@ include file="common/HEADER.jsp"%>
<h1>我是主题页面</h1>
<%@ include file="common/footer.jsp"%>
<%--jsp标签--%>
<jsp:include page="common/HEADER.jsp"/>
<h1>我是第二个</h1>
<jsp:include page="common/footer.jsp"/>
<%--@ include会将两个页面合二为一--%>
<%@ include file="common/HEADER.jsp"%>
<h1>我是主题页面</h1>
<%@ include file="common/footer.jsp"%>
<%--jsp标签
jsp:include;拼接页面,本质是三个页面
--%>
<jsp:include page="common/HEADER.jsp"/>
<h1>我是第二个</h1>
<jsp:include page="common/footer.jsp"/>
8.5九大内置对象
- PageContext 存东西
- Request 存东西
- Response
- Session 存东西
- Application 【ServletContext】存东西
- config 【ServletConfig】
- page 几乎不用
- execption 和java异常一样
pageContext.setAttribute("name1","h1");//保存的数据只在一个页面中有效
request.setAttribute("name2","h2");//保存的数据在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","h3");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","h4");//保存数据只在服务器中有效,从打开服务器到关闭服务器
%>
request : 客户端向服务器发送请求,产生的数据,用户看完就没用管理,比如:新闻、用户看完就没用的
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车;
application:客户端向服务器发送请求,产生的数据,一个用户用完了,其他用户还可能使用,比如:聊天数据;
8.6、JSP标签,JSTL标签,EL表达式
<!-- 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>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
**EL表达式:${}
- 获取数据
- 执行运算
- 获取web开发的常用对象
- 调用java方法
JSP标签
<%--<jsp:include>--%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="kuangshen"/>
<jsp:param name="age" value="18"/>
</jsp:forward>
JSTL标签
JSTL标签库的使用就是为了弥补HTML标签的不足;
它自定义了许多的标签,可以供我们使用,标签的功能和java代码的一样
核心标签(要求掌握部分即可)
JSTL标签使用步骤:
- 引入对应的taglib
- 使用其中的方法
- 在tomcat中也需要引入jstl的包否则会报错,jstl解析错误
c:if
<h4>
if测试
</h4>
<hr>
<form action="coreif.jsp" method="get">
<%-- el表达式获取表单中的数据
${parom.参数}
--%>
<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="${param.username}"></c:out>
c:choose
<c:set var="score" value="91"/>
<c:choose>
<c:when test="${score>90}">你的成绩还行</c:when>
<c:when test="${score>80}">你的成绩不行</c:when>
<c:when test="${score>60}">你退学吧</c:when>
</c:choose>
c:foreach
<c:forEach var="people" items="${list}" >
<c:out value="${people}"></c:out><br>
</c:forEach>
<hr>
<c:forEach var="people" items="${list}" begin="1" end="3" step="2">
<c:out value="${people}"></c:out><br>
</c:forEach>
格式化标签
SQL标签
XML 标签
9.0、javaBean
实体类
javaBean有特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法;
一般用来和数据库的字段做映射 ORM
ORM:对象关系映射
- 表-->类
- 字段-->属性
- 行记录 ---->对象
people表
id | name | age | address |
---|---|---|---|
1 | laozi1 | 3 | 深圳 |
2 | laozi2 | 14 | 深圳 |
3 | laozi3 | 14 | 深圳 |
class Perple{
private int id;
private String name;
private int age;
private String address;
}
class a{
new Perple(1,"laozi1",3,"深圳");
new Perple(2,"laozi2",14,"深圳");
new Perple(3,"laozi3",14,"深圳");
}
- 过滤器
- 文件上传
- 邮件发送
- 复习jdbc:如何使用jdbc,增删改查,事务
10.三层架构
什么是mvc: model view Controller 模型 视图,控制器
10.1早些年的架构

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

model
- 业务处理:业务逻辑(service)
- 数据持久层(CRUD)(DAO)
view
- 展示数据
- 提供链接发起Servlet请求(a,form.img..)
Controller(Serlet)
- 接收用户请求:(req:请求参数,session信息.....)
- 交给业务层处理对应代码
- 控制视图的跳转
登陆-->接受用户的登录请求--->处理用户请求(获取用户登陆的参数,username,password)---->交给业务层处理登陆业务,判断用户名密码是否正确:事务--->DAO查询用户名和密码是否正确--->数据库
11、Filter
Filter:过滤器,用来过滤网站的数据;
- 处理中文乱码
- 登陆验证
1.导包
不要搞错包
2实现Filter接口
package com.hyc.filter;
import javax.servlet.*;
import java.io.IOException;
public class ChatcterEncodingFilter implements Filter {
//初始化:web服务器启动的就以及初始化了,随时等待过去对象出现
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("ChatcterEncodingFilter已经初始化");
}
// 在过滤中的所有代码,在过滤特定请求的时候都会执行
// 必须要让过滤器找到同行
// 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("执行前");
chain.doFilter(request,response);//让请求继续往前走,如果不写的程序到这里停止
System.out.println("执行后");
}
//销毁
public void destroy() {
System.out.println("ChatcterEncodingFilter销毁");
}
}
3在web.xml中配置Filter
<filter>
<filter-name> ChatcterEncodingFilter</filter-name>
<filter-class>com.hyc.filter.ChatcterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ChatcterEncodingFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
12.监听器
实现一个监听器的接口;(有无数种)
-
编写一个监听器
package com.hyc.listner; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class OnlineListner implements HttpSessionListener { //创建session监听,看你的一举一动 //一旦创建session就会触发一个事件 public void sessionCreated(HttpSessionEvent se) { System.out.println(se.getSession().getId()); ServletContext ctx = se.getSession().getServletContext(); Integer oc =(Integer) ctx.getAttribute("OnlineCount"); if (oc==null){ oc = new Integer(1); }else { int count = oc.intValue(); oc = new Integer(count+1); } ctx.setAttribute("OnlineCount",oc); } public void sessionDestroyed(HttpSessionEvent se) { ServletContext ctx = se.getSession().getServletContext(); Integer oc =(Integer) ctx.getAttribute("OnlineCount"); if (oc==null){ oc = new Integer(0); }else { int count = oc.intValue(); oc = new Integer(count-1); } ctx.setAttribute("OnlineCount",oc); } /* * 销毁session * 手动销毁 * 自动销毁 * */ }
-
在web.xml中注册监听器
<!-- 注册监听器-->
<listener>
<listener-class>com.hyc.listner.OnlineListner</listener-class>
</listener>
3,看情况准备
13、过滤器和监听器的常见应用
监听器:GUI编程中经常使用;
package com.hyc.listner;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class Testpanel {
public static void main(String[] args) {
Frame frame = new Frame("中秋快乐");//一个窗体
Panel pa1 = new Panel(null);//面板
frame.setLayout(null);
frame.setBounds(300,300,500,500);
frame.setBackground(new Color(0,0,255));
pa1.setBounds(50,50,300,300);
pa1.setBackground(new Color(255,0,0));
frame.add(pa1);
frame.setVisible(true);
//监听事件:关闭时间
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("关闭");
System.exit(0);
}
}
);
用户登陆之后才能进入首页,用户注销之后就不能进入主页了!
登记权限问题:什么权限进入什么页面
-
用户登陆后,向session中放入用户的数据
-
进入主页的时候判断用户是否已经登陆
HttpServletRequest request1 = (HttpServletRequest) request; HttpServletResponse response1 = (HttpServletResponse) response; Object user_session = request1.getSession().getAttribute(Coestext.USER_SESSION); if (user_session==null){ response1.sendRedirect("/jf/error.jsp"); } chain.doFilter(request,response);
14、jdbc(复习)
什么是JDBC: java连接数据库
新建数据库
添加数据库依赖
<dependencies>
<dependency>
<!-- mysql的驱动-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
idea连接数据库
jdbc固定六部曲,(固定步骤)
- 加载驱动
- 连接数据库,代表数据库
- 向数据库发送sql的接口,做增删改查(CRUD)
- 编写sql(根据业务,编写不同sql)
- 执行SQL
- 关闭连接
String url = "jdbc:mysql://localhost:3306/peojdbc?userUnicode=true&charcterEncoding=utf-8";
String username = "root";
String password = "root";
//1加载驱动
Class.forName("java.sql.Driver");
//2连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement();
//3编写sql
String sql = "select *\n" + "from users ;";
//4返回结果集
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
System.out.println("id"+rs.getInt("id"));
System.out.println("name"+rs.getString("name"));
}
//5先开后关
statement.close();
connection.close();
PreparedStatement安全接口的复习
package com.hyc.test;
import java.sql.*;
public class TestJdbc {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
String url = "jdbc:mysql://localhost:3306/peojdbc?userUnicode=true&charcterEncoding=utf-8";
String username = "root";
String password = "root";
//1加载驱动
Class.forName("java.sql.Driver");
//2连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "insert into users (id, name, password, email, birthday) values (?,?,?,?,?);";
PreparedStatement pst = connection.prepareStatement(sql);
//3编写sql
String sql1 = "select *\n" + "from users ;";
pst.setInt(1,4);
pst.setString(2,"hjj");
pst.setString(3,"123456");
pst.setString(4,"一二三@qq.com");
pst.setDate(5,new Date(new java.util.Date().getTime()));
//4返回结果集
int i = pst.executeUpdate();
if (i>=0){
System.out.println("添加成功");
}
ResultSet rs = pst.executeQuery(sql1);
while (rs.next()){
System.out.println("id"+rs.getInt("id"));
System.out.println("name"+rs.getString("name"));
}
//5先开后关
pst.close();
connection.close();
}
}
事务
要么都成功,要么都失败
ACID原则:保证数据安全
开始事务
事务提交 comit()
事务回滚 rollback()
关闭事务
经典例子
a:1000
b:1000
a(900)---》100---》b(1100)
junit单元测试
依赖
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
测试成功是这样的
package com.hyc.test;
import org.junit.jupiter.api.Test;
public class testjunit {
@Test()
public void test(){
System.out.println("hello");
}
}
测试失败是这样的
接下来用junit来测试数据库中的事务
package com.hyc.test;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class testjunit {
@Test()
public void test() {
String url = "jdbc:mysql://localhost:3306/peojdbc?userUnicode=true&charcterEncoding=utf-8";
String username = "root";
String password = "root";
Connection connection = null;
//1加载驱动
try {
Class.forName("java.sql.Driver");
//2连接数据库,代表数据库
connection = DriverManager.getConnection(url, username, password);
//3.通知数据库开启事务
connection.setAutoCommit(false);
String sql = "update accout\n" +
"set moeny = moeny-100\n" +
"where name =\"a\";";
connection.prepareStatement(sql).executeUpdate();
// int i = 1/0;
String sql2 = "update accout\n" +
"set moeny = moeny+100\n" +
"where name =\"b\";";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();//以上sql全执行成功了就提交事务
System.out.println("success");
} catch (Exception e) {
try {
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
smbms项目
数据库:
项目如何搭建:
考虑使用不使用maven?依赖?jar包
项目搭建准备工作
-
搭建maven项目
-
配置tomcat
-
测试项目是否能够跑起来
-
导入项目会遇到的依赖jar包
- jsp.Servlet.mysql,jsp
-
创建项目结构
-
编写实体类
- orm: 表映射
-
编写基础公共类
-
数据库配置文件
driver=com.mysql.jdbc.Driver url =jdbc:mysql://localhost:3306?useUnicode=true&charcterEncoding=utf-8 username = root password = root
-
编写数据库公共类
package com.hyc.dao; 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 (Exception e){ e.printStackTrace(); } driver = properties.getProperty("driver"); url = properties.getProperty("url"); password = properties.getProperty(" password"); username = properties.getProperty("username"); } public static Connection getconnection(){ Connection conn = null; try { Class.forName(driver); conn = DriverManager.getConnection(url,username,password); } catch (Exception e) { e.printStackTrace(); } return conn; } //查询公共类 //预编译的sql我们直接执行就好了 public static ResultSet execute(Connection conn,String sql,Object[] params,PreparedStatement pst,ResultSet rs){ try { pst = conn.prepareStatement(sql); for (int i = 0; i < params.length ; i++) { //pst.setObject占位符是从1开始的,但是我们的数组是从0开始的 pst.setObject(i+1,params[i]); } rs = pst.executeQuery(); } catch (SQLException throwables) { throwables.printStackTrace(); } return rs; } //增删改公共方法 public static int execute(Connection conn,String sql,Object[] params,PreparedStatement pst){ int UpdateRows = 0; try { pst = conn.prepareStatement(sql); for (int i = 0; i < params.length ; i++) { //pst.setObject占位符是从1开始的,但是我们的数组是从0开始的 pst.setObject(i+1,params[i]); } UpdateRows = pst.executeUpdate(); } catch (SQLException throwables) { throwables.printStackTrace(); } return UpdateRows; } public static boolean closeResoure(Connection conn,PreparedStatement pst ,ResultSet rs) { boolean flag = true; if (conn!=null){ try { conn.close(); //GC回收 conn=null; } catch (SQLException throwables) { throwables.printStackTrace(); flag = false; } } if (pst!=null){ try { pst.close(); //GC回收 pst=null; } catch (SQLException throwables) { throwables.printStackTrace(); flag = false; } } if (rs!=null){ try { rs.close(); //GC回收 rs=null; } catch (SQLException throwables) { throwables.printStackTrace(); flag = false; } } return flag; } }
-
编写过滤器
-
-
导入静态资源
登陆功能实现
-
编写前端也眯娜
-
设置欢迎页面
<welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-lit>
-
编写dao层得到用户登陆的接口
public user getLoginUser(Connection conn, String usercode);
-
编写dao得到用户登陆的接口实现
package com.hyc.dao.user; import java.sql.*; import com.hyc.dao.BaseDao; import com.hyc.pojo.user; import java.sql.Connection; public class UserDaoImpl implements UserDao { @Override public user getLoginUser(Connection conn, String usercode) { PreparedStatement pst = null; ResultSet rs = null; user user = null; if (conn != null) { String sql = "select * from smbms_user where userCode=?"; Object[] params = {usercode}; try { rs = BaseDao.execute(conn,sql,params,pst,rs); if (rs.next()){ user = new user(); user.setId(rs.getInt("id")); user.setUserCode(rs.getString("userCode")); user.setUserName(rs.getString("userName")); user.setUserPassword(rs.getString("userPassword")); user.setGender(rs.getInt("gender")); user.setBirthday(rs.getDate("birthday")); user.setPhone(rs.getString("phone")); user.setAddress(rs.getString("address")); user.setUserRole(rs.getInt("userRole")); user.setCreatedBy(rs.getInt("createdBy")); user.setCreationDate(rs.getTimestamp("creationDate")); user.setModifyBy(rs.getInt("modifyBy")); user.setModifyDate(rs.getTimestamp("modifyDate")); } BaseDao.closeResoure(null,pst,rs); }catch (Exception e){ } } return user; } }
-
编写业务层
public interface UserService { public user login(String userCode,String password); }
-
业务层实现类
public user login(String userCode, String password) { Connection conn = null; user user = null; try{ conn = BaseDao.getconnection(); user = userDao.getLoginUser(conn,userCode); }catch (Exception e){ e.printStackTrace(); }finally { BaseDao.closeResoure(conn,null,null); } return user; }
-
servlet编写
package com.hyc.servlet.user; import com.hyc.pojo.user; import com.hyc.service.user.UserService; import com.hyc.service.user.UserServiceImpl; import com.hyc.util.Constaets; 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 LoginSerlvet extends HttpServlet { //Servlet:控制层调用业务层代码 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("进入servlet"); //获取用户名和密码 String uc = req.getParameter("userCode"); String upwd = req.getParameter("userPassword"); UserServiceImpl userService = new UserServiceImpl(); user user = userService.login(uc,upwd); if (user!=null){ System.out.println("查有此人"); req.getSession().setAttribute(Constaets.USER_SEESION,user); //跳转到内部主页 resp.sendRedirect("/smbms/jsp/frame.jsp"); }else { //查无此人转发会登陆页面 req.setAttribute("error","用户名或者密码不正确"); req.getRequestDispatcher("login.jsp").forward(req,resp); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } }
-
注册servlet
<!-- servlet--> <servlet> <servlet-name>login</servlet-name> <servlet-class>com.hyc.servlet.user.LoginSerlvet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping>
9.优化登陆选项,拦截登陆优化
编写过滤器
package com.hyc.filter; import com.hyc.pojo.user; import com.hyc.util.Constaets; import javax.servlet.*; import javax.servlet.http.HttpServlet; 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 servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest servletRequest1 = (HttpServletRequest) servletRequest; HttpServletResponse servletResponse1 = (HttpServletResponse) servletResponse; user user = (user)servletRequest1.getSession().getAttribute(Constaets.USER_SEESION); if (user == null) { servletResponse1.sendRedirect("/smbms/error.jsp"); }else { filterChain.doFilter(servletRequest,servletResponse); } } @Override public void destroy() { } }
测试,登陆,注销,权限都要ok
密码修改
-
导入素材
-
写项目,从底层往上面写
-
编写userdao
//修改密码 @Override public int updateuser(Connection conn, int id, String password) { String sql = "update smbms_user\n" + "set userPassword=?\n" + "where id=?;"; int execute = 0; if (conn!=null){ PreparedStatement pst = null; Object parms[] = {password,id}; execute =BaseDao.execute(conn, sql, parms, pst); BaseDao.closeResoure(null,pst,null); } return execute; }
-
在服务层接口新增修改密码方法
public boolean updateuser( int id, String password);
-
编写service层别忘记注册
public boolean updateuser(int id, int password) { boolean flag = false; Connection conn = null; try { conn= BaseDao.getconnection(); //修改密码 if(userDao.updateuser(conn,password,id)>0){ System.out.println("修改成功"); flag = true; } }catch (Exception e){ } return flag; }
package com.hyc.servlet.user; import com.hyc.pojo.user; import com.hyc.service.user.UserService; import com.hyc.service.user.UserServiceImpl; import com.hyc.util.Constaets; import com.mysql.jdbc.StringUtils; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; //实现Servlet复用 public class UserServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从session里面那到用户的id Object o = req.getSession().getAttribute(Constaets.USER_SEESION); String newpassword = req.getParameter("newpassword"); boolean flag = false; if (o != null&&newpassword!=null) { UserServiceImpl userService = new UserServiceImpl(); flag = userService.updateuser(((user)o).getId(),newpassword); if (flag){ req.setAttribute("massage","修改密码成功,请退出使用新密码登陆"); req.getSession().removeAttribute(Constaets.USER_SEESION); System.out.println( req.getSession().getAttribute(Constaets.USER_SEESION)); resp.sendRedirect("/smbms/login.jsp"); }else { req.setAttribute("massage","密码修改失败"); } }else { req.setAttribute("massage","新密码有问题"); req.getRequestDispatcher("smbms/jsp/pwdmodify.jsp").forward(req,resp); } } }
-
实现复用需要提取方法
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); } }
-
测试功能
优化密码注册密码修改使用ajax
- 阿里巴巴的fastjson;
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
2.后台代码修改
//验证旧密码,session中有用户的密码
public void pwdmodify(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{
Object o = req.getSession().getAttribute(Constaets.USER_SEESION);
String oldpassword = req.getParameter("oldpassword");
//万能的map:结果集
HashMap<String, String>resultMap = new HashMap<String, String>();
if (o==null){//session失效了,过期了
resultMap.put("result","sessionerror");
}else if(oldpassword!=null){
resultMap.put("result","error");
}else {
String userPassword = ((user)o).getUserPassword();
if (oldpassword.equals(userPassword)){
resultMap.put("result","true");
}else {
resultMap.put("result","false");
}
}
try{
resp.setContentType("application/json");
PrintWriter writer = resp.getWriter();
//JSONArray 阿里巴巴的json工具类,转换格式
writer.write(JSONArray.toJSONString(resultMap));
writer.close();
}catch (Exception e){
System.out.println(e.getMessage());
}
}
实现底层用户管理分页
- 导入分页的工具类
- 用户列表页面导入
- 引入页面
1.获取用户数量
-
userdao
public int getUserCount(Connection conn ,String username,int userrole);
-
userDaoimpl
//根据用户名或者角色名查询用户总数[核心sql]项目内最难得sql @Override public int getUserCount(Connection conn, String username, int userrole) { PreparedStatement pst = null; ResultSet rs = null; int count = 0; if (conn!=null){ StringBuffer sql = new StringBuffer(); sql.append("select count(1) as count from smbms_user u,smbms_role r where u.userRole = r.id"); ArrayList<Object> list = new ArrayList<>();//存放参数 if (!StringUtils.isNullOrEmpty(username)){ sql.append(" and u.userName like ?"); list.add("%"+username+"%");//list默认下标0 } if (userrole>0){ sql.append(" and u.userRole like ?"); list.add(userrole);//list默认下标0 } //怎么把list转换为数组 Object[] params = list.toArray(); System.out.println("userdaoimpl"+sql.toString());//输出最后完整的sql语句; rs = BaseDao.execute(conn,sql.toString(),params,pst,rs); try { if (rs.next()){ count = rs.getInt("count");//从结果集获取数量 } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { BaseDao.closeResoure(conn,pst,rs); } } return count; }
-
UserService
public int getUserCount(String username,int userRole);
-
UserServiceimpl
@Override public int getUserCount(String username, int userRole) { Connection conn = null; int count = 0; conn = BaseDao.getconnection(); count = userDao.getUserCount(conn,username,userRole); BaseDao.closeResoure(conn,null,null); return count; }
-
第二条线,分页查询用户
Userdao 确认sql:
select u.*,r.roleName as userRoleName from smbms_user u ,smbms_role r where u.userRole = r.id and u.userName like ? and u.userRole = ? order by u.createdBy DESC limit ?,?;
//查询条件获取用户list public List<user> getUserList(Connection conn,String userName,int userRole,int CurrentPagNo,int pageSize);
-
编写分页查询用户实现类
public List<user> getUserList(Connection conn, String userName, int userRole, int CurrentPagNo, int pageSize) { PreparedStatement pst = null; ResultSet rs = null; List<user> userList = new ArrayList<>(); List<Object> List = new ArrayList<>(); if (conn!=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"); 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 u.createdBy DESC limit ?,?"); CurrentPagNo = (CurrentPagNo-1)*pageSize; List.add(CurrentPagNo); List.add(pageSize); Object[] params = List.toArray(); System.out.println("sql-->"+sql.toString()); rs = BaseDao.execute(conn,sql.toString(),params,pst,rs); try { if (rs.next()){ user _user = new user(); _user.setId(rs.getInt("id")); _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); } } catch (SQLException throwables) { throwables.printStackTrace(); } return userList; }
-
编写服务层
public List<user> getUserList(String queryUserName,int queryUserRole,int currentPagNo,int PageSize);
@Override
public List<user> getUserList( String queryUserName,int queryUserRole, int currentPagNo, int PageSize) {
Connection conn = null;
List<user> userList = null;
conn = BaseDao.getconnection();
userList = userDao.getUserList(conn,queryUserName,queryUserRole,currentPagNo,PageSize);
return userList;
}
2 .显示用户serlvet
- 获取用户的前端数据(查询)
- 判断请求是否需要执行,看参数的值来判断
- 为了实现分页,需要计算出当前页面和总页面的参数
- 用户列表展示
- 返回前端
15.文件上传原理
文件上传原理就是操作io流
一共就那麽几个步骤
1.判断文件是不是文件表单
2.创建缓冲区以防文件过大
处理上传文件,一般需要通过流来获取,我们可以使用req的流,原生态的文件上传流获取,十分麻烦
但是我们都建议使用apache的文件上传组件来实现,common-fileupload,他需要以来与commons-io组件
通过这个工厂设置一个缓冲区,当上传文件大于缓冲区的时候,将他放到临时文件中
3.处理上传文件把前端请求解析成一个fileitems集合对象
可以使用UUID(唯一识别通用的通用码),保证文件名唯一
随意生成一个唯一的识别通用码
网络传输中的东西,都需要序列化
pojo 实体类 如果想要通过网络在多个电脑上运行,传输===>需要把对象都序列化
没有方法的接口叫做标记接口 jvm--> Java栈, 本地方法栈 :native--> c++
jni = java Native Interface
4.确认存放文件存放路径
5文件传输和返回前端成功与否的信息