第一章、Servlet(Java EE)

1. web开发概述

web开发,将开发的程序部署在服务器中,通过浏览器访问(http请求),在java后端接收、处理、响应。

服务器:

狭义上:指一种软件,里面可以存放文件,别人可以访问,服务器可以做出回应。

广义上:硬件(云服务机房) + 软件

总之:服务器是一个容器(部署项目),是连接用户与程序之间的中间件。

2. web开发环境搭建

第一步:获取Tomcat安装程序包

第二步:(1)设置JAVA_HOME环境变量(D:\Program Files\Java\jdk1.8.0_261)

              (2) 设置PATH环境变量(配置JDK)

第三步:解压tomcat压缩文件

第四步:双击 bin 目录下的 startup.bat 文件

              输入 http://localhost:端口号 或 http:127.0.0.1:端口号 或 局域网ip:端口号 

3. 创建发布web项目

1. 创建java项目,添加web功能

2. 发布web应用到服务器

3. 在WEB-INF中创建 lib 文件,并将要用的jar包放在lib文件中。

注:自动将web应用发布到web服务器下,需要在开发工具中集成tomcat进

4. Servlet概述

 Servlet是Server Applet的简称,意思为用Java编写的服务器端的程 序.

它运行在web服务器中,web服务器负责Servlet和客户的通信以及调 用Servlet方法

server  ==  用java写的服务器端程序。

Servlet的作用:

  1.    接收客户端的请求
  2.    调用其他程序处理请求(dao,JDBC等)
  3.    根据处理的结果向客户端做出相应。

5. Servlet创建和概述

web.xml 是 web 项目中的配置文件。在服务器启动时,有服务器加载启动。
1、创建一个类继承javax.servlet.http包下的HttpServlet

 继承HttpServlet ,我们的类,就具备 servlet 功能(接收、处理、响应)

(1)无参的构造方法:服务器在创建Servlet 对象,调用构造方法,只调用了一次

 public DemoServlet() {
        System.out.println("无参的构造方法");
    }

(2)init()方法(初始化):初始化Servlet,ServletConfig config:   用来获取Servlet中的一些参数信息。如果没有什么可以初始化的内容,此方法可以不用·重写,但是服务器会调用,只会调用父类中的Servlet的init()只调用一次;

  @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init");
    }

(3)service() 方法:提供服务。HttpServletRequest : 表示请求,客户端请求的数据,都分装在此对象中。  HttpServletResponse:表示响应,用来为客户端响应数据。(只多次调用)

@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("service");
    }

(4)destroy()方法:在servlet对象销毁前,会调用destroy(),一般是在关闭服务器时,在此方法中,可以执行一些最终想要的操作,例如保存日志...。如果没有,也可以不用重写,但是服务器还会调用,可以调用父类中的。(只调用一次)

@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("service");
    }

总体代码:

  • 构造方法 默认存在
  • init() 父类有
  • service() 父类有, 判断请求方式,调用doGet或doPost
  • destroy() 父类有
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//    继承 HttpServlet ,我们的类就具有了 servlet 功能(接收、处理、响应)
public class DemoServlet extends HttpServlet {
    /*
    服务器在创建Servlet对象时,调用构造方法。
    在第一次访问 Servlet 时创建 Servlet 对象,调用构造方法,只调用了一次
     */
    public DemoServlet() {
        System.out.println("无参的构造方法");
    }
    /*
     初始化 Servlet ,ServletConfig : 用来获得Servlet中的一些参数信息
     如果没有什么可以初始化的内容
    */
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init");
    }
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("service");
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }

}

 2、在web.xml文件中配置Servlet

3、运行Servlet程序 通过浏览器访问http:localhost:8080/ 项目名/配置的url

4、客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被 外界访问,必须把servlet程序映射到一个URL地址上,这个工作在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">
<!--   配置注册servlet-->
    <servlet>
        <!--生成的对象名,只有一个,只创建一个Servlet 对象-->
        <servlet-name>demo</servlet-name>
        <!--配置类的地址,由服务器创建Sevlet 对象,通过反射机制创建-->
        <servlet-class>demoserver.DemoServlet</servlet-class>
<!--        配置一个参数-->
        <init-param>
            <param-name>count</param-name>
            <param-value>10</param-value>
        </init-param>
<!--        配置服务器启动时,就创建Servlet对象-->
        <load-on-startup>0</load-on-startup>
    </servlet>
<!--    为servlet提供一个前端访问地址-->
    <servlet-mapping>
        <servlet-name>demo</servlet-name>
<!--        http://127.0.0.1:8080/backServer/demo -->
        <url-pattern>/demo</url-pattern>
    </servlet-mapping>
</web-app>

 

6. Servlet生命周期

  1. 实例化。构造方法:只调用一次,只有第一次访问Servelt时或服务器启动时 创建Servlet实例
  2. 初始化。Init方法:只被调用一次,在Servlet实例创建好实例后立即执行, 用于执行一些初始化Servlet的操作
  3. 服务。service方法:多次调用,每次请求都调用service方法,根据请求方式 调用doGet()或doPost()方法。
  4. 消亡。destroy:只被调用一次,在服务器关闭时调用,执行一些操作。

7. http协议,http请求

http协议

在网页中点一个http击超链接,提交表单都是向服务器端发送http请求。一个http 请求,包含三部分:

  •    请求行
  •    请求头:包括请求地址、方式、客户端信息。
  •    请求体:百世post请求中的数据都是在请求体中。

http请求(get和post的区别)

get主要用于从服务器端获取数据,传递少量的数据,获取大量数据,在地址中拼接携带的,一个是不安全的(相对于post),传递数据量小。

在servlet 中使用doget(),处理get请求。

post主要用于向服务器发送数据,注册、登录、提交表单等用post,post数据在请求体中存储,相对安全,且传输的数据量大,上传文件都是post。

在servlet 中使用doPost(),处理post请求。

HttpServletRequest(接口) :对象表示请求,所用请求数据都包装在此对象中。是由某个子类实现的,org.apache.catalina.connector.RequestFacade@255a0e9b

model层

package model;

public class User {
    int id;
    String account;
    String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", account='" + account + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

dao层(连接数据库  查询验证账号密码是否正确)

package dao;

import model.User;

import java.sql.*;

public class LoginDao {

    public User checkLogin(String account, String password) throws ClassNotFoundException, SQLException {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        User user = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = "jdbc:mysql://127.0.0.1:3306/school?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
            connection = DriverManager.getConnection(url,"root", "123456");
            ps = connection.prepareStatement("select id,account from user where account =? and password =? ");
            ps.setObject(1, account);
            ps.setObject(2, password);
            rs =   ps.executeQuery();
            while(rs.next()){
                user = new User();
                user.setId(rs.getInt("id"));
                user.setAccount(rs.getString("account"));
            }
            return user;
        }finally {
            if(ps!=null){
                ps.close();
            }
            if (connection!=null){
                connection.close();
            }
        }

    }
}

servic层


import dao.LoginDao;
import model.User;

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 LoginServlet extends HttpServlet {


    /*
      处理get请求
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
    }

    /*
      处理post请求
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         //转码  post请求中文接收时解码格式不是utf-8,接收前设置解码格式
         req.setCharacterEncoding("utf-8");
         //接收表单请求数据
         String account =  req.getParameter("account");
         String password =  req.getParameter("password");

         //调用dao  连接数据库  查询验证账号密码是否正确
        LoginDao loginDao = new LoginDao();
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = null;
        try {
            out = resp.getWriter();
            User user =  loginDao.checkLogin(account,password);
               if(user!=null){
                   out.print(user);
               }else{
                   out.print(user);
                   out.print("账号或密码错误");
               }
        } catch (Exception e) {
            e.printStackTrace();
            out.print("系统忙!");
        }
    }
}

前端

直接通过submit 提胶片表单到后端服务器,这种方式属于同步提交,服务器响应回来的内容会将整个网页覆盖,会影响前端页面中的正常操作。

在现在的前后端分离开发模式中,前端向后端发送请求,都是异步发送。

何为异步发送?

      异步发送的本质是使用浏览器中提供的一个js对象,就是XMLHttpRequest,使用此对象异步向服务器发送请求,后端响应的内容会反馈给XMLHTTPRequest对象,再从js中把响应的内容更新到网页的某个标签上,整个过程页面不会被覆盖,不会刷新。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script type="text/javascript">
			function login(){
				var httpobj = new XMLHttpRequest();
				httpobj.open("POST","http://127.0.0.1:8080/backServer/login",true);
				httpobj.send();
				httpobj.onreadystatechange = function(){
					document.getElementById("accountMsgId").innerHTML = httpobj.responseText;
				}
				
			}
		</script>
	</head>
	<body>
		  <form>
			  账号<input type="text" name="account" /> <br/>
			    <span id="accountMsgId"></span> <br/>
			  密码<input type="password" name="password" /> <br/>
			  <input type="button" value="登录"  onclick="login()"/>
		  </form>
	</body>
</html>
  • getMethod()得到客户机请求方式
  • getScheme()请求协议
  •  getRemoteAddr()返回发出请求的客户机的IP地址
  • getServerName()服务器名(ip或域名)
  • getServerPort()服务器端口 http请求
  • getParameter(name) --- String 通过name获得值
  • getParameterValues --- String[ ] 通过name获得多值
  •  处理中文乱码 post setCharacterEncoding(编码格式)

 前端:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
	</head>
	<body>
		
		  <form action="http://127.0.0.1:8888/backServer/login" method="post">
			  账号<input type="text" name="account" /> <br/>
			  密码<input type="password" name="password" /> <br/>
			       <!-- 只提交选中的-->
			  性别<input type="radio" name="gender" value="男" />男 <br/>
			      <input type="radio" name="gender" value="女" />女 <br/>
			  省份<select name="province">
				    <option value="101">北京</option>
					<option value="102">上海</option>
					<option value="103">石家庄</option>
			      </select>	  <br/>
		      爱好<input type="checkbox" name="hobby"  value="打游戏"/>	打游戏	  
				  <input type="checkbox" name="hobby"  value="打球"/>	打球  
				  <input type="checkbox" name="hobby"  value="敲代码"/>	敲代码	  
			  <input type="submit" value="登录" />
		  </form>
	</body>
</html>

后端(servlet)

 @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         //转码  post请求中文接收时解码格式不是utf-8,接收前设置解码格式
         req.setCharacterEncoding("utf-8");
         //接收表单请求数据
         String account =  req.getParameter("account");
         String password =  req.getParameter("password");
         String gender =  req.getParameter("gender");
         String province =  req.getParameter("province");
         String[] hobby =  req.getParameterValues("hobby");//接收name相同的多个值
         System.out.println(account+":"+password+":"+gender+":"+province+":"+ Arrays.toString(hobby));
         //接收请求行,请求头中的数据
         System.out.println(req.getMethod());
         System.out.println(req.getScheme());
         System.out.println(req.getProtocol());
         System.out.println(req.getRemoteAddr());//获得客户机ip
         System.out.println(req.getRemotePort());
         System.out.println(req.getServerName());
         System.out.println(req.getServerPort());
         System.out.println(req.getContentLength());
         System.out.println(req.getHeader("User-Agent"));
         //调用dao  连接数据库  查询验证账号密码是否正确
        LoginDao loginDao = new LoginDao();
        //User user =  loginDao.checkLogin(account,password);

         resp.setContentType("text/html;charset=utf-8");
        //根据处理的结果,向前端响应
        resp.getWriter().print("<h1>登录成功</h2>");
    }

8. http响应

  •     HttpServletResponse 是 ServletResponse 的子接口。
  •     Web 服务器收到客户端的http 请求,会针对每一次请求,分别创建一个代表响应的HttpServletResponse 对象。
  • HttpServeltResponse 对象代表响应。

    一个http响应代表服务器向客户端回送的数据,它包括:响应行,响应头,响应体。

响应行里包含了http协议版本,以及用于描述服务器对请求的处理结果。

状态码:服务器和浏览器用于确定状态的固定数字号码。

  例: 

  •   200 :请求成功
  •   302 :请求重定向
  •   400 :语义有无,当前请求无法被服务器理解或请求参数有误
  •   404 :请求资源不存在,通常是路径写错了或者服务器资源删除了
  •   500 :服务内部错误(代码异常)

9. 过滤器

作用:对服务器Web资源进行拦截。

跨服务器访问:
前后端分离开发,前端一个服务器,后端一个服务器;在发送ajax 请求时,浏览器有一个安全限制(默认是遵守同源策略);只要请求协议,域名/ip,端口有一个不同,就是称为跨域访问。

解决方法:前端解决和后端解决。

Servlet API 中,与过滤器有关的API共有三个接口,分别是:

  • Filter
  • FilterChain
  • FilterConfig

 Filter接口是过滤器类必须实现的接口,该接口中有三个方法。

  • init(FilterConfig filterConfig):该方法是对filter 对象进行初始化的方法,仅在容器初始化filter对象结束后被调用一次。参数FilterConfig 可以获得filter 的初始化的参数。
  • doFilter(ServletRequest request,ServletResponse response,FilterChain chain): 该方法是filter进行过滤操作的方法,是最重要的方法。过滤器实现类必须实现该方法。方法体中可以对request和response进行预处理。其中FilterChain 可以将处理后的request =和 response 对象传递到过滤链上的下一个资源。
  • destroy():该方法在容器销毁过滤器对象前被调用。

过滤器的作用:

  •  过滤器用来实现通用的功能,减少代码冗余,提高可维护性
  •  一个过滤器可以配置给多个资源使用
  •  一个资源也可以配置多个过滤器,按照配置顺序调用 

1. 跨域过滤器

public class CorsFilter implements Filter {
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        System.out.println("跨域过滤器");
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        //允许携带Cookie时不能设置为* 否则前端报错
        httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("origin"));//允许所有请求跨域
        httpResponse.setHeader("Access-Control-Allow-Methods", "*");//允许跨域的请求方法GET, POST, HEAD 等
        httpResponse.setHeader("Access-Control-Allow-Headers", "*");//允许跨域的请求头
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");//是否携带cookie

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

     配置文件(web.xml)

    <filter>
        <filter-name>cors</filter-name>
        <filter-class>filter.CorsFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>cors</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

2. 编码过滤器

public class EnCodingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("编码过滤器");
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

 略(与跨域过滤器配置文件)

3. 验证用户是否登录是否失效过滤器

public class IsLoginFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("后端验证用户是否登录失效过滤器");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        if(user == null){
            servletResponse.getWriter().print(201);
        }else{
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
}

 配置文件(web.xml)

    <filter>
        <filter-name>islogin</filter-name>
        <filter-class>filter.IsLoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>islogin</filter-name>
        <url-pattern>/back/*</url-pattern>
    </filter-mapping>

10. web会话跟踪机制

如何将后端更多的信息,传递到前端去?

json 是一种轻量级的数据交换格式,已经成为前后端数据交换的规范。

    java对象 --->  json格式(字符串)---> 前端js(转为js 对象)

会话:是打开浏览器,成功连接到后端服务器开始,到关闭浏览器,整个过程称为一次会话。

会话对象(HttpSession):session 对象用于服务器端存储用户信息,会话 id 作为客户端和服务器之间身份识别。打开浏览器,成功连接到后端服务器开始,到浏览器关闭,整个过程称为一次会话。

HttpSession接口: 会话对象是Web容器创建的,在Servlet中使用 HttpServletRequest中的方法获得会话对象。session对象

     public HttpSession getSession():获取跟当前请求相关的 session,如果不存在session,就创建一个新的session对象返回。 

session实现会话机制的过程:

   当一个客户端向服务器第一次发送请求时,服务器会创建一个Httpsession 对象,,此对象会生成一个id 号,就将此id号响应到浏览器,在浏览器中保存。

浏览器:

id 保存在浏览器中;之后的每次请求,都把此id 号放在请求头中国,向后端发送,浏览器中的id也是会话级别的,关闭即消失。

服务器:

  接收请求时,在服务器端的众多的Httpsession 中找到对应的会话对象;如果找不到,就会创建一个新的对象。

登录成功后,开始了与后端服务的会话,此时生成HttpSession对象,req.getSession();获得session,第一次请求中,没有会话id,会新建一个会话对象,之后的请求中,如果有会话id,去找对应id 的Session对象。

HTTPSession session = req.getSession();

session.setAttribute("user",user);

在后端的session对象中存储用户信息,服务器会响应会话 id。

  • setAttribute(String key,Object value)     以key/value的形式保存对象值
  • getAttribute(String key) 通过key获取对象值
  • removeAttribute(String key) 通过key删除属性
  • getMaxInactiveInterval() 获取session的有效非活动时间,以秒为单位
  • setMaxInactiveInterval (int interval ) 设置session的最大非活动时间,以秒为单位, 超时将被销毁。
  • getId() 获取session对象的编号
  • invalidate() 设置session对象失效
  • isNew() 判断一个session是不是一个新创建的会话对象  

会话对象的生命周期

开始于成功连接到后端服务,使用req.getSesstion() 获得 session 开始。

  • 当容器创建一个新的HttpSession对象后,即生成一个随机数,称为 会话ID,并将ID值封装成一个名字为JSESSIONID的session,返回给 客户端。 
  • 调用request.getSession()方法获得会话对象时,容器先从request 中获取JSESSIONID值,根据JSESSIONID值查找到对应的会话对象, 返回使用。 
  • 如果没有获取到JSESSIONID值,认为当前的请求没有相关联的会话 对象,重复步骤1

销毁:

  •      服务器关闭
  •      到达最大的非活动时间(服务器会销毁,退出时,强制销毁session)
  •      使用req.invalidate();

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值