基本概念
在java中,动态资源开发的技术称为javaweb
web开发
- web是网页的意思
- 静态web
- html css
- 提供给所有人看的数据一样
- 动态web
- 淘宝,几乎所有的网站
- 提供所有人看的数据始终会发生变化,每个人在不同时间,不同地点看的信息各不相同
- 技术栈:Servlet/JSP ASP PHP
web应用程序
可以提供浏览器访问的程序
- a.html b.html ....多个web资源,这些web资源可以被外界访问,对外界提供服务
- URL
- 一个web应用由多部分组成(静态web,动态web)
- html css
- jsp servlet
- java程序
- jar包
- 配置文件(properties)
- web应用程序编写完毕,若想提供给外界访问,需要一个服务器来统一管理
Tomcat
安装
安装tomcat,之前需要先安装一下jdk,用java -version
检查
官网目前已经更新到tomcat10了,但是tomcat10和idea一起使用还是存在问题,所以推荐使用tomcat9
下载压缩包之后,直接解压
启动
如果你直接点击bin目录下的startup.bat,可能会出现界面一闪而过,如果没有一闪而过就可以跳过下面的办法了
你需要在控制台中输入
之后在网页上输入localhost:8080
,就会显示
但是,运行结果可能会出现乱码
修改conf目录下的logging.properties文件
将文件中原有的配置修改
#原有
java.util.logging.ConsoleHandler.encoding = UTF-8
#修改成GBK,因为windows默认是gbk
java.util.logging.ConsoleHandler.encoding = GBK
访问测试:localhost:8080
乱码的本质:读取二进制的时候采用的编码和最初将字符转换成二进制时的编码不一致
将"我们是中国人"以UTF-8编码转换成byte数组(byte数组其实就相当于二进制序列了,此过程即编码),再以GBK编码和byte数组创建新的字符串(此过程即以GBK编码去解码byte数组,得到字符串),就产生乱码了
文件夹对应作用
--webapps Tomcat服务器的web目录
-ROOT
-project 网站的目录名
-WEB-INF
-classes java程序
-lib web应用所依赖的jar包
-web.xml 网站配置文件
- index.html 默认的首页
- static
-css
-style.css
-js
-img
-....
HTTP
什么是HTTP
HTTP(超文本传输协议)是一个简单的请求—响应协议,它通常是运行在TCP上
-
文本:html,字符串
-
超文本:图片,音乐,视频,地图,定位...
-
80端口
Https:安全的
- 443端口
HTTP请求
- 客户端——发请求(Request)——服务器
百度的例子
Request URL: https://www.baidu.com/?tn=78040160_14_pg&ch=8 请求地址
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: no-cache
Connection: keep-alive
- 请求行
- 请求方式:GET,POST
- get:请求能携带的参数比较少,大小有限制,不安全但高效
- post:请求能携带的参数没有限制,大小没有限制,安全但不高效
- 请求方式:GET,POST
- 请求头
Accept: 告诉浏览器,它支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK,UTF-8,GB312 ..
Accept-Language: 告诉浏览器,他的语言环境
Cache-Control: no-cache 缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST:主机
HTTP响应
- 服务器——响应——客户端
百度的例子
Cache-Control: private 缓存控制
Connection: keep-alive 连接
Content-Type: text/html;charset=utf-8
- 响应体
Accept: 告诉浏览器,它支持的数据类型
Accept-Encoding: 支持哪种编码格式 GBK,UTF-8,GB312 ..
Accept-Language: 告诉浏览器,他的语言环境
Cache-Control: no-cache 缓存控制
Connection: 告诉浏览器,请求完成是断开还是保持连接
HOST:主机
Refrush:告诉客户端,多久刷新一次
Location让网页重新定位
- 响应状态码
响应状态码 | 描述 |
---|---|
200 | 请求成功 |
3** | 请求重定向 |
4** | 找不到 |
5** | 服务器错误 |
502 | 网关错误 |
面试题
当你的浏览器中输入地址并回车的一瞬间到页面能够展示回来,经历了什么
Maven
为什么学习Maven?
在javaWeb开发中,需要大量的jar包,我们需要导入。Maven就是为了方便导入jar包
安装Maven
下载完成后解压
配置环境变量
在我们系统环境变量中
配置如下环境变量
名称 | 具体含义 |
---|---|
M2_HOME | maven目录下的bin目录 |
MAVEN_HOME | maven目录 |
在系统变量PATH中配置MAVEN_HOME | %MAVEM_HOME%\bin |
测试Maven 是否安装成功mvn -version
修改setting.xml
路径:D:\Environment\maven\apache-maven-3.5.4\conf\settings.xml
在setting.xml中配置镜像(为了下载依赖的速度变快)和本地仓库(设置依赖的下载位置)
阿里云镜像
<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>
本地仓库
配置好之后,在本地需要新建一个文件夹soft(文件夹名可以自己设定。比如repo,repository)
<!-- 本地仓库位置 -->
<localRepository>D:/Environment/maven/soft</localRepository>
在Maven中创建一个带模板项目
在IDEA中启用使用Maven
创建项目
在项目创建成功后,检查一下是否正确(看一眼,万一依赖下载到C盘要炸,越来越多后面电子会“炸”)
标记文件夹
补充文件夹java和resources,标记文件夹功能
- java ——>Sources Root
- resources——>Resources Root
- resources文件夹是给java文件读取的
修改web.xml
使用模板新建的项目,web.xm
l太旧了
使用下载的tomcat中的中D:\Environment\apache-tomcat-9.0.37\webapps\ROOT\WEB-INF\web.xml
<?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中创建一个普通项目
在New Project中不选择模板,直接点击Next
WEB-INF用户不可见的,所以,如果你将jquery的包放在WEB-INF中,html中是拿不到的
pom.xml
maven由于他的约定大于配置,我们之后可能遇到的问题,无法导入或者生效xml、properties文件的问题
<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>
Maven手动导入jar
下载jar包
导入jar
Add as Library
右键lib文件夹
碰到的问题
- Maven 3.6.2(无法导入maven项目)
解决方法:降级为3.6.1
- iDEA中每次都要重复配置Maven
解决方法:在IDEA中全局默认配置去配置
在IDEA中配置Tomcat
配置Tomcat
没有配置Deployment
,会碰到如下警告
碰到的问题
启动tomcat
Servlet
Servlet简介
- servlet是sun公司开发动态web的一门技术
- sun公司在这些API中提供了一个接口叫做Servlet,如果你想开发一个servelt,只需要完成2个步骤
- 编写好一个类,实现servlet接口
- 把开发好的java类部署到web服务器中
把实现了servlet接口的java程序叫做Servlet
HelloServlet
第一个Servlet程序
-
构建一个普通的Maven项目后删除里面的src目录,以后就在这个项目中建立一个Moudel,这个空的工程就是Maven的主工程
-
Maven父子工程的理解
父项目中会有
<modules> <module>servlet-01</module> </modules>
子项目会有(如果没有的话下面这段,自己加一个)
比如我创建的一个Moudle就没有自动生成,就需要自己写,还有删除一些自带的
<modelVersion>4.0.0</modelVersion> <parent> <artifactId>javaweb-servlet-01</artifactId> <groupId>com.study</groupId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>servlet01</artifactId> <packaging>war</packaging>
优点:父项目中的jar包可以在子项目中使用
-
Maven环境优化
-
修改web.xml为最新的
-
将Maven的结构搭建 java resource
-
编写一个Servlet程序
- 编写一个普通类
- 实现Servlet接口,直接继承HttpServlet
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.println("hello servlet !");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 编写Servlet的映射
- 为什么需要映射:因为我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的servlet,还需要给他一个能够访问的路径
<!-- 注册servlet-->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<!-- servlet的请求路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 配置tomcat并启动
- 启动测试,OK!
Mapping
一般是用一个servlet可以指定一个映射路径
- 一个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>/hello1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
- 一个servlet可以指定通用映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
- 指定一些后缀或者前缀(但是*前不加/)
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
ServletContext上下文
web容器在启动的时候,它会为每一个web程序都创建一个对应的ServletContext对象,它代表当前的web应用
共享数据
我们在HelloServlet中保存数据,可以在另外一个servlet中拿到
但是尽量不要用ServletContext来共享数据,数据一多会炸,可以使用session
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
String username = (String) context.getAttribute("username");
System.out.println(username);
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
resp.getWriter().print("名字:"+username);
}
}
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("hello");
ServletContext context = this.getServletContext();
String username = "DJ";
context.setAttribute("username",username);//将一个数据保存在servletContext中
}
}
读取资源文件
ProPerties
- 在java目录下新建properties
- 在resources目录下新建propertites
发现都被打包到同一个路径下:classes,我们俗称这个路径是classpath
public class ServletDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext context = this.getServletContext();
//这个路径主要是针对target生成的
InputStream is= context.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String username = prop.getProperty("username");
String password = prop.getProperty("password");
System.out.println(username+" "+ password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
HttpServletResponse
使用例子
向浏览器输出消息
(上面一直提到)
下载文件
- 要获取下载的文件的路径
- 设置下载的文件名
- 设置想办法让浏览器能够支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 获取OutputStream流写入到buffer缓冲区
- 使用OutputStream将缓冲区中的数据输出到客户端
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载的文件的路径
String realPath="D:\\Project\\javawebservlet01\\response\\target\\classes\\图片.png";
System.out.println("下载文件的路径"+realPath);
// 2. 设置下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
System.out.println("文件名"+fileName);
// 3. 设置想办法让浏览器能够支持下载我们需要的东西
//web下载文件的头信息 URLEncoder.encode 处理文件名乱码
resp.setHeader("Content-disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
// 5. 创建缓冲区
int length=0;
byte[] buffer = new byte[1024];
// 6. 获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
// 7. 获取OutputStream流写入到buffer缓冲区 使用OutputStream将缓冲区中的数据输出到客户端
while((length=in.read(buffer))>0){
out.write(buffer,0,length);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
定时刷新验证码
采用的其实是刷新整个页面
package com.study.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//让浏览器3s自动刷新一次
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.green);
g.setFont(new Font(null,Font.BOLD,20));
String num = makeNum();
System.out.println(num);
g.drawString(num,0,20);
//告诉浏览器,这个请求用图片的方式打开
resp.setContentType("image/jpeg");
//把图片写到浏览器 jpg表示文件格式名
ImageIO.write(image,"jpg",resp.getOutputStream());
}
private String makeNum(){
Random random = new Random();
String num = random.nextInt(1000000)+"";//[0,100000)
StringBuffer stringBuffer = new StringBuffer();
for(int i = 0;i<6-num.length();i++){
stringBuffer.append("0");
}
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
重定向
URL会发生变化
一个web资源收到客户端A请求后,B通知客户端A去访问另外一个web资源C,这个过程叫重定向
void sendRedirect(String var1) throws IOException;
常见的例子:登录状态
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置后台传给前台的数据不是乱码
resp.setCharacterEncoding("UTF-8");//不然页面显示会乱码
resp.sendRedirect("/response_war/img");
}
<form action="${pageContext.request.contextPath}/redi" method="get">
username:<input type="text" name="username" /><br/>
password:<input type="text" name="password" /><br/>
<input type="submit">
</form>
面试题:重定向和请求转发的区别
- 相同点
- 页面都会发生跳转
- 不同点
- 请求转发的时候URL不会发生变化 307
- 重定向的时候,URL发生后变化 302
HttpServletRequest
请求转发
req.getRequestDispatcher("/success.jsp").forward(req,resp);
//常用方法
//1. 获得前台的参数
//设置前台传给后台的数据不是乱码
req.setCharacterEncoding("UTF-8");
req.getParameter("username");
req.getParameterValues("hobbys");
//2. 通过请求转发
// /success.jsp /代表当前的web应用
req.getRequestDispatcher("/success.jsp").forward(req,resp);
Cookie,Session
会话
会话:用户打开一个浏览器,点击浏览很多链接,访问了多个web资源,关闭浏览器,这个过程就是会话
有状态会话:
一个网站,怎么证明你来过?
客户端 服务端
- 服务端给客户端一个信件,客户端下次访问服务端就带上一个信件就可以了 cookie
- 服务器登记你来过了,下次你来的时候我来匹配你:session
保存会话的两种技术
Cookie
cookie:一般会保存在本地的用户目录下 appdata
//从请求中拿到cookie拿到cookie的信息
//服务器响应给客户端cookie
Cookie[] cookies = req.getCookies(); //获得cookie
cookie.getName();//获得cookie的key
cookie.getValue();//获得cookie的value
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");//新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期,若没有设置,关闭浏览器cookie就失效
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
//保存用户上一次访问的时间
public class CookieDemo 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");
PrintWriter out = resp.getWriter();
//Cookie 服务器从客户端获取
Cookie[] cookies = req.getCookies();
if(cookies!=null){
//如果存在,遍历数组
out.write("你上一次访问的时间是");
for(Cookie cookie:cookies){
if("lastLoginTime".equals(cookie.getName())){
//获取cookie的值
System.out.println(cookie.getValue());//String
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
out.write(date.toLocaleString());
}
}
}else{
out.write("这是第一次访问本站");
System.out.println("这是第一次访问本站");
}
//服务器给客户端响应一个cookie
Cookie cookie = new Cookie("lastLoginTime",System.currentTimeMillis()+"");
//有效期为一天 s
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
Session(重点)
什么是Session
- 服务器会给每一个用户(浏览器)创建一个Session对象
- 一个Session独占一个浏览器,只要浏览器没有关闭,这个Session就一直存在
- 用户登录之后,整个网站都可访问
//创建session 并且给属性赋值,也是可以存放一个对象的
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class CookieDemo1 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");
//得到session
HttpSession session = req.getSession();
//给Session中存在东西
session.setAttribute("name","张三");
//获得session的ID
String id = session.getId();
//判断Session 是不是新创建的
if(session.isNew()){
resp.getWriter().write("session创建成功ID"+id);
}else{
resp.getWriter().write("session已经创建成功ID"+id);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
//取出session的值
package com.study.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
public class CookieDemo2 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");
//得到session
HttpSession session = req.getSession();
//取Session中存在东西
resp.getWriter().write(session.getAttribute("name"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
设置session的失效时间
在web.xml
<!-- 设置session的失效时间 单位:分钟-->
<session-config>
<session-timeout>1</session-timeout>
</session-config>
在代码中
session.removeAttribute("name");
session.invalidate();
Session和Cookie的区别
- session存储在服务器端,cookie保存在浏览器。
- session比较安全,cookie用某些手段可以修改,不安全。
- cookie的存储量有限、只允许存入4KB,而session是无限量的
使用场景:
- 保存一个登录用户的信息
- 购物车信息
- 在整个网站中经常使用的数据,将他保存在session
JSP
什么是jsp
java server pages :java服务器页面,也和servlet一样,用户动态web技术
最大的特点
- 写JSP就像在写HTML
- 区别
- HTML只给用户提供静态的数据
- jsp页面可以嵌入java代码,为用户提供动态数据
JSP原理
思路 JSP是怎么执行的
- 代码层面没有任何问题,和html代码很像
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
- 服务器内部工作
tomcat 中有一个work目录
IDEA中使用Tomcat的会在IDEA生成一个work目录
D:\Environment\apache-tomcat-9.0.37\work\Catalina\localhost\ROOT\org\apache\jsp
发现页面变成了java程序,jsp最终会被转换成一个java类
- 浏览器向服务器发送请求,不管访问什么资源,其实都是在访问Servlet
- JSP本质上就是一个servlet
final javax.servlet.jsp.PageContext pageContext;//页面上下文
javax.servlet.http.Httpsession session=null;//Session
final javax.servlet.Servletcontext application;//application
final javax.servlet.ServletConfig config;//config
javax.servlet.jsp.JspWriter out=null;//out
final java.lang.Object page = this;//pag e当前页
HttpServletRequest request;//请求
HttpServletReponse reponse ;//响应
在JSP页面中
只要是JAVA代码就会原封不动的输出
如果是HTML代码,就会被转换为
out.writer("<html>\r\n")
JSP基础语法
jsp表达式
<%=new java.util.Date()%>
jsp脚本片段
<%for(int i = 0;i<10;i++){%>
<p>123</p>
<%}%>
jsp声明
<%!
static {
system. out. println(" Loading Servlet! ");
}
private int globalvar =0;
public void f(){
system. out printIn("进入了方法 ");
}
%>
JSP声明:会被编译到JSP生成ava的类中!其他的,就会被生成到 jspService方法中
<!--我是Html注释->
<%--我是JSP注释--%>
jsp的注释不会在客户端显示,html的注释可以看到
九大内置对象
- PageContext 存东西
- Request 存东西
- Response
- Session 存东西
- Application【ServeltContext】存东西
- config【ServletConfig】
- out
- page 不用了解
- exception
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻,用户看完没用了
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车
application:客户端向服务器发送请求,产生的数据,一个用户用完,其他用户还可以使用,比如:聊天记录
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--http://localhost:8080/jsp01_war_exploded/pageContextDemo01.jsp--%>
<%--内置对象--%>
<%
pageContext.setAttribute("name1","张三");// 保存的数据只在一个页面中有效,在另外一个页面就请求不到了
request.setAttribute("name2","李四");//保存的数据只有在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","王五");//保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","小李");//保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%
// 通过pageContext取出我们保存的值
//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");
//pageContext.forward("/pageContextDemo02.jsp"); 测试request请求转发的作用域
%>
<%--使用EL表达式输出 ${}--%>
<%--一般取值就用EL表达式,比%=好,因为会自动过滤null的值--%>
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
</body>
</html>
JSTL标签、EL表达式(${})
JSTL标签库的使用为了弥补HTML标签不足;它自定义了许多标签,可以供我们使用,标签的功能和java代码一样
核心标签
标签 | 描述 |
---|---|
<c:out> |
用于在JSP中显示数据,就像<%= ... > |
<c:set> |
用于保存数据 |
<c:remove> |
用于删除数据 |
<c:if> |
与我们在一般程序中用的if一样 |
<c;choose> |
本身只当做<c:when>和<c:otherwise>的父标签 |
<c:when> |
<c:choose>的子标签,用来判断条件是否成立 |
<c:otherwise> |
<c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行 |
<cLforeach> |
基础迭代标签,接受多种集合类型 |
<c:url> |
使用可选的查询参数来创造一个URL |
JSTL标签使用步骤
- 引入对应的taglib
- 使用其中的方法
- 在Tomcat也需要引入jstl的包,否则会出现500
- lib目录下
D:\Environment\apache-tomcat-9.0.37\lib
- lib目录下
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>if测试</h4>
<form action="coreif.jsp" method="get">
<%-- EL表达式获取表单中数据--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断如果提交的是用户名是admin就登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员欢迎你"/>
</c:if>
<c:out value="${isAdmin}"/>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:set var="score" value="55" />
<c:choose>
<c:when test="${score>=90}">
优秀
</c:when>
<c:when test="${score>=80}">
良好
</c:when>
<c:when test="${score>=60}">
合格
</c:when>
<c:otherwise >
不及格
</c:otherwise>
</c:choose>
</body>
</html>
JavaBean
javaBean有特定的写法
- 必须有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般和数据库的字段做映射
ORM 对象关系映射
- 表——>类
- 字段——>属性
- 行记录——>对象
注意:一定要每一个字段都和实体类的属性对应
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--stu = new Test();--%>
<jsp:useBean id="test" class="com.jmu.vo.Test" scope="page"/>
<jsp:setProperty name="test" property="id" value="1018" />
<jsp:setProperty name="test" property="name" value="大东" />
<jsp:getProperty name="test" property="id"/>
<jsp:getProperty name="test" property="name"/>
</body>
</html>
MVC三层结构
Filter
Filter:过滤器,用来过滤网站的数据
- 处理中文乱码
- 登录验证
Filter开发步骤:
-
编写过滤器
- 导入不要错
import javax.servlet.*;
- 导入不要错
package com.jmu.fiter;
import javax.servlet.*;
import java.io.IOException;
public class CharacterEncodingFilter implements Filter {
//初始化:web服务器启动,就一起初始化,随时等待过滤对象出现
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("执行前");
filterChain.doFilter(servletRequest,servletResponse);//让我们的请求继续走,如果不行,程序执行到这里就被拦截
System.out.println("执行后");
}
//销毁 web服务器关闭的时候,过滤会销毁
public void destroy() {
System.out.println("销毁");
}
}
- 在web.xml中配置filter
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>com.jmu.fiter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<!-- 只要是/filter/*的任何请求就执行过滤器-->
<url-pattern>/filter/*</url-pattern>
</filter-mapping>
例子
用户登录之后,才能进入主页,用户注销后就不能进入主页
- 用户登录之后,向session放入用户的数据,并且重定向到主页
req.getSession().setAttribute("USER_SESSION",req.getSession().getId());
resp.sendRedirect("/sys/success.jsp");//重定向
- 注销
if(req.getSession().getAttribute("USER_SESSION")!=null){
req.getSession().removeAttribute("USER_SESSION");
}
resp.sendRedirect("/login.jsp");
- 将主页放在sys文件夹中,当session("USER_SESSION")为空的时候,就跳转到登录页面
package com.jmu.fiter;
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 {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//如果没有强转 ServletRequest没有getSession方法
HttpServletRequest req = (HttpServletRequest)servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
if((req.getSession().getAttribute("USER_SESSION"))==null){
resp.sendRedirect("/login.jsp");
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void destroy() {
}
}
xml
<filter>
<filter-name>sysFilter</filter-name>
<filter-class>com.jmu.fiter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sysFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
练习登录
项目搭建
- 搭建一个maven web项目
- 配置tomcat
- 修改web.xml
- 测试项目是否能够跑起来(localhost:8080/)He
- 导入项目中会遇到的jar
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!-- Servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- JSP依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<!-- jstl表达式的依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- standar标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
-
创建项目结构 java main(com.jmu.dao/filter/vo/servlet/service/util) resources
- dao层用来和数据库交互并返回结果
- service业务层(判断用户是否登录成功)
- servlet调用控制层
- filter过滤器
- util工具类
-
编写实体类vo
-
编写基础公共类
- resources中db.properties
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/demo?serverTimezone=GMT&useUnicode=true&characterEncoding=utf8&useSSL=true
username = root
password = 123456
-
编写数据库工具类
-
编写字符编码过滤器filter(上面有写过的)
-
在webapp导入静态资源css js image等等 在webapp下新建static再放
登录功能实现
- 登录页面(在jsp文件夹下新建一个主页home.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--login.jsp--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/login.do" method="post">
用户名 <input type="text" name="username"/><br/>
密码 <input type="password" name="password"/><br/>
<input type="submit" value="登录" />
</form>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--home.jsp--%>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>主页</h1>
<a href="${pageContext.request.contextPath}/logout.do">注销</a>
</body>
</html>
- 在web.xml中将登录页面设为首页,不是index.jsp
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
- 编写接口UserDao
package com.jmu.dao;
import com.jmu.vo.User;
public interface UserDao {
//通过username得到登录的用户
public User getLoginUser(String username);
}
- 编写接口UserDao的实现类UserDaoImpl
package com.jmu.dao;
import com.jmu.util.JdbcUtil;
import com.jmu.vo.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class UserDaoImpl implements UserDao{
@Override
public User getLoginUser(String username) {
Connection conn = null;
PreparedStatement pst =null;
User user = null;
try {
conn = JdbcUtil.getConnection();
String sql = "select * from user where username = ?";
pst = conn.prepareStatement(sql);//预编译
//传递参数
Object[] params = {username};
for(int i = 0;i<params.length;i++){
pst.setObject(i+1,params[i]);
}
ResultSet rs = pst.executeQuery();
while(rs.next()){
int auto_id=rs.getInt("auto_id");
String password=rs.getString("password");
int age=rs.getInt("age");
user = new User(auto_id,username,password,age);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtil.release(conn,pst,null);
}
return user;
}
}
- 编写业务层接口UserService
package com.jmu.service;
import com.jmu.vo.User;
public interface UserService {
//用户登录
public User login(String username, String password);
}
- 业务层实现类UserServiceImpl
package com.jmu.service;
import com.jmu.dao.UserDao;
import com.jmu.dao.UserDaoImpl;
import com.jmu.vo.User;
import org.junit.Test;
public class UserServiceImpl implements UserService {
//业务层都会调用dao层,所以我们要引入Dao层
private UserDao userDao;
public UserServiceImpl(){
userDao = new UserDaoImpl();
}
@Override
public User login(String username, String password) {
User user = null;
user = userDao.getLoginUser(username);
//对比密码
if(user!=null&&user.getPassword().equals(password)){
return user;
}else{
return null;
}
}
@Test
public void test(){
System.out.println(new UserServiceImpl().login("user02","122").toString());
}
}
- 编写servlet
登录servlet
package com.jmu.servlet;
import com.jmu.service.UserService;
import com.jmu.service.UserServiceImpl;
import com.jmu.util.Constants;
import com.jmu.vo.User;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username=req.getParameter("username");
String password=req.getParameter("password");
//和数据库中的密码进行对比 调用业务层
UserService userService=new UserServiceImpl();
User user =userService.login(username,password);
if(user!=null){
//将用户信息保存到session里面
req.getSession().setAttribute(Constants.USER_SESSION,user);
//跳转到主页
resp.sendRedirect(req.getContextPath()+"/jsp/home.jsp");
}else{
//跳转到ERROR
resp.sendRedirect(req.getContextPath()+"/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 注册servlet
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.jmu.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
- 运行测试