Web核心
Web核心
JavaWeb技术栈
- B/S架构:Browser/Server,浏览器/服务器架构模式,它的特点是,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器,获取Web资源,服务器把Web资源发送给浏览器即可
- 好处:易于维护升级,服务器升级后,客户端无需任何部署就可以使用到新的版本
- 静态资源:HTML、CSS、JavaScript、图片等。负责页面展现动态资源: Servlet、JSP等。负责逻辑处理
- 数据库:负责存储数据
- HTTP协议:定义通信规则
- Web服务器:负责解析HTTP协议,解析请求数据,并发送响应数据
Http
-
概念: HyperText Transfer Protocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则
-
HTTP协议特点:
-
基于TCP协议:面向连接,安全
-
基于请求-响应模型的:一次请求对应一次响应
-
HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的。
·缺点:多次请求间不能共享数据。Java中使用会话技术(Cookie、Session)来解决这个问题. -
优点:速度快
-
Http请求数据的格式
-
请求数据分为3部分:
-
请求行:请求数据的第一行。其中GET表示请求方式,/
表示请求资源路径,HTTP/1.1表示协议版本 -
请求头:第二行开始,格式为key: value形式。
-
请求体:POST请求的最后一部分,存放请求参数
-
-
常见的HTTP请求头:
Host:表示请求的主机名
User-Agent:浏览器版本,例如Chrome浏览器的标识类似Mozilla/5.0 ...Chrome/79,IE浏览器的标识类似Mozilla/5.o (Windows NT ...) like Gecko;Accept:表示浏览器能接收的资源类型,如text/,image/或者/表示所有;
Accept-Language:表示浏览器偏好的语言,服务器可以据此返回不同语言的网页;
Accept-Encoding:表示浏览器可以支持的压缩类型,例如gzip, deflate等。
-
GET请求和POST请求区别:
- GET请求请求参数在请求行中,没有请求体。
POST请求请求参数在请求体中 - GET请求请求参数大小有限制,POST没有
- GET请求请求参数在请求行中,没有请求体。
Http响应数据格式
- 响应数据分为三部分
-
- 响应行:响应数据的第一行,其中HTTP/1.1表示协议版本,200表示状态码,OK表示状态码描述
- 响应头:第二行开始,格式为 key:value
- 响应体:最后一部分,存放响应数据
- 常见的Http响应头
-
- Content-Type:表示该响应内容的类型,例如text/html,image/jpeg
- Content-Length:表示该响应内容的长度(字节数)
- Content-Encoding:表示该响应压缩算法:例如gzip
- Cache-control:指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒
响应码
响应码分类:
分类 | 分类描述 |
---|---|
1** | 信息响应,服务器收到请求,需要请求者继续执行操作 |
2** | 成功响应,操作被成功接受并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端响应,请求包含语法错误或无法完成请求 |
5** | 服务器响应,服务器在处理请求的过程中发生了错误 |
常见的响应码:
状态码 | 状态英文名称 | 中文描述 |
---|---|---|
200 | OK | 请求成功。一般用于GET与POST请求 |
201 | Created | 已创建。成功请求并创建了新的资源,通常用于POST或PUT请求 |
301 | Moved Permanently | 永久移动。请求的资源已被永久的移动到新的url,返回信息包括新的url,浏览器会自动定向新url,今后任何新的请求都应使用新的url代替 |
302 | Found | 临时移动。与301类似,但资源只是临时被移动,客户端应继续使用原有的url |
304 | Not Modifiled | 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源(响应信息中不包含响应体)。客户端通常会缓存访问过的资源 |
400 | Bad Request | 语义有误,当前请求无法被服务器理解,除非进行修改,否则客户端不应该重复提交这个请求,或者是请求参数有误 |
401 | Unauthorized | 当前请求需要用户验证 |
403 | Forbidden | 服务器已经理解请求,但是拒绝执行它 |
404 | Not Found | 请求失败,服务器无法根据客户端的请求找到资源(网页) |
408 | Request Timenout | 请求超时,服务器等待客户端发送的请求时间过长,超时 |
500 | Internal Serber Error | 服务器遇到了不知道如何处理的情况 |
501 | Not Implemented | 此请求方法不被服务器支持且无法被处理,只有GET和HEAD是要求服务器支持的,他们必定不会返回此错误代码 |
503 | Service Unavaliable | 服务器没有准备好处理请求,由于超载或系统维护,服务器暂时的无法处理客户端请求 |
TomCat
- Tomcat是一款Apache下面的开源的Servlet容器,实现了对Servlet和JSP规范的支持。另外 Tomcat 本身内含了一个 HTTP 服务器,所以也可以被当作一个 Web 服务器来使用。但是Tomcat作为一个Web服务器,它对静态资源的处理能力要比Apache或者Nginx这类的Web服务器差很多,所以我们经常将Apache和Tomcat(或者是Nginx和Tomcat)组合使用,Apache来充当Web服务器处理静态资源的请求,Tomcat充当Servlet容器来处理动态请求。
- 直接官网下载安装即可 :Apache Tomcat® - Welcome!
- 解决控制台中文乱码问题:打开tomcat conf目录下的logging.properties配置文件,将java.util.logging.ConsoleHandler.encoding = UTF-8改为java.util.logging.ConsoleHandler.encoding = GBK就完成
Tomcat部署项目
- 将项目放置到webapps目录下,即部署完成
- 一般JavaWeb项目会被打成war包,然后将war包放到webapps目录下,Tomcat会自动解压缩war文件
idea中部署:
选择并进入配置
Servlet
- Servlet是Java提供的一门动态web资源开发技术
- Servlet是JavaEE规范之一,其实就是一个接口,将来需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet
Servlet执行流程
- Servlet由web服务器创建,Servlet方法有web服务器调用
- 服务器怎么知道Servlet中一定有Service方法:因为我们自定义的Servlet,必须实现Servlet接口并复写其方法,而Servlet接口中有service方法
Servlet生命周期
- Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为四个阶段:
-
- 加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象
- 初始化:在Servlet实例化之后,容器将调用init()方法初始化这个对象,完成一些如加载配置文件,创建连接等初始化的工作,该方法只调用一次
- 请求处理:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理
- 服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destory()方法完成资源的释放,当destroy方法调用之后,容器就会释放这个Servlet实例,该实例随后会被java的垃圾收集器回收
Servlet urlPattern配置
-
精确匹配:配置路径:@WebServlet("user/select")
-
目录匹配:@WebServlet("user/*")
-
扩展名匹配:@WebServlet("*/do")
-
任意匹配@WebServlet("/")或@WebServlet("/*")
优先级:精确路径>目录路径>扩展名路劲>/*>/
Request和Response
- Request:请求对象 获得请求数据
- Response:响应对象,设置响应数据
Request
获取请求数据
请求行
- String getMethod():获取请求方式:GET
- . String getContextPath(:获取虚拟目录(项目访问路径):/request-demo
- StringBuffer getRequestURLO:获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
- String getRequestURIO:获取URI(统一资源标识符):/request-demo/req1
- . String getQuaryString(:获取请求参数(GET方式) : username=zhangsan&password=123
请求头
- String getHeader(String name):根据请求头名称,获取值
请求体:
- ServletInputStream getInputStream():获取字节输入流.
- BufferedReader getReader():获取字符输入流
Request通用方式获取请求参数
- Map<String,String[]> getParameterMao():获取所有参数Map集合
- String[] getParameterValues(String name):根据名称获取参数值(数组)
- String gerParameter(String Name):根据名称获取参数值单个值
解决中文乱码问题
request.setCharacterEncoding("UTF-8"); //post方式提交的解决乱码
请求转发
- 请求转发(forward):一种在服务器内部的资源跳转方式
- 实现方法:request.getRequestDispatcher("资源B路径").forward(request,response);
- 请求转发资源间共享数据:使用Request对象
-
- void SetAttribute(String name,Object o):存储数据到request域中
- obeject getAttribute(String name):根据key 获取值
- void removeAtrtribute(String name):根据key 删除该健值对
- 请求转发的特点
-
- 浏览器地址路径不发生变化
- 只能转发到当前服务器的内部资源
- 一次请求可以转发的资源间使用request共享数据
Response
响应行
- void setStatus(int sc):设置响应状态码
响应头
- void setHeader(String name,String value):设置响应头健值对
响应体
- PrintWriter getWriter():获取字符输出流
- ServletOutputStream getOutputStream():获取字节输出流
重定向
- 重定向:一种资源跳转方式
- 实现方式:
- resp.setStatus(302); resp.setHeader("location" ,"资源B的路径")
- resp.setresponse.sendRedirect("资源B的路径");
- 特点:
-
- 浏览器地址栏路径发生变化
- 可以重定向到任意位置的资源(服务器内部,外部均可)
- 两次请求,不能在多个资源使用request共享数据、
综合案例
- 创建一个登陆注册页面
- 1.创建html静态登陆和注册页面 :
- 创建数据库连接工具类 以及mybatis等工具的配置 和实体类的创建 数据库的创建等:
mybatis-config:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
Mapper配置文件信息,以及sql语句
<mapper namespace="com.qiu.Mapper.UserMapper">
<insert id="add">
insert into user(username,password) value (#{username},#{password});
</insert>
<select id="select" resultType="com.qiu.Pojo.User">
select * from user where username=#{username} and password=#{password};
</select>
<select id="selectun" resultType="com.qiu.Pojo.User">
select * from user where username=#{username};
</select>
</mapper>
UserMapper接口
public interface UserMapper {
User select(@Param("username")String username,@Param("password")String password);
User selectun(String username);
void add(@Param("username")String username,@Param("password")String password);
}
html静态文本的设置:
<form action="/untitled_war/Servlet" method="post" id="form">
登陆表单的action 和method设置
<form id="reg-form" action="/untitled_war/ServletDemo02" method="post">
注册表单的action 和method设置
- 编写sqlsession工具类以及servlet实现类
private static SqlSessionFactory sqlSessionFactory;
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
servlet实现:
@WebServlet("/Servlet")
public class Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
/** String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);*/
SqlSessionFactory sqlSessionFactory = SqlSessionFactorutils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.select(username, password);
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
if (user!=null){
writer.write("登陆成功");
}else{
writer.write("登陆失败");
}
sqlSession.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
@WebServlet("/ServletDemo02")
public class ServletDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
// String resource = "mybatis-config.xml";
// InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactory sqlSessionFactory = SqlSessionFactorutils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectun(username);
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
if (user==null){
mapper.add(username,password);
sqlSession.commit();
writer.write("注册成功");
}else {
writer.write("注册失败,请重新输入账号密码");
}
sqlSession.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
至此完成
JSP
Jsp原理
- 概念: Java Server Pages,Java服务端页面
- JSP = HTML + Java,用于简化开发的JSP本质上就是一个Servlet
- JSP在被访问时,由JSP容器(Tomcat)将其转换为Java文件(Servlet),在由JSP容器(Tomcat)将其编译,最终对外提供服务的其实就是这个字节码文件
JSP脚本
- JSP脚本用于在JSP页面内定义Java代码
- JSP脚本分类:
-
- <%...%>:内容会直接被放到_jspService()方法之中
- <%=...%>:内容会被放到out.print()中,作为out.print()的参数
- <!%...%>:内容会放到_jspService()方法之外,被类直接包含
JavaWeb中的四大域对象
- page:当前页面有效
- request:当前请求有效
- session:当前对话有效
- application:当前应用有效
MVC与三层模式
MVC模式
- MVC是一种分层开发的模式,其中:
- M:Mode,业务模型,处理业务
- V:view,视图,界面展示
- C:Controller,控制器,处理请求,调用模型和视图
- MVC的好处:
-
- 职责单一,互不影响
- 有利于分工协作
- 有利于组件重用
三层架构模式
- 数据访问层:对数据库的CRUD基本操作
- 业务逻辑层:对业务逻辑进行封装,组合数据访问层中基本功能,形成复杂的业务逻辑功能
- 表现层:接受请求,封装数据,调用业务逻辑层,响应数据
会话跟踪
-
会话:用户打开浏览器,访问web服务器的资源,会话建立,知道有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应
-
会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同义词会话的多次请求间共享数据
-
http协议是无状态的,每次浏览器向服务器请求时,服务区都会将请求视为新的请求,因此我们需要会话跟踪技术来实现会话内数据共享
-
实现方法:1, 客户端会话跟踪技术:Cookie 2.服务端会话跟踪技术:session
Cookie
Cookie的基本使用
- cookie:客户端会话技术,将数据保存到客户端,以后每次请求都携带Cookie数据进行访问
- Cookie基本使用:
-
- 创建Cookie对象,设置数据,并发送Cookie到客户端,使用response对象
Cookie cookie = new Cookie("username","xiaoqiu"); //创建Cookie对象,设置数据
response.addCookie(cookie); //发送Cookie到客户端,使用response对象
- 2.接受Cookie对象 并遍历
Cookie[] cookies = request.getCookies();
String name="username";
for (Cookie cookie : cookies) {
if(cookie.getName().equals(name))
{
String value = cookie.getValue();
System.out.println(name+":"+value);
break;
}
}
Cookie的注意事项
- Cookie的存活时间:
- 默认情况下,Cookie存储在浏览器内存中,当浏览器关闭,内存释放,则Cookie被销毁setMaxAge(int seconds):设置Cookie存活时间
- 正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除
- 负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
- 零:删除对应Cookie
Cookie cookie = new Cookie("username",username);
cookie.setMaxAge(60*60*24*7);
- Cookie存储中文:cookie不能直接存储中文,但是可以通过编解码来实现:
username=URLEncoder.encode(username,"UTF-8");
Session
-
服务端会话跟踪技术:将数据保存到服务端
-
JavaEE提供了HttpSession接口,来实现一次会话的多次请求间数据共享功能
-
使用:
-
-
获取Session对象:
-
HttpSession session=request.getSession();
-
Session对象的功能:
-
void setAttribute(String name, Object o):存储数据到session域中
-
Object getAttribute(String name):根据key,获取值
-
void removeAttribute(String name):根据key,删除该键值对
-
Session使用细节
-
Session钝化,活化:
- 钝化:在服务器正常关闭后,Tomcat会自动将Session数据写入硬盘的文件中
- 活化:再次启动服务器后,从文件中加载数据到Session中
-
Session销毁:
-
默认情况下,无操作,30分钟自动销毁
-
<session-config> <session-timeout>30</session-timeout> </session-config>
-
调用Session对象的invalidate()方法
-
Session和Cookie的不同
- 存储位置:Cookie是将数据存储在客户端,Session将数据存储在服务端
- 安全性: Cookie 不安全,Session安全
- 数据大小:Cookie最大3KB,Session无大小限制
- 存储时间:Cookie 可以长期存储,Session默认30分钟
- 服务器性能:Cookie不占服务器资源,Session占用服务器资源
Filter
- 概念:Filter表示过滤器,是JavaWeb三大组件(Servlert,Filter,listenner)之一
- 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
- 过滤器一般完成一些通用的操作,比如:权限控制,统一编码处理,敏感字符处理等
Filter的执行流程
- 放行后访问对应资源,资源访问完成后,还会回到Filter中
- 回到Filter中,将执行放行后的逻辑
Filter的路径配置
- Filter可以根据需求,配置不同的拦截资源路径@WebFilter(" /*")
- 拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截。
- 目录拦截:/user/*:访问/user下的所有资源,都会被拦截
- 后缀名拦截: .jsp:访问后缀名为jsp的资源,都会被拦截拦截所有:
- /*:访问所有资源,都会被拦截
过滤器链
- 一个web应用,可以配置多个过滤器,这多个过滤器被称为过滤器链
案例
/**
* 登陆验证的过滤器
*/
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req= (HttpServletRequest) request;
//判断是否进入的是登陆或者注册网站
String[] url={"/css/","/imgs/","/login.jsp","/LoginServlet","/checkCodeServlet","/registerServlet","register.jsp"};
String requestURL = req.getRequestURL().toString();
for (String s : url) {
if(requestURL.contains(s)){
chain.doFilter(request, response);
return;
}
}
//判断是否登陆
HttpSession session = req.getSession();
Object user = session.getAttribute("user");
if(user!=null){
//已经登陆
chain.doFilter(request, response);
}else {
//没有登陆 跳转到登陆界面 并给出提示信息
session.setAttribute("login_msg","尚未登录,请先登陆");
req.getRequestDispatcher("login.jsp").forward(req,response);
}
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
Listener
- 概念: Listener表示监听器,是JavaWeb三大组件(Servlet、Filter、Listener)之一。
- 监听器可以监听就是在application,session,request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件
- Listener分类: JavaWeb中提供了8个监听器