javaweb
javaweb
1.基础概念
-
静态web
- html,css
- 提供给所有人看的数据始终不会改变
-
动态web
-
数据始终都在改变,每个人在不同时间不同地点看到的数据不同(淘宝之类的)
-
Servlet/jsp,asp,php
在Java中动态资源开发技术统称为javaweb
-
1.2 web程序
能通过浏览器访问到的程序
-
我们能访问的任何资源,都存在这个某一个计算机上
-
URL
-
这个统一的web资源都会放在同一个文件下,web应用程序--》Tomcat
-
一个web应用由多部分组成(静态web,动态web)
- html,css,js
- jsp,servlet
- java程序
- jar包
- 配置文件
web应用程序写好后想要被访问到:需要一个服务器来统一管理
1.3丶静态web

- 静态页面的缺点:
- Web页面无法动态更新,所有用户看到的都是同一个页面
- 它无法与数据库交互(数据无法持久化,用户无法交互)
1.4丶动态web

缺点:
- 动态资源出现问题就要重新编写我们的后台程序,重新发布
- 停机维护
优点:
- Web页面可以动态更新,所有用户看到的都是同一个页面
- 它可以与数据库交互(数据能持久化,用户能交互)

2.Tomcat
2.1丶Tomcat基础
(1)Tomcat目录

(2)丶启动和配置

(3)丶配置文件


这里可以配置访问端口
- Tomcat的默认端口号:8080
- mysql:3306
- http:80
- https:443

访问的localhost只是我们设置的,我们可以设置成任意的(但是你在这里直接更改还不行,你得去window设置(C:\Windows\System32\drivers\etc)里面添加一个域名跟你想修改的配置),但是它真正实现访问的是你的主机ip127.0.0.1
端口号同理
面试题
2.2 请你谈一谈网站是如何访问的!
-
输入一个域名,回车
-
就会在本地C:\Windows\System32\drivers\etc配置文件下查找是否有这个域名映射;
-
有:就直接返回这个IP地址对应的web程序
# 127.0.0.1 localhost # ::1 localhost2.没有:去DNS服务器找,找到就返回,找不到就报错
![1638955772869]()
-
2.3 发布一个Web网站

http://localhost:8080/shinian/html/zhuye.html
访问地址(上面)
网站应该有的结构:
--webapps:Tomcat服务器的web服务器
-shinian
-Root:网站的目录名
-index.html/jsp 默认的首页
-WEB-IF 放网站程序的
-web.xml
-classes:java程序
-lib:web应用所依赖的jar包
-static 资源目录
-html
-js
-img
-......
3.HTTP
3.1 什么是HTTP
3.2 两个时代
- http1.0
- HTTP/1.0 客户端与服务器连接后,一次只能获取一个web资源
- http2.0
- HTTP/1.1 客户端与服务器连接后,一次能获取多个web资源
3.3 请求
客户端--发请求(Request)--服务器
百度为例:
请求 URL: https://www.baidu.com/ 域名
请求方法: GET 请求方式 :Get/Post
状态代码: 200 OK 状态码
远程地址: 14.215.177.39:443 主机Ip地址和端口号
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 能接收的资源
Accept-Encoding: gzip, deflate, br 接收的编码
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 语言
Cache-Control: max-age=0
Connection: keep-alive
1.请求行:
- 请求行中的请求方式:GET
- 有哪些方式:GET,Post等
- get:请求能够携带的参数比较少,大小有限制,会在浏览器的URL地址栏显示数据内容,不安全,但高效
- Post:请求能够携带的参数比较多,大小没限制,不会在浏览器的URL地址栏显示数据内容,安全,但不高效
2.消息头:
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: gzip, deflate, br 接收的编码
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 语言
Cache-Control: max-age=0 缓存控制
Connection: keep-alive 告诉浏览器,请求完成是断开还是连接
Host: 主机
3.4 响应
服务器--响应(Respond)--客户端
Cache-Control: private 缓存控制
Connection: keep-alive 连接
Content-Encoding: gzip 编码
Content-Type: text/html;charset=utf-8 类型
1.响应体
Accept: 告诉浏览器,它所支持的数据类型
Accept-Encoding: gzip, deflate, br 接收的编码
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 语言
Cache-Control: max-age=0 缓存控制
Connection: keep-alive 告诉浏览器,请求完成是断开还是连接
Host: 主机
Refresh: 告诉客户端,多久刷新一次
location:让网页重新定位
2.响应状态码(重点):
200:请求成功
3**:请求重定向
- 重定向:你重新到我给你的新位置去;
4xx:找不到资源 404
- 资源不存在
5xx:服务器代码错误 500 502:网关错误
3.5 常见面试题
当你的浏览器地址栏输入并回车的一瞬间到页面能够展示回来,经历了什么?
4.Maven
为什么要学这个技术?
- 在javaweb开发中,需要大量的导包,手动导入太麻烦
- 在此基础上Maven诞生了!
4.1 Maven项目架构管理工具
我们目前只用来导包
Maven核心思想:约定大于配置
- 有约束,不要去违反
Maven会规定你该如何去编写我们的java代码,必须按照这个规范来;
4.2 配置环境
在环境变量中,配置如下配置
- M2_HOME maven目录下的bin目录
- MAVEN_HOME maven的目录
- 在系统的path中配置 %MAVEN_HOME%\bin
4.3 阿里云镜像
-
镜像:morris
- 加速我们的下载
-
国内推荐阿里云镜像
<mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror>
4.4 本地仓库
在本地的仓库就会有远程仓库
建立一个本地仓库:localRepository
<localRepository>D:\Maven\apache-maven-3.8.4\maven-repo</localRepository>
4.5 在Idea使用Maven
-
创建一个Maven项目




2.此时的Maven仓库多了什么东西?
3.IDEA里的Maven设置

4.6.不勾选模板创建一个普通Maven

4.7 标记文件夹功能

4.8 在Maven中配置Tomcat


必须的配置:为什么会有这个问题,因为我们访问一个网站是需要一个文件夹的,IDEA不会给默认**

4.9 pom.xml(Maven的核心配置文件)

在配置文件中导入其他包的依赖,Maven的高级之处在于它能够帮你导入这个jar包所依赖的其他jar包
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.Servlet
5.1 基础概念
-
Servlet是一种实现动态Web的一门技术
-
本质:servlet其实就是对请求和响应的封装
-
你想实现一个Servlet,必须有两个步骤:
- 编写一个类实现Servlet接口
- 将这个java类部署到服务器上
把实现了Servlet接口的java程序叫做 Servlet
5.2 HelloServlet
-
构建一个普通的Maven项目,删掉里面的src目录,用户我们的学习就在这个项目里面建立Moudel,这个空工程的就是Maven主工程
-
关于Maven的父子工程的理解:
-
父项目会有:
<modules> <module>Servlet-01</module> </modules>2.子项目会有:
<parent> <artifactId>JavaWeb-01-Maven2</artifactId> <groupId>com.LiuDeHen</groupId> <version>1.0-SNAPSHOT</version> </parent>注意:这里子项目中没有parent的话后面在子项目里调用包时可能会因为子项目没有指向父项目,而需要用到父项目的包二无法自动导包
3.就跟继承一样,父项目的java子项目可以直接用
son extends father -
-
Maven环境优化
-
修改子项目web.xbl为最新的
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0" metadata-complete="true"> </web-app> -
将maven的结构搭建完整(webapps里一般要有java源目录和resources资源目录)
-
-
编写一个Servlet程序
-
编写一个普通类
-
实现Servlet接口,这里我们直接继承HttpServelt
- Servlet接口有两个实现类,HttpServlet和GenericServlet
public class HelloServlet extends HttpServlet { // 由于Get和Post只是实现请求的不同方式,可以相互调用,业务逻辑都一样 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); //响应流 writer.write("helloServlet"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); }3.为什么要继承HttpServlet
![1639062246093]()
5.编写servlet映射
为什么需要映射勒,因为servlet就是一个java程序而已,我们想要通过浏览器访问到,必须通过web服务器,所以我们就需要再web服务器里注册映射我们写的servlet,并且再给浏览器一个能够访问的路径
<!-- 注册映射servlet--> <servlet> <!-- 自定义一个name 与下面访问地址的name对应--> <servlet-name>hello</servlet-name> <!--servlet类的位置--> <servlet-class>com.LiuDeHen.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <!--访问地址,这样前台就可以通过这个访问了--> <url-pattern>/hello</url-pattern> </servlet-mapping>运行后会加载到webapp这个包下,然后就会解析web.xml(下面这个图),就会访问到servlet程序
![1639059435538]()
上图中访问地址前必须必须要有/
-
6.配置Tomcat
注意:配置项目发布路径就可以了
7.测试
启动Tomcat会出现一个target包
5.3 Servlet原理

5.4 Mapping问题
-
一个Servlet指定一个映射
<servlet-mapping> <servlet-name>hello</servlet-name> <!--访问地址,这样前台就可以通过这个访问了--> <url-pattern>/hello</url-pattern> </servlet-mapping> -
一个Servlet指定多个映射
<servlet-mapping> <servlet-name>hello</servlet-name> <!--访问地址,这样前台就可以通过这个访问了--> <url-pattern>/hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <!--同一个name,不同访问地址也可以访问到同一个Servlet--> <url-pattern>/hello1</url-pattern> </servlet-mapping> -
默认请求路径
<servlet-mapping> <servlet-name>hello</servlet-name> <!--此时仍然访问的是Servlet而不是先访问index页面--> <url-pattern>/*</url-pattern> </servlet-mapping> -
使用通配符
<servlet-mapping> <servlet-name>hello</servlet-name> <!--访问地址,任意字符都能访问到--> <url-pattern>/hello/*</url-pattern> </servlet-mapping> -
指定一些前缀后缀
<servlet-mapping>
<servlet-name>hello</servlet-name>
<!--*不像其他类型,前面不能有任何东西,但是在访问的时候,前面可以有任何文件夹-->
<url-pattern>*.lc</url-pattern>
</servlet-mapping>
6.优先级问题
假如我定义了一个404报错Servlet,使用的是通配符地址,那么我访问/hello,是访问的hello页面还是404页面?
肯定是hello页面,固有的映射路径优先级最高,如果找不到才会找默认路径
5.5 ServletContext
Web服务器在启动的时候,它会为每一个Web程序都创建一个ServletContext对象,它代表了当前的Web应用,(一个web只有一个ServetContext)
1 共享数据
我在这个Servlet中保存的数据,可以在另一个Servlet拿到
注意:响应时要设置响应编码格式不然会出现?

在当前Servlet设置
ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("User","你好");
在另外一个Servlet获取
resp.setContentType("text/html");
resp.setCharacterEncoding("GBK");
ServletContext servletContext = this.getServletContext();
Object user = servletContext.getAttribute("User");
PrintWriter writer = resp.getWriter();
writer.write(user.toString());
2 获取初始化参数
设置初始化需要的配置文件
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql//localhost:3306/lc</param-value>
</context-param>x
获取:
ServletContext servletContext = this.getServletContext();
String s=servletContext.getInitParameter("url");
resp.getWriter().print(s);
3 请求转发
ServletContext servletContext = this.getServletContext();
RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/hello");//转发地址
dispatcher.forward(req,resp); //调用forword实现请求转发
这个只是转发,并不会改变我们的地址


4 读取资源文件
Properties
-
在java目录下新建properties
-
在resource下新建properties
发现:都被导包到同一个路径下(target里的)classes,俗称为classpath
思路:我们只需要给一个流
username:root pwd:lc20010725InputStream stream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.Properties"); Properties p=new Properties(); p.load(stream); String user = p.getProperty("username"); String pwd = p.getProperty("pwd"); resp.getWriter().print(user+":"+pwd);注意:我们读的文件是target里导出的文件
5.6 HttpServletResponse
web服务器接收到客户端的请求,针对这个请求,会分别创建一个代表请求的HttpServletRequest,代表响应的HttpServletResponse
- 如果要获取客户端请求过来的参数:找HttpServletRequest
- 如果要获取服务器响应的信息:找HttpServletResponse
常用分类:
1 向客户端发送消息(ServletResponse里的):
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
2 向浏览器发送响应头的方法:
ServletResponse里的:
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
HttpServletResponse里的:
void sendRedirect(String var1) throws IOException;
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);
3 状态码:
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;
常见应用(*重定向):
-
在客户端输入数据
-
下载文件
resp.setCharacterEncoding("UTF-8"); resp.setContentType("txt/html"); // 1.找到资源路径 // 相对路径 // String path = this.getServletContext().getRealPath("/WEB-INF/classes/1.txt"); // 绝对路径 String path="D:\\JavaWeb-01-Maven2\\Response\\target\\Response\\WEB-INF\\classes\\1.png"; // 2.获取文件名 String filename = path.substring(path.lastIndexOf("\\") + 1); // 3.想办法让浏览器支持我们下载 resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(filename,"UTF-8")); // 4.获取下载文件的流 FileInputStream in = new FileInputStream(path); // 5.创建一个缓冲区 int len=0; byte[] buffer = new byte[1024]; // 6.获取输出流对象 ServletOutputStream out = resp.getOutputStream(); // 7.将OutputStream流写到缓存区,再使用响应的输出流将缓存流数据输出到客户端 // 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 while ((len=in.read(buffer))>0){ out.write(buffer,0,len); } out.close(); in.close();3.验证码功能:
就不写了,我们要知道响应的传给浏览器信息的时候,编码格式,文件格式,包括上面的下载,也就是要设置它的响应头的内容
4.实现重定向(重点):
![1639117377363]()
b收到一个来自客户端a的请求后,它会通知a去访问另外一个web资源c,这就叫重定向
常见场景:
-
用户登录
void sendRedirect(String var1) throws IOException;测试:
// resp.setHeader("location","/Response_war/down"); // resp.setStatus(302); // 重定向就是由上面两步构成 resp.sendRedirect("/Response_war/down");面试题:请你谈谈重定向(拽)和转发(怂)的区别?
拽哥叫别人自己去,怂逼帮它去
相同点:
- 都会跳转页面
不同点:
-
转发不改变地址 307
-
重定向改变地址 302
总结:转发是一次请求,重定向两次,转发是服务器内部完成,而重定向是在客户端完成
-
5.7 HttpServletRequest
概念:
HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,Http请求中的所有信息都会封装到HttpServletRequest,通过HttpServletRequest可以获取到客户端的所有信息
应用:
1.获取前端的传递参数
String username = req.getParameter("username");
String pwd = req.getParameter("pwd");
String[] hobbies = req.getParameterValues("hobbies");
2.请求转发
req.getRequestDispatcher("/Succes.jsp").forward(req,resp);
6.Cookie和Session
6.1 会话
会话:用户打开一个浏览器,点开很多超链接,访问不同web资源,到关闭浏览器,这就是会话
有效会话:当一个同学来过教室,下次再来教室里的时候,其他同学就知道你曾经来过,称之为有状态会话
例子:怎么证明你是中国公民
你 国家
1.你有身份证 国家给你的身份证
2.国家数据库里有你信息 国家数据库里有你信息
那么在网站上怎么证明你来过呢?
客户端 服务端
1.当客户端访问服务端的时候,服务端会给客户端一个信件,客户端下次访问带上信件就可以了 Cookie
2.服务端登记你来过,下次你来的时候自动匹配你 Session
6.2 保存会话的两种技术
Cookie
- 客户端技术(响应,请求)
Session
- 服务器技术,利用这个技术就可以保存用户的会话信息?我们可以把数据放到Session中
6.3 Cookie(饼干,信件)

站在面向对象的角度
-
客户端去获取Cookie
-
服务端去响应给客户端Cookie
// 获取Cookie,因为Cookie是服务端给客户端,所以客户端去获取(面向对象的角度) Cookie[] cookies = req.getCookies(); // 获取cookie 的key值 cookies[i].getName() // 获取cookie的 value值 cookies[i].getValue() // 新建一个cookie Cookie cookie = new Cookie("time",System.currentTimeMillis()+""); // 设置到期时间 cookie.setMaxAge(24*60*60); // 服务端给客户端一个Cookie resp.addCookie(cookie);Cookie:一般会保存在本地 用户目录下的 Appdate下
细节:
- 一个网站Cookie是否有上限!
- 一个Cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个Cookie,最多存放20个Cookie
- Cookie大小上限4kb
- 浏览器Cookie上限为300
删除Cookie:
- 不设置有效期,关闭浏览器,自动失效
- 设置有效期为0
6.4 Session

什么是Session:
-
服务器会给每一个用户(浏览器)创建一个Session对象
-
一个Session独占一个浏览器,只要浏览器没有关闭,Session就一直存在
-
一访问web程序就会产生一个Session,同一个浏览器只有一个Seesion
// 获取Session HttpSession session = req.getSession(); // 设置Session(设置类型为object,比Cookie广) session.setAttribute("Test",new Test(20,"lc","Code")); // 获取ID String id = session.getId(); // 判断这个Session是不是新的 if(session.isNew()){ out.write("Session创建成功,ID"+id); }else{ out.write("Session已经在服务器中存在,ID"+id); } // 获取name为“Test”的Session Test T =(Test)session.getAttribute("Test"); // 移除那个key为Test的session session.removeAttribute("Test"); // 手动注销Session // session.invalidate();移除和注销是不同的,移除了Session还是那个Session,只是那个属性为Test的Session没有了
//在配置里注销(自动注销): <session-config> <session-timeout>15</session-timeout> </session-config>而注销

再一次访问,ID不同因为是另外一个Session了

总结:Session和Cookie的区别
1.Cookie是把数据写到用户的客户端
2.Session把用户的数据写到服务端(保存重要信息,减少服务器资源的浪费)
3.Session对象由服务器创建,cookie也是由服务器创建给客户端
使用场景:
- 保存一个登录用户的信息
- 购物车信息
- 在网站中经常用到的数据保存到Session
Session的SessionID是服务端响应了一个Cookie给客户端

7.JSP
7.1什么是JSP
Java Server Pages:java服务端页面,也和Servlet一样,用于动态Web技术!
最大的特点:
- 写JSP就像在写HTML
- 区别:
- HTML只给用户提供静态数据
- Jsp页面可以嵌入java代码,为用户提供动态数据
7.2 JSP原理
思路:JSP到底怎么执行的!
- 服务器内部工作
- 发现页面转换成java程序

JSP只有在被访问时才会转化为java和class文件
(重)浏览器向服务器发送请求的时候,不管访问你什么资源,其实都是在访问Servlet!
Jsp最终也会被转换为JAVA程序
JSP实质上就是一个Servlet
看JSP源码


1.判断请求方式
2.JSP内置对象
final javax.servlet.jsp.PageContext pageContext; //页面上下文
javax.servlet.http.HttpSession session = null; //session
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //Config配置
javax.servlet.jsp.JspWriter out = null; //out输出
final java.lang.Object page = this; //当前页面
HttpServletRequest request //请求
HttpServletResponse response //响应
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;

在java代码中:
java代码会被原封不动的输出
而HTML代码就会被输出成:
out.write("\r\n");
7.3 JSP基础语法
作为java技术的一种扩张,支持java所有的语法,也有自己的一些扩充的语法
1.JSP表达式
<%--JSP表达式
作用:用来将程序的输出,输出到客户端
<%= 变量或者表达式%>
--%>
<%=1+2%>
一般用EL表达式替代
${} 跟<%=%>等同
2.JSP脚本片段
<%--JSP脚本片段--%>
<%
int a=7;
out.print("当前a为:"+a);
%>
3.JSP脚本片段嵌入HTML
<%--在代码里嵌入HTML代码--%>
<%
for (int i = 0; i <3 ; i++) {
%>
<h1>你好刘超</h1> <%=1%>
<%
}
%>
为什么能怎么写,java代码在转换后还是java代码,而HTML代码会被转换成out.print("你好刘超“);
4.JSP声明
<%--JSP声明--%>
<%!int a=10;
static {
int b;
}
%>
Jsp声明会被编译到类里,作用域高
普通<%%>写的带代码都在jsp.java文件里的JspService方法里,
7.4 JSP指令
<%@ page errorPage="err/500.jsp" %>
<%--指令
两个页面合二为一
--%>
<%@ include file="comom/Header.jsp"%>
<h1>我是内容</h1>
<%@ include file="comom/Footer.jsp"%>
<hr>
<%--JSP标签
拼接页面实际还是三个页面
--%>
<jsp:include page="comom/Header.jsp"/>
<h1>我是内容</h1>
<jsp:include page="comom/Footer.jsp"/>
7.5 9大内置对象及作用域
作用域:
- Pagecontext 存东西 保存的东西只在一个页面中有效
- Request 存东西 保存的东西在这次请求中有效
- Response
- Session 存东西 保存的东西在一次会话中(浏览器从开启到关闭)有效
- Application(ServletContext) 存东西 凌驾于所有Servlet之上,保存的数据在服务器中,从服务器开启到关闭
- config(ServletConfig)
- out
- page
- exception
pageContext.setAttribute("1","a"); 存东西 保存的东西只在一个页面中有效
request.setAttribute("2","b"); 存东西 保存的东西在这次请求中有效
session.setAttribute("3","c"); 存东西 保存的东西在一次会话中(浏览器从开启到关闭)有效
application.setAttribute("4","d"); 存东西 凌驾于所有Servlet之上,保存的数据在服务器中,从服务器开启到关闭
作用域:
request: 从客户端向服务端发送请求,产生得数据,用户用完就不用了,比如:看新闻
session:从客户端向服务端发送请求,产生得数据,用户用完还有用,比如:购物车,登录
application:从客户端向服务端发送请求,产生得数据,一个用户用完了,另外一个用户还能用到,比如聊天信息
7.6 JSP标签,JSTL标签和EL表达式
EL表达式:${}
-
获取数据
-
执行运算
-
获取web开发得常用对学校
JSP标签
<jsp:forward page="jsptag2.jsp"> <jsp:param name="name" value="刘超"/> <jsp:param name="age" value="20"/> </jsp:forward>
JSTL标签
JSTL标签库是为了弥补HTML得不足
<!-- 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>

JSTL使用步骤:
- 导入taglibs
- 使用对应方法


8.JavaBean
实体类
javaBean特有得写法
- 必须要有一个无参构造
- 属性必须私有化
- 必须由对应得get/set方法
一般用来和数据库得字段做映射 ORM
ORM:对象关系映射
- 表---》类
- 字段---》字段
- 行记录---》对象
9.MVC三层架构
什么是MVC:model view controller 模型,视图,控制器
9.1 早些年的架构

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

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

Filter开发步骤:
-
导包
![1639553333197]()
-
编写过滤器
-
导包不要错
-
重写3个方法
// web服务器服务器启动,就会初始化 @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("开启过滤器"); } // chain:链 // 1过滤的所有代码,在特定的特定请求的时候都会执行 // 2必须要让过滤器继续执行 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("utf-8"); servletResponse.setCharacterEncoding("utf-8"); servletResponse.setContentType("text/utf-8;charset=UTF-8"); // 让我们的请求继续走,如果不写,程序到这里拦截停止 filterChain.doFilter(servletRequest,servletResponse); } //web服务器关闭,才会停止 @Override public void destroy() { System.out.println("关闭过滤器"); }
-
3.在web.xml中配置FIlter
<filter>
<filter-name>filter</filter-name>
<filter-class>com.LiuDeHen.Filter.DemoFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<!-- select下的所有请求,都会经过这个过滤器-->
<url-pattern>/select/*</url-pattern>
</filter-mapping>
11.监听器
//统计在线人数
public class ListenerServlet implements HttpSessionListener {
// 创建Session监听,一旦创建就会触发一次
@Override
public void sessionCreated(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
System.out.println(se.getSession().getId());
Integer l = (Integer) context.getAttribute("OnlineCount");
if (l==null){
l=new Integer(1);
}else{
int i=l;
l=i+1;
}
context.setAttribute("OnlineCount",l);
}
// 销毁Session监听,一旦销毁就会触发一次
@Override
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
se.getSession().invalidate();
Integer l = (Integer) context.getAttribute("OnlineCount");
if (l==null){
l=new Integer(0);
}else{
int i=l;
l=i--;
}
context.setAttribute("OnlineCount",l);
}
在xml里注册监听器
<listener>
<listener-class>com.LiuDeHen.Listener.ListenerServlet</listener-class>
</listener>
12.过滤器和监听器常见应用
监听器:GUI经常用到
过滤器:
用户登录之后才能进入主页!
- 用户登录之后,向Session中放入用户的数据
- 进入主页的时候判断用户是否已经登录,要求:在过滤器中实现
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest) servletRequest;
HttpServletResponse resp=(HttpServletResponse) servletResponse;
if (req.getSession().getAttribute("username_ID")==null){
resp.sendRedirect("/login.jsp");
}
filterChain.doFilter(servletRequest,servletResponse);
}
13 JDBC复习
基础配置
什么是JDBC:java连接数据库

需要jar包支持:
- java.sql
- javax.sql
- mysql驱动(必须导入)
实验环境搭建:
CREATE DATABASE JDBC
USE JDBC;
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123','24@11.com','2021-9-2');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'张si','123','24@11.com','2021-9-2');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'张wu','123','24@11.com','2021-9-2');
SELECT * FROM users
导入数据库依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
JDBC步骤:
- 加载驱动
- 连接数据库,代表数据库
- 拿到操作数据库的对象Statem
- 编写sql
- 执行sql
- 关闭连接
// 配置信息
String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
String username="root";
String password="lc20010725";
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接
Connection connection = DriverManager.getConnection(url, username, password);
// 操作数据库的对象statement;
Statement statement = connection.createStatement();
// 编写sql
String sql="select * from users";
// 执行sql,返回结果集
ResultSet resultSet = statement.executeQuery(sql);
// 取出数据
while (resultSet.next()){
System.out.println("id"+resultSet.getObject("id"));
System.out.println("name"+resultSet.getObject("name"));
System.out.println("password"+resultSet.getObject("password"));
System.out.println("email"+resultSet.getObject("email"));
System.out.println("birthday"+resultSet.getObject("birthday"));
}
// 关闭连接
resultSet.close();
statement.close();
connection.close();
预编译sql
// 1配置信息
String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
String username="root";
String password="lc20010725";
// 2加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 3获取连接
Connection connection = DriverManager.getConnection(url, username, password);
// 4编写sql
String sql="insert into users(id,name,password,email,birthday) values (?,?,?,?,?)";
// 5预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,1);//给第一个占位符填充
preparedStatement.setString(2,"lc");
preparedStatement.setString(3,"123");
preparedStatement.setString(4,"12@qq.com");
preparedStatement.setDate(5,new Date(new java.util.Date().getTime()));
//6执行sql
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功");
}
// 7关闭连接
preparedStatement.close();
connection.close();
事务
要么都成功,要么都失败!
ACID原则:保证数据的安全性
开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务
junit单元测试
依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
@Test只有在方法上有效
@Test
public void test(){
System.out.println("你好");
}
// 配置信息
String url="jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSl=true";
String username="root";
String password="lc20010725";
Connection connection=null;
try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接
connection = DriverManager.getConnection(url, username, password);
// false为开启事务
connection.setAutoCommit(false);
String sql="update account set money=money-100 where name='A'";
connection.prepareStatement(sql).executeUpdate();
// 制造错误
// int i=1/0;
String sql2="update account set money=money+100 where name='B'";
connection.prepareStatement(sql2).executeUpdate();
// 提交事务
connection.commit();
System.out.println("提交成功");
}catch (Exception e){
// 出现异常就回滚
try {
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}finally {
// 关闭连接
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}





浙公网安备 33010602011771号