TomCat

TomCat

web相关概念回顾

1. 软件架构
    1. C/S:客户端/服务器端
    2. B/S:浏览器/服务器端
​
2. 资源分类
    1. 静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源.静态资源可以直接被浏览器解析
        * 如: html,css,JavaScript
    2. 动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资源,在返回给浏览器
        * 如:servlet/jsp,php,asp....
3. 网络通信三要素
    1. IP:电子设备(计算机)在网络中的唯一标识。
    2. 端口:应用程序在计算机中的唯一标识。 0~65536
    3. 传输协议:规定了数据传输的规则
        1. 基础协议:
            1. tcp:安全协议,三次握手。 速度稍慢
            2. udp:不安全协议。 速度快

web服务器软件:

* 服务器:安装了服务器软件的计算机
* 服务器软件:接收用户的请求,处理请求,做出响应
* web服务器软件:接收用户的请求,处理请求,做出响应。
    * 在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目
    * web容器
* 常见的java相关的web服务器软件:
    * webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
    * webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
    * JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。
    * Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范servlet/jsp。开源的,免费的。
* JavaEE:Java语言在企业级开发中使用的技术规范的总和,一共规定了13项大的规范
​
* Tomcat:web服务器软件
    1. 下载:http://tomcat.apache.org/
    2. 安装:解压压缩包即可。
        * 注意:安装目录建议不要有中文和空格
    3. 卸载:删除目录就行了
    4. 启动:
        * bin/startup.bat ,双击运行该文件即可
        * 访问:浏览器输入:http://localhost:8080 回车访问自己
                          http://别人的ip:8080 访问别人
        
        * 可能遇到的问题:
            1. 黑窗口一闪而过:
                * 原因: 没有正确配置JAVA_HOME环境变量
                * 解决方案:正确配置JAVA_HOME环境变量
​
            2. 启动报错:
                1. 暴力:找到占用的端口号,并且找到对应的进程,杀死该进程
                    * netstat -ano
                2. 温柔:修改自身的端口号
                    * conf/server.xml
                    * <Connector port="8888" protocol="HTTP/1.1"
                       connectionTimeout="20000"
                       redirectPort="8445" />
                    * 一般会将tomcat的默认端口号修改为80。80端口号是http协议的默认端口号。
                        * 好处:在访问时,就不用输入端口号
    5. 关闭:
        1. 正常关闭:
            * bin/shutdown.bat
            * ctrl+c
        2. 强制关闭:
            * 点击启动窗口的×
    6. 配置:
        * 部署项目的方式:
            1. 直接将项目放到webapps目录下即可。
                * /hello:项目的访问路径-->虚拟目录
                * 简化部署:将项目打成一个war包,再将war包放置到webapps目录下。
                    * war包会自动解压缩
​
            2. 配置conf/server.xml文件
                在<Host>标签体中配置
                <Context docBase="D:\hello" path="/hehe" />
                * docBase:项目存放的路径
                * path:虚拟目录
​
            3. 在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写
                <Context docBase="D:\hello" />
                * 虚拟目录:xml文件的名称
        
        * 静态项目和动态项目:
            * 目录结构
                * java动态项目的目录结构:
                    -- 项目的根目录
                        -- WEB-INF目录:
                            -- web.xml:web项目的核心配置文件
                            -- classes目录:放置字节码文件的目录
                            -- lib目录:放置依赖的jar包
                    
  • 将Tomcat集成到IDEA中,并且创建JavaEE的项目,部署项目。

ieda配置tomcat

  1. IDEA会为每一个tomcat部署的项目单独建立一份配置文件

    • 查看控制台的log:Using CATALINA_BASE: "C:\Users\fqy.IntelliJIdea2018.1\system\tomcat_itcast"

  2. 工作空间项目 和 tomcat部署的web项目

    • tomcat真正访问的是“tomcat部署的web项目”,"tomcat部署的web项目"对应着"工作空间项目" 的web目录下的所有资源

    • WEB-INF目录下的资源不能被浏览器直接访问。

  3. 断点调试:使用"小虫子"启动 dubug 启动

乱码:

D:\apache\apache-tomcat-9.0.53\conf

logging.properties

java.util.logging.ConsoleHandler.encoding = UTF-8 -> GBK

或者:

idea help VM 加 -Dfile.encoding=UTF-8

(cmd亦然乱码)

*Servlet:服务器

Servlet(程序): server applet

  • 概念:运行在服务器端的小程序

    • Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。

    • 将来我们自定义一个类,实现Servlet接口,复写方法。

  • <!--配置Servlet -->
        <servlet>
            <servlet-name>demo1</servlet-name>
            <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
        </servlet>
    ​
    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>
    * 步骤:
        1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
        2. 定义一个类,实现Servlet接口
        3. 复写方法
        4. 在类上使用@WebServlet注解,进行配置
            * @WebServlet("资源路径")
              @Target({ElementType.TYPE})
              @Retention(RetentionPolicy.RUNTIME)
              @Documented
            public @interface WebServlet {
                String name() default "";//相当于<Servlet-name>
                String[] value() default {};//代表urlPatterns()属性配置
                String[] urlPatterns() default {};//相当于<url-pattern>
                int loadOnStartup() default -1;//相当于<load-on-startup>
                WebInitParam[] initParams() default {};
                boolean asyncSupported() default false;
                String smallIcon() default "";
                String largeIcon() default "";
                String description() default "";
                String displayName() default "";
            }

执行原理:

  1. 执行原理:

  1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
  2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。
  3. 如果有,则在找到对应的<servlet-class>全类名
  4. tomcat会将字节码文件加载进内存,并且创建其对象
  5. 调用其方法
        1.解析请求路径
            2.将路径中的/demo1 ,去和web.xml配置文件中的<url-pattern>内容进行匹配
            3.如果匹配上了就会访问<servlet-class>体指向的servlet

生命周期:

  1. Servlet中的生命周期方法:

    1. 被创建:执行init方法,只执行一次

      Servlet什么时候被创建?

      • 默认情况下,第一次被访问时,Servlet被创建

      • 可以配置执行Servlet的创建时机。

        • 在<servlet>标签下配置

          1. 第一次被访问时,创建

            • <load-on-startup>的值为负数

              1. 在服务器启动时,创建 * <load-on-startup>的值为0或正整数

      • Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的

      • 多个用户同时访问时,可能存在线程安全问题。

      • 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值

    2. 提供服务:执行service方法,执行多次

      • 每次访问Servlet时,Service方法都会被调用一次。

    3. 被销毁:执行destroy方法,只执行一次

      • Servlet被销毁时执行。服务器关闭时,Servlet被销毁

      • 只有服务器正常关闭时,才会执行destroy方法。

      • destroy方法在Servlet被销毁之前执行,一般用于释放资源

体系结构

  1. Servlet的体系结构

    1. Servlet -- 接口 | GenericServlet -- 抽象类 | *** HttpServlet -- 抽象类

    • GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象

    • 将来定义Servlet类时,可以继承GenericServlet,实现service()方法即可

    • HttpServlet:对http协议的一种封装,简化操作

    1. 定义类继承HttpServlet

    2. 复写doGet/doPost方法

相关配置

  1. Servlet相关配置

  1. urlpartten:Servlet访问路径
   2. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})
   3. 路径定义规则:
        		1. /xxx:路径匹配
                		2. /xxx/xxx:多层路径,目录结构
    		3. *.do:扩展名匹配

Servlet执行原理:

*HTTP:

概念:Hyper Text Transfer Protocol 超文本传输协议 * 传输协议:定义了,客户端和服务器端通信时,发送数据的格式 * 特点: 1. 基于TCP/IP的高级协议 2. 默认端口号:80 3. 基于请求/响应模型的:一次请求对应一次响应 4. 无状态的:每次请求之间相互独立,不能交互数据

  • 历史版本:

    • 1.0:每一次请求响应都会建立新的连接

    • 1.1:复用连接

请求消息数据格式

  • 请求消息数据格式

    1. 请求行 请求方式 请求url 请求协议/版本 GET /login.html HTTP/1.1

    请求方式:

    • HTTP协议有7中请求方式,常用的有2种

      • GET:

        1. 请求参数在请求行中,在url后。

        2. 请求的url长度有限制的

        3. 不太安全

      • POST:

        1. 请求参数在请求体中

        2. 请求的url长度没有限制的

        3. 相对安全

    1. 请求头:客户端浏览器告诉服务器一些信息 请求头名称: 请求头值

      • 常见的请求头:

        1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息

          • 可以在服务器端获取该头的信息,解决浏览器的兼容性问题

      1. Referer:http://localhost/login.html

        • 告诉服务器,我(当前请求)从哪里来?

          • 作用:

            1. 防盗链:

              1. 统计工作:

    2. 请求空行 空行,就是用于分割POST请求的请求头和请求体的。

    3. 请求体(正文):

      • 封装POST请求消息的请求参数的

  • 字符串格式:

    POST /login.html	HTTP/1.1
    	Host: localhost
    	User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
    	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8		(移除。*/)
    	Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
    	Accept-Encoding: gzip, deflate
    	Referer: http://localhost/login.html
    Connection: keep-alive
    	Upgrade-Insecure-Requests: 1

  • 例:username=zhangsan

响应消息数据格式

  • 响应消息数据格式

    • 响应消息:服务器端发送给客户端的数据

      响应行

      1. 格式:协议/版本 响应状态码 状态码描述

      2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。

        1. 状态码都是3位数字

        2. 分类:

          1. 1xx:服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多状态码

          2. 2xx:成功。代表:200

          3. 3xx:重定向。代表:302(重定向),304(访问缓存)

          4. 4xx:客户端错误。

            • 代表:

              • 404(请求路径没有对应的资源)

              • 405:请求方式没有对应的doXxx方法

          5. 5xx:服务器端错误。代表:500(服务器内部出现异常)

    • 响应头:服务器告诉客户端的一些信息

      1. 格式:头名称: 值

        1. 常见的响应头:

          1. Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式

            1. Content-disposition:服务器告诉客户端以什么格式打开响应体数据

              • 值:

                • in-line:默认值,在当前页面内打开

                  • attachment;filename=xxx:以附件形式打开响应体。文件下载

          2. 响应空行

          3. 响应体:传输的数据

    • * 响应字符串格式
      		HTTP/1.1 200 OK
      		Content-Type: text/html;charset=UTF-8
      		Content-Length: 101
      		Date: Wed, 06 Jun 2018 07:08:42 GMT
      
      		<html>
      		  <head>
      		    <title>$Title$</title>
      		  </head>
      		  <body>
      		  hello , response
      		  </body>
      		</html>

*Request(请求):

②如果把变量放到request里,就说明它的作用域是request,它的有效范围是当前请求周期。 所谓请求周期:就是从Http请求发起,到服务器处理结束,返回响应的整个过程。在这个过程中可能使用forward的方式跳转了多个JSP页面,在这些页面里,你都可以使用这个变量。

操作基础信息:头、行、体

  1. request对象和response对象的原理

    1. request和response对象是由服务器创建的。我们来使用它们

  2. request对象是来获取请求消息

    response对象是来设置响应消息

  3. request对象继承体系结构: ServletRequest -- 接口 | 继承 HttpServletRequest -- 接口 | 实现 org.apache.catalina.connector.RequestFacade 类(tomcat)

  4. request功能

  5. 获取请求消息数据

    1. 获取请求行数据

    • GET /day14/demo3?name=lisi HTTP/1.1

    • 方法
      获取请求方式 :GETString getMethod()
      (*)获取虚拟目录:/String getContextPath()
      获取Servlet路径: /demo1String getServletPath()
      获取get方式请求参数:name=zhangsanString getQueryString()
      (*)获取请求URI:/day14/demo3String getRequestURI()
      (*)获取请求URLhttp://localhost/day14/demo1StringBuffer getRequestURL()
      获取协议及版本:HTTP/1.1String getProtocol()
      获取客户机的IP地址:192.168.157.53String getRemoteAddr()
      1. 获取请求头数据

        • 方法:->迭代。.hasMoreElements

          • Enumeration<String> getHeaderNames():获取所有的请求头名称

          • String getHeader(String name):通过请求头的名称获取请求头的值

    1. 获取请求体数据:

    • 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

    • 步骤:

      1. 获取流对象

        • BufferedReader getReader():获取字符输入流,只能操作字符数据

        • ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据

        • 在文件上传知识点后讲解

      2. 再从流对象中拿数据

操作请求参数&转发:

  • 中文乱码问题:

    • get方式:tomcat 8 已经将get方式乱码问题解决了

      • post方式:会乱码

      • 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");

  1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数

    1. String getParameter(String name):根据参数名称获取参数值 username=zs&password=123

    2. String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game

    3. Enumeration<String> getParameterNames():获取所有请求的参数名称

    4. Map<String,String[]> getParameterMap():获取所有参数的map集合

  1. 请求转发:一种在服务器内部的资源跳转方式

    1. 使用:

      1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)

      2. 使用RequestDispatcher对象来进行转发forward(ServletRequest request, ServletResponse response)

      例:request.getRequestDispatcher("/demo9").forward(request,response);

    2. 特点:

    request是表示一个请求,只要发出一个请求就会创建一个request,它的

    用处:常用语服务器间同一请求不同页面之间的参数传递,常用语表单的控件值传递。

    		1. 浏览器**地址栏路径不发生变化**
    		2. 只能转发到当前**服务器内部资源**中。
    		3. 转发是**一次请求**
    		4. **作用域仅在当前请求中有效。**
  1. 共享数据

    • 域对象:一个有作用范围的对象,可以在范围内共享数据

    • request域对象:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

    • 方法:

      1. void setAttribute(String name,Object obj):存储数据

      2. Object getAttitude(String name):通过键获取

      3. void removeAttribute(String name):通过键移除键值对

  2. 获取ServletContext

    • ServletContext getServletContext()

      • 获取ServletContext域对象

BeanUtils:封装JavaBean的,简化数据封装操作

方法名称方法介绍
voidsetProperty(Object bean,String name,Object value)设置属性值
ObjectgetProperty(Object bean,String name)获取属性值
voidpopulate(Object obj , Map map)将map集合的键值对信息,封装到对应的JavaBean对象中

案例:用户登录

用户登录案例需求:

1.编写login.html登录页面 username & password 两个输入框 2.使用Druid数据库连接池技术,操作mysql,day14数据库中user表 3.使用JdbcTemplate技术封装JDBC 4.登录成功跳转到SuccessServlet展示:登录成功!用户名,欢迎您 5.登录失败跳转到FailServlet展示:登录失败,用户名或密码错误

* 分析

* 开发步骤
	1. 创建项目,导入html页面,配置文件,jar包
	2. 创建数据库环境
		CREATE DATABASE day14;
		USE day14;
		CREATE TABLE USER(
			id INT PRIMARY KEY AUTO_INCREMENT,
			username VARCHAR(32) UNIQUE NOT NULL,
			PASSWORD VARCHAR(32) NOT NULL
		);

	3. 创建包cn.itcast.domain,创建类User
		package cn.itcast.domain;
		/**
		 * 用户的实体类
		 */
		public class User {
		
		    private int id;
		    private String username;
		    private String password;
		    public int getId() {
		    	return id;
		    }
		    public void setId(int id) {
		        this.id = id;
		    }
		
		    public String getUsername() {
		        return username;
		    }
		
		    public void setUsername(String username) {
		        this.username = username;
		    }
		
		    public String getPassword() {
		        return password;
		    }
		
		    public void setPassword(String password) {
		        this.password = password;
		    }
		
		    @Override
		    public String toString() {
		        return "User{" +
		                "id=" + id +
		                ", username='" + username + '\'' +
		                ", password='" + password + '\'' +
		                '}';
		    }
		}
		
	4. 创建包cn.itcast.util,编写工具类JDBCUtils
		package cn.itcast.util;

		import com.alibaba.druid.pool.DruidDataSourceFactory;
		
		import javax.sql.DataSource;
		import javax.xml.crypto.Data;
		import java.io.IOException;
		import java.io.InputStream;
		import java.sql.Connection;
		import java.sql.SQLException;
		import java.util.Properties;
		
		/**
		 * JDBC工具类 使用Durid连接池
		 */
		public class JDBCUtils {
		
		    private static DataSource ds ;
		
		    static {
		
		        try {
		            //1.加载配置文件
		            Properties pro = new Properties();
		            //使用ClassLoader加载配置文件,获取字节输入流
		            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
		            pro.load(is);
		
		            //2.初始化连接池对象
		            ds = DruidDataSourceFactory.createDataSource(pro);
		
		        } catch (IOException e) {
		            e.printStackTrace();
		        } catch (Exception e) {
		            e.printStackTrace();
		        }
		    }
		
		    /**
		     * 获取连接池对象
		     */
		    public static DataSource getDataSource(){
		        return ds;
		    }
		      /**
			   * 获取连接Connection对象
			   */
			 public static Connection getConnection() throws SQLException {
			    return  ds.getConnection();
		     }
		}
		
		
		5. 创建包cn.itcast.dao,创建类UserDao,提供login方法
		package cn.itcast.dao;

		import cn.itcast.domain.User;
		import cn.itcast.util.JDBCUtils;
		import org.springframework.dao.DataAccessException;
		import org.springframework.jdbc.core.BeanPropertyRowMapper;
		import org.springframework.jdbc.core.JdbcTemplate;
		
		/**
		 * 操作数据库中User表的类
		 */
		public class UserDao {
		
		    //声明JDBCTemplate对象共用
		    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
		
		    /**
		     * 登录方法
		     * @param loginUser 只有用户名和密码
		     * @return user包含用户全部数据,没有查询到,返回null
		     */
		    public User login(User loginUser){
		        try {
		            //1.编写sql
		            String sql = "select * from user where username = ? and password = ?";
		            //2.调用query方法
		            User user = template.queryForObject(sql,
		                    new BeanPropertyRowMapper<User>(User.class),
		                    loginUser.getUsername(), loginUser.getPassword());
						return user;
			    } catch (DataAccessException e) {
			        e.printStackTrace();//记录日志
		          	return null;
		        	}
			    }
			}
		
		
	6. 编写cn.itcast.web.servlet.LoginServlet类
		package cn.itcast.web.servlet;

		import cn.itcast.dao.UserDao;
		import cn.itcast.domain.User;
		
		import javax.servlet.ServletException;
		import javax.servlet.annotation.WebServlet;
		import javax.servlet.http.HttpServlet;
		import javax.servlet.http.HttpServletRequest;
		import javax.servlet.http.HttpServletResponse;
		import java.io.IOException;	
		@WebServlet("/loginServlet")
		public class LoginServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //1.设置编码
            req.setCharacterEncoding("utf-8");
            //2.获取请求参数
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            //3.封装user对象
            User loginUser = new User();
            loginUser.setUsername(username);
            loginUser.setPassword(password);
            //4.调用UserDao的login方法
		        UserDao dao = new UserDao();
		        User user = dao.login(loginUser);
		
		        //5.判断user
		        if(user == null){
		            //登录失败
		            req.getRequestDispatcher("/failServlet").forward(req,resp);
		        }else{
		            //登录成功
		            //存储数据
		            req.setAttribute("user",user);
		            //转发
		            req.getRequestDispatcher("/successServlet").forward(req,resp);
		        }
		
		    }
		
		    @Override
		    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		        this.doGet(req,resp);
		    }
		}

	7. 编写FailServlet和SuccessServlet类
		@WebServlet("/successServlet")
		public class SuccessServlet extends HttpServlet {
		    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		        //获取request域中共享的user对象
		        User user = (User) request.getAttribute("user");
		
		        if(user != null){
		            //给页面写一句话
		
		            //设置编码
		            response.setContentType("text/html;charset=utf-8");
		            //输出
		            response.getWriter().write("登录成功!"+user.getUsername()+",欢迎您");
		        }
            
           } 
           
           @WebServlet("/failServlet")
		public class FailServlet extends HttpServlet {
		    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		        //给页面写一句话
		
		        //设置编码
		        response.setContentType("text/html;charset=utf-8");
		        //输出
		        response.getWriter().write("登录失败,用户名或密码错误");
		
		    }
		
		    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		        this.doPost(request,response);
		    }
		}
	8. login.html中form表单的action路径的写法
		* 虚拟目录+Servlet的资源路径

	9. BeanUtils工具类,简化数据封装
		* 用于封装JavaBean的
		1. JavaBean:标准的Java类
			1. 要求:
				1. 类必须被public修饰
				2. 必须提供空参的构造器
				3. 成员变量必须使用private修饰
				4. 提供公共setter和getter方法
			2. 功能:封装数据
		2. 概念:
			成员变量:
			属性:setter和getter方法截取后的产物
				例如:getUsername() --> Username--> username
		3. 方法:
			 populate(Object obj , Map map):将map集合的键值对信息,封装到对应的JavaBean对象中		

*Response(响应):

设置响应消息

response.sendRedirect("/day15/responseDemo2");重定向:

功能:设置响应消息 1. 设置响应行 1. 格式:HTTP/1.1 200 ok 2. 设置状态码:setStatus(int sc)

  1. 设置响应头setHeader(String name, String value) ,文件属性名

    Content-Type text/html;charset=UTF-8 *文件属性类型/拓展名*;

    例:response.setHeader("Content-Type", "text/html;charset=UTF-8");

    响应对象.设置响应头(“头”,“文件类型/拓展名;字段=字段值”)

    文件下载需要的响应头:

    String mimeType = servletContext.getMimeType(realPath);
     response.setHeader("content-type",mimeType);
    response.setHeader("content-disposition","attachment;filename="+filename);
  2. 设置响应体

    获取输出流

    • 字符输出流:PrintWriter getWriter()

    • 字节输出流:ServletOutputStream getOutputStream()

    • 使用输出流,将数据输出到客户端浏览器

      response.getWriter().write("2思密达");

      response.getOutputStream().println("2思密达");

    乱码问题:

    1. PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1

    2. 设置该流的默认编码

    3. 告诉浏览器响应体使用的编码

    //简单的形式,设置编码,是在获取流之前设置 response.setContentType("text/html;charset=utf-8");

  3. 完成重定向

    • 重定向:资源跳转的方式

    • 代码实现: //1. 设置状态码为302 response.setStatus(302); //2.设置响应头location response.setHeader("location","/day15/responseDemo2"); //简单的重定向方法 response.sendRedirect("/day15/responseDemo2");

dis请求和转发

*面试题: forward 和 redirect 区别

  • 重定向的特点:redirect

    1. 地址上显示的是最后的那个资源的路径地址

    2. 请求次数最少有两次, 服务器在第一次请求后,会返回302 以及一个地址, 浏览器在根据这个地址,执行第二次访问。

    3. 可以跳转到任意路径。 不是自己的工程也可以跳。

    4. 效率稍微低一点, 执行两次请求。

    5. 后续的请求,没法使用上一次的request对象,因为这是两次不同的请求。

  • 转发的特点:forward

    1. 地址上显示的是请求servlet的地址。 返回200 ok

    2. 请求次数只有一次, 因为是服务器内部帮客户端执行了后续的工作。

    3. 只能跳转自己项目的资源路径

    4. 效率上稍微高一点,因为只执行一次请求。

    5. 可以使用上一次的request对象。 带着数据走

区别转发forward()重定向sendRedirect()
根目录包含项目访问地址没有项目访问地址
地址栏不会发生变化会发生变化
哪里跳转服务器端进行的跳转浏览器端进行的跳转
请求域中数据不会丢失会丢失

如果要保留请求域中的数据,使用转发,否则使用重定向。

以后访问数据库,增删改使用重定向,查询使用转发。

路径分类

  1. 相对路径:通过相对路径不可以确定唯一资源

    • 如:./index.html

    • 不以/开头,以.开头路径

    • 规则:找到当前资源和目标资源之间的相对位置关系

      • ./:当前目录

      • ../:后退一级目录

  2. 绝对路径:通过绝对路径可以确定唯一资源

    • 如:http://localhost/day15/responseDemo2 /day15/responseDemo2

    • 以/开头的路径

    • 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出

      • 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)

        • 建议虚拟目录动态获取:request.getContextPath()

        • <a> , <form> 重定向...

      • 给服务器使用:不需要加虚拟目录

        • 转发路径

请求:重定向(2)&转发(1)

ServletContext(域:Web应用):

④如果把变量放到application里,就说明它的作用域是application,它的有效范围是整个应用。所谓整个应用:是指从应用启动到应用结束。application里的变量存活时间最长,如果不进行手动删除,它们就一直可以使用。

  1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信

    作用范围:所有的用户都可以取得此信息,此信息在整个服务器端被保留

    Application属性范围值只要设置一次,则所有的网页窗口都可以取得数据

    ServletContext在服务器启动时创建,在服务器关闭时销毁,

    一个JavaWeb应用只创建一个ServletContext对象

  2. 获取:

    1. 通过request对象获取 request.getServletContext();

    2. 通过HttpServlet获取

      this.getServletContext();

  3. 功能:

    String getMimeType(String file)MIME类型:在互联网通信过程中定义的一种文件数据类型获取MIME类型:大类型/小类型 text/html image/jpeg
    1. setAttribute(String name,Object value) 2. getAttribute(String name)设置,获取,数据域对象:共享数据
    3. removeAttribute(String name)删除数据
    ServletContext()对象范围:所有用户所有请求的数据对象范围:所有用户所有请求的数据
    String getRealPath(String path)String b = context.getRealPath("/b.txt");//web目录下资源访问获取文件的真实(服务器)路径
    String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
    String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
    InputStream getResourceAsStream(String path)InputStream is= getResourceAsStream(String path)获取项目下文件的输入流

案例:文件下载

* 文件下载需求:
	1. 页面显示超链接
	2. 点击超链接后弹出下载提示框
	3. 完成图片文件下载
	//1.获取请求参数
        String filename = request.getParameter("filename");

        //2.获取要下载的文件在服务器的真实位置
        ServletContext servletContext = request.getServletContext();
        String realPath = servletContext.getRealPath("/imgs/"+filename);

        //响应头
        //图片文件类型
        String mimeType = servletContext.getMimeType(realPath);
        response.setHeader("content-type",mimeType);
        response.setHeader("content-disposition","attachment;filename="+filename);

        //3.创建输入流
        //BufferedInputStream bis = new BufferedInputStream(new FileInputStream(realPath));
        BufferedInputStream bis = new BufferedInputStream(servletContext.getResourceAsStream(realPath));

        //4.输出流
        BufferedOutputStream bos = new BufferedOutputStream( response.getOutputStream());
		//ServletOutputStream sos = response.getOutputStream();


        //流操作
        byte[] bytes = new byte[1024];
        int len;

        while ((len=bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
        }

        bis.close();
    }
* 分析:
	1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
	2. 任何资源都必须弹出下载提示框
	3. 使用响应头设置资源的打开方式:
		* content-disposition:attachment;filename=xxx
* 步骤:
	1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
	2. 定义Servlet
		1. 获取文件名称
		2. 使用字节输入流加载文件进内存
		3. 指定response的响应头: content-disposition:attachment;filename=xxx
		4. 将数据写出到response输出流
* 问题:
	* 中文文件问题
		* 解决思路:
			1. 获取客户端使用的浏览器版本信息
			2. 根据不同的版本信息,设置filename的编码方式不同

验证码:

package com.hpit.web;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
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;

@WebServlet("/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        int width = 100;
        int height = 50;

        //1.创建一对象,在内存中图片(验证码图片对象)
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

        //2.美化图
        //2.1 填充背景色
        Graphics g = image.getGraphics();//画笔对象
        g.setColor(Color.PINK);//设置画笔颜色
        g.fillRect(0,0,width,height);

        //2.2画边框
        g.setColor(Color.BLUE);
        g.drawRect(0,0,width - 1,height - 1);

        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
        //生成随机角标
        Random ran = new Random();

        for (int i = 1; i <= 4; i++) {
            int index = ran.nextInt(str.length());
            //获取字符
            char ch = str.charAt(index);//随机字符
            //2.3写验证码
            g.drawString(ch+"",width/5*i,height/2);
        }


        //2.4画干扰线
        g.setColor(Color.GREEN);

        //随机生成坐标点

        for (int i = 0; i < 10; i++) {
            int x1 = ran.nextInt(width);
            int x2 = ran.nextInt(width);

            int y1 = ran.nextInt(height);
            int y2 = ran.nextInt(height);
            g.drawLine(x1,y1,x2,y2);
        }

        //3.将图片输出到页面展示
        ImageIO.write(image,"jpg",response.getOutputStream());
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

Cookie&Session

会话技术:

1. 会话:一次会话中包含多次请求和响应。
	* 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
2. 功能:在一次会话的范围内的多次请求间,共享数据
3. 方式:
	1. 客户端会话技术:Cookie
	2. 服务器端会话技术:Session

Cookie:

  1. 概念客户端会话技术,将数据保存到客户端

  2. 快速入门:

    • 使用步骤:

      1. 创建Cookie对象,绑定数据

        • new Cookie(String name, String value)

      2. 发送Cookie对象

        • response.addCookie(Cookie cookie)

      3. 获取Cookie,拿到数据

        • Cookie[] request.getCookies()

  3. 实现原理

    • 基于响应头set-cookie和请求头cookie实现

查找cookie:

public  static Cookie findCookie(Cookie[] cookies,String name){
        //判断cookie不为null并且长度大于0
        if(cookies!=null && cookies.length>0){
            //遍历cookie数组查找cookie
            for (Cookie cookie : cookies) {
                //找到了指定名称的cookie
                if(name.equals(cookie.getName())){
                    return cookie;
                }
            }
        }
        return  null ;
    }

细节:

  1. cookie的细节

    1. cookie在浏览器中的保存时间

      1. 默认情况下,当浏览器关闭后,Cookie数据被销毁

      2. 持久化存储:

        • setMaxAge(int seconds)

          1. 正数:将Cookie数据写到硬盘的文件中。持久化存储。并指定cookie存活时间,时间到后,cookie文件自动失效

          2. 负数:默认值

          3. 零:删除cookie信息

    2. cookie存中文

      • 在tomcat 8 之前 cookie中不能直接存储中文数据。

        • 需要将中文数据转码---一般采用URL编码(%E3)

      • 在tomcat 8 之后,cookie支持中文数据。特殊字符还是不支持,建议使用URL编码存储,URL解码解析

    3. cookie共享问题?演示***

      1. 同个tomcat服务器中,部署了多个web项目

        • 默认情况下cookie不能共享

        • setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录

        • 如果要共享,则可以将path设置为"/"

      2. 不同的tomcat服务器间cookie共享问题

        • setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享

        • setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享

    4. Cookie的特点和作用

      • 特点:

      1. cookie存储数据在客户端浏览器

      2. 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)

      • 作用

      1. cookie一般用于存储少量的不太敏感的数据

      2. 在不登录的情况下,完成服务器对客户端的身份识别

案例:判断用户是否第一次登陆

@WebServlet("/lastVisit")
public class LastVisitServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决中文乱码问题
        response.setContentType("text/html;charset=utf-8");

        //判断用户是否是第一次访问   lastVisit
        Cookie[] cookies = request.getCookies();//[username=zs,password=123,lastVisit=2018-10-01]
        //查找cookie
        Cookie cookie = CookieUtils.findCookie(cookies, "lastVisit");
        //判断用户是否是第一次访问
        //第一次访问
        if(cookie==null){
            response.getWriter().write("欢迎您第一次访问");
        }else{
            //不是第一次访问
            //获取cookie中保存的时间
            String value = cookie.getValue();
            response.getWriter().write("您上次的访问时间是:"+value);
        }

        //不论用户是否是第一次访问,都需要更新Cookie信息
        //更新cookie信息
        //获取当年前时间字符串
        Date now = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = format.format(now);
        //创建cookie
        Cookie lastVisit = new Cookie("lastVisit", time);
        //设置cookie的存活时间
        lastVisit.setMaxAge(2*24*60*60);
        //响应到客户端
        response.addCookie(lastVisit);
    }
}

JSP

  1. 概念:

  • Java Server Pages: java服务器端页面

    一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码,用于简化书写!!!

  1. 原理

  • JSP本质上就是一个Servlet

  1. JSP的脚本:JSP定义Java代码的方式

    1. <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。

    2. <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置

    3. <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。

  2. JSP的内置对象

    • 在jsp页面中不需要获取和创建,可以直接使用的对象

    • jsp一共有9个内置对象。

    • 基础3个:

      • request

      • response

      • out:字符输出流对象。可以将数据输出到页面上。和response.getWriter()类似

        • response.getWriter()和out.write()的区别:

          • 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。

          • response.getWriter()数据输出永远在out.write()之前

Session:

③如果把这个变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。 所谓当前会话:就是指从用户打开浏览器开始,知道用户关闭浏览器这中间的过程,这个过程可能包含多个请求响应。 也就是说,只要用户不关闭浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被称为一个会话,而放到会话中的变量,就可以在当前会话的所有请求里使用。

  1. 概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession

  2. 快速入门:

    1. 获取HttpSession对象: HttpSession session = request.getSession();

    2. 使用HttpSession对象: Object getAttribute(String name) void setAttribute(String name, Object value) void removeAttribute(String name)

  3. 原理

    • Session的实现是依赖于Cookie的。

    • 在一次会话中,客户端向服务端发送一个响应头,创建Session对象,会通过Cookie响应返回一个JsessionID,用于管理此用户对象,

      每次请求或响应都会与服务端存储的sessionID判定,没有即第一次访问并创建JsessionID对象,有就调用此对象,

      用户数据就会存储在此session中。

细节:

  1. 细节

session的保存时间

  1. 服务器关闭

  2. session对象调用invalidate() 。

  3. session默认失效时间 30分钟 选择性配置修改 <session-config> <session-timeout>30</session-timeout> </session-config>

当客户端关闭后,服务器不关闭,两次获取session不是同一个。如果需要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存。 例: Cookie c = new Cookie("JSESSIONID",session.getId()); c.setMaxAge(60*60); response.addCookie(c);
客户端不关闭,服务器关闭后,两次获取的session不是同一个,但是要确保数据不丢失。tomcat自动完成以下工作session的钝化: 在服务器正常关闭之前,将session对象序列化到硬盘上 session的活化: 在服务器启动后,将session文件转化为内存中的session对象即可。

session的特点

  1. session用于存储一次会话的多次请求的数据,存在服务器端

  2. session可以存储任意类型,任意大小的数据

  • session与Cookie的区别:

    1. session存储数据在服务器端,Cookie在客户端

    2. session没有数据大小限制,Cookie有

    3. session数据安全,Cookie相对于不安全

案例:验证码

1. 案例需求:
	1. 访问带有验证码的登录页面login.jsp
	2. 用户输入用户名,密码以及验证码。
		* 如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
		* 如果验证码输入有误,跳转登录页面,提示:验证码错误
		* 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
<%--
  Created by IntelliJ IDEA.
  User: 24836
  Date: 2021/9/23
  Time: 9:34
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <link rel="stylesheet" href="css/login.css">
</head>
<body>
<div id="login-box">

    <h1>login</h1>
    <form method="post" action="/LoginServlet" id="loginfrom">
        <div class="form">
            <div class="item">
                <input type="text" id="uname" value="<%=request.getSession().getAttribute("uname") == null ? "" : request.getSession().getAttribute("uname")%>" name="username" placeholder="Username"/>
            </div>
            <div class="item">
                <input type="password" id="upwd" value="<%=request.getSession().getAttribute("upwd") == null ? "" :request.getSession().getAttribute("upwd") %>"  name="password" placeholder="Password"/>
            </div>
            <img src="/CheckCodeServlet" style="display: inline-block" id="login_check">
            <p style="color: red"><%=request.getSession().getAttribute("error_check") == null ? "" : request.getSession().getAttribute("error_check")%></p>
            <p style="color: red"><%=request.getSession().getAttribute("error_user") == null ? "" : request.getSession().getAttribute("error_user")%></p>
            <div class="item">
                <input type="text" id="check" name="check">
            </div>
            <span id="msg" style="font-size: 12px;color: red;line-height: 30px;padding: 0 10px 0 10px;"></span>
        </div>
        <input type="button" id="loginBut" class="anliu" name="login" value="Login"/>
    </form>
</div>


</body>
<script type="text/javascript" src="js/jquery-3.3.1.js"></script>
<script src="js/login.js"></script>
</html>

package com.login.web;

import com.login.dao.AdminDAO;
import com.login.pojo.Admin;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //乱码
        request.setCharacterEncoding("utf-8");

        //获取用户输入
        Map<String, String[]> parameterMap = request.getParameterMap();
        /*String uname = request.getParameter("username");
        String upwd = request.getParameter("password");*/

        //存
        Admin admin = new Admin();
        try {
            BeanUtils.populate(admin, parameterMap);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }

        //获取数据库内对象
        AdminDAO adminDAO = new AdminDAO();
        Admin loginadmin = adminDAO.loginadmin(admin);

        //用户输入验证码
        //String checkp = request.getParameter("check");
		//用户输入验证码
        String checkp = parameterMap.get("check")[0];
        
        //3.拿到图片中的验证码
        String check = (String) request.getSession().getAttribute("check");
        //将session中的验证码销毁
        request.getSession().removeAttribute("check");
        request.getSession().removeAttribute("error_user");
        request.getSession().removeAttribute("error_check");
        request.getSession().removeAttribute("uname");
        request.getSession().removeAttribute("upwd");

        if (checkp.equalsIgnoreCase(check)){
            //判断
            if (loginadmin!=null){
                //用户名或者密码正确
                request.getSession().setAttribute("username",loginadmin.getUsername());
                //重定向
                response.sendRedirect(request.getContextPath()+"/success.jsp");
            }else {
                //用户名或者密码错误
                //向request中存入提示信息
                request.getSession().setAttribute("error_user","用户名或者密码错误!");
                //重定向
                response.sendRedirect(request.getContextPath()+"/login.jsp");
            }
        }else {
            //验证码不同
            request.getSession().setAttribute("error_check", "验证码错误");
            //重定向
            String username = admin.getUsername();
            String password = admin.getPassword();
            request.getSession().setAttribute("uname", username);
            request.getSession().setAttribute("upwd", password);
            response.sendRedirect(request.getContextPath()+"/login.jsp");
        }
    }



    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

Servlet中的四种域对象(转)

pageContext

pageContext作用域为page(页面执行期)。

request

request是表示一个请求,只要发出一个请求就会创建一个request,它的作用域仅在当前请求中有效。

用处:常用语服务器间同一请求不同页面之间的参数传递,常用语表单的控件值传递。

方法:request.setAttribute(); reuqest.getAttribute();

request.removeAttribute(); request.getParameter();

session

服务器会为每一个会话创建一个Session对象,所以Session中的数据可供当前会话中所有Servlet共享。

用处:常用于web开发中的登录验证界面(当用户登陆成功后浏览器分配其中一个Session键值对)。

方法:session.setAttribute(); session.getAttribute();

session.removeAttribute();

Application(ServletContext上下文)

作用范围:所有的用户都可以取得此信息,此信息在整个服务器端被保留。Application属性范围值只要设置一次,则所有的网页窗口都可以取得数据。ServletContext在服务器启动时创建,在服务器关闭时销毁,一个JavaWeb应用只创建一个ServletContext对象。

方法:ServletContext application = this.getServletContext();

application.setAttribute(); application.getAttribute();

application.removeAttribute();

Servlet作用域

例如,我们访问index.jsp的时候,分别对pageContext、request、session、application四个作用域进行累加。

计算完成后就从index.jsp执行forward转发到test.jsp,在test.jsp里再进行一次累加,然后显示出这四个整数来。

从结果来看:

①page里的变量没法从index.jsp传递到test.jsp,只要页面跳转了,它们就不见了。

②request里的变量可以跨越forward前后两页。但是只要刷新页面,它们就重新计算了。

③session和application的变量一直在累加,开始还看不出区别,只要关闭浏览器,再次重启浏览器访问这个页面,session里的变量就重新计算了。

④application里的变量一直在累加,除非你重启Tomcat,否则它会一直变大。

作用域规定的是变量的有效期限

①如果把变量放到pageContext里,就说明它的作用域是page,它的有效范围只在当前JSP页面里。从把变量放到pageContext开始,直到JSP页面跳转前都可以使用。

②如果把变量放到request里,就说明它的作用域是request,它的有效范围是当前请求周期。 所谓请求周期:就是从Http请求发起,到服务器处理结束,返回响应的整个过程。在这个过程中可能使用forward的方式跳转了多个JSP页面,在这些页面里,你都可以使用这个变量。

③如果把这个变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。 所谓当前会话:就是指从用户打开浏览器开始,知道用户关闭浏览器这中间的过程,这个过程可能包含多个请求响应。 也就是说,只要用户不关闭浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被称为一个会话,而放到会话中的变量,就可以在当前会话的所有请求里使用。

④如果把变量放到application里,就说明它的作用域是application,它的有效范围是整个应用。所谓整个应用:是指从应用启动到应用结束。application里的变量存活时间最长,如果不进行手动删除,它们就一直可以使用。


四种域对象的总结

一、ServletContext

    1、生命周期:当Web应用被加载进容器时创建代表整个web应用的ServletContext对象,当服务器关闭或Web应用被移除时,ServletContext对象跟着销毁。

    2、作用范围:整个Web应用。

    3、作用:

      a)在不同Servlet 之间转发

        this.getServletContext().getRequestDispatcher("/servlet/Demo10Servlet").forward(request, response);

        方法执行结束,service就会返回到服务器,再有服务器去调用目标servlet,其中request会重新创建,并将之前的request的数据拷贝进去。

      b)读取资源文件。

       1、由于相对路径默认相对的是java虚拟机启动的目录,所以我们直接写相对路径将会是相对于tomcat/bin目录,所以是拿不到资源的。如果写成绝对路径,当项目发布到其他环境时,绝对路径就错了。

        2、为了解决这个问题ServletContext提供了:

            this.getServletContext().getRealPath("/1.properties"),给进一个资源的虚拟路径,将会返回该资源在当前环境下的真实路径。        

            this.getServletContext().getResourceAsStream("/1.properties"),给一个资源的虚拟路径返回到该资源真实路径的流。

        3、当在非servlet下获取资源文件时,就没有ServletContext对象用了,此时只能用类加载器

            classLoader.getResourceAsStream("../../1.properties"),此方法利用类加载器直接将资源加载到内存中,有更新延迟的问题,以及如果文件太大,占用内存过大。

            classLoader.getResource("../1.properties").getPath(),直接返回资源的真实路径,没有更新延迟的问题。

二、Request 域

    1、生命周期:在service 方法调用前由服务器创建,传入service方法。整个请求结束,request生命结束。

    2、作用范围:整个请求链(请求转发也存在)。

    3、作用: 在整个请求链中共享数据。最常用到:在Servlet 中处理好的数据交给Jsp显示,此时参数就可以放置在Request域中带过去。

三、Session 域

    HttpSession 在服务器中,为浏览器创建独一无二的内存空间,在其中保存会话相关的信息。     1、生命周期:在第一次调用 request.getSession() 方法时,服务器会检查是否已经有对应的session,如果没有就在内存 中创建一个session并返回。

           当一段时间内session没有被使用(默认为30分钟),则服务器会销毁该session。

           如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁。

           如果调用session提供的invalidate() ,可以立即销毁session。

      注意:服务器正常关闭,再启动,Session对象会进行钝化和活化操作。同时如果服务器钝化的时间在session 默认销毁时间之内,则活化后session还是存在的。否则Session不存在。 如果JavaBean 数据在session钝化时,没有实现Serializable 则当Session活化时,会消失。

    2、作用范围:一次会话。

四、PageContext 域

    1、生命周期:当对JSP的请求时开始,当响应结束时销毁。

    2、作用范围:整个JSP页面,是四大作用域中最小的一个。

    作用:

        (1)获取其它八大隐式对象,可以认为是一个入口对象。

        (2)获取其所有域中的数据

            pageContext  操作所有域中属性的方法

              public java.lang.Object getAttribute(java.lang.String name,int scope)               public void setAttribute(java.lang.String name, java.lang.Object value,int scope)

              public void removeAttribute(java.lang.String name,int scope)

              pageContext 中代表域的常量

                PageContext.APPLICATION_SCOPE

                PageContext.SESSION_SCOPE

                PageContext.REQUEST_SCOPE

                PageContext.PAGE_SCOPE

              findAttribute方法,在四大域中搜寻属性,搜寻的顺序是page域、request域、session域、application域,从小域到大域开始搜索,如果搜索到就直接获取该值,如果所有域中都找不到,返回一个null(与el表达式不同,此处返回null,对网页是不友好的)

        (3)跳转到其他资源 其身上提供了forward和include方法,简化重定向和转发的操作


ActionContext与ServletActionContext的区别及获取request、session等对象 我们知道struts2接受客户端请求,在Action中进行处理后,将视图结果返回。struts2容器自身不依赖于web容器,不用和servlet对象中的请求(request)、响应(response)进行关联,对于请求的参数,通过paramerInterceptor将参数封装在Action中,然后通过调用get、set方法将参数值设置进Action之中。如果仅仅获取参数,可能有时候满足不了开发的需求,有时我们要获取request或者response中的信息,要对其进行设置、处理。

一、ActionContext

是Action执行的上下文,Action的上下文可以看作是一个容器,里面封装了请求(Request)、会话(Session)、Application等,这里面的Request、Session、Application是Map类型的,往里面封装的是键值对,所以这就体现了struts2不与底层servlet Api打交道,那么对很多web的相关对象进行封装,这样可以达到Action与web层解耦。

用ActionContext得到Map类型的Request、Session、Application。

例子:

获取request:

 Map request = ActionContext.getContext().get("request");

往request里封装数据

request.put("name", value);

在前台就可以用request.getAttribute("name");

获取session

Map session = ActionContext.getContext().getSession();

将数据封装到session中

session.put("name", value);

在前台页面上用sessionScope.getAttribute("name");得到session里面封装的值。

得到session、request有点区别,得到request用的是get("reqeust"),得到session用的是getSession()

也可以直接对Java Servlet Http的请求(HttpServletRequest)、响应(HttpServletResponse)操作,和上面的例子有点区别,注意区别。

ActionContext ctx = ActionContext.getContext(); HttpServletRequest request = (HttpServletRequest)ctx.get(ServletActionContext.HTTP_REQUEST); HttpServletResponse response = (HttpServletResponse)ctx.get(ServletActionContext.HTTP_RESPONSE);

用法就和Servlet中的request、response用法一样

二、ServletActionContext

它继承ActionContext,所以ServletActionContext也可以得到HttpServetRequest、HttpServletResponse,,它也提供了直接与Servlet相关对象访问的功能,它可以取得的对象有:

(1)javax.servlet.http.HttpServletRequest : HTTPservlet请求对象

(2)javax.servlet.http.HttpServletResponse : HTTPservlet相应对象

(3)javax.servlet.ServletContext : Servlet上下文信息

(4)javax.servlet.ServletConfig : Servlet配置对象

(5)javax.servlet.jsp.PageContext : Http页面上下文

如何获取HttpRequest、HttpResponse

例子

HttpServletRequest request = ServletActionContext.getRequest();

HttpServletResponse response = ServletActionContext.getResponse();

然后就可以用request.setAttribute("name", value)方法了。

总结:不难看出,两者之间还是存在很多共同功能,那么我们还是根据自己的需求进行选择,能用ActionContext对象满足就尽量使用ActionContext,避免让我们直接去访问Servlet对象。另外,不要在Action还没实例化的时候去通过ActionContext调用方法,因为Action实例在ActionContext实例之前创建,ActionContext中一些值还没有设置,会返回null。

———————————————— 原文链接:JAVA EE 中的域对象总结_朗晴的技术博客-CSDN博客_servlet中的域对象

JSP&EL&JSTL:

JSP:

page

①如果把变量放到pageContext里,就说明它的作用域是page,它的有效范围只在当前JSP页面里。从把变量放到pageContext开始,直到JSP页面跳转前都可以使用。

  1. 指令

    • 作用:用于配置JSP页面,导入资源文件

    • 格式: <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>

    • 指令分类:

      1. page: 配置JSP页面的

        • contentType:等同于response.setContentType()

          1. 设置响应体的mime类型以及字符集

          2. 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)

        • import:导包

        • errorPage:当前页面发生异常后,会自动跳转到指定的错误页面

        • isErrorPage:标识当前是否是错误页面。

          • true:是,可以使用内置对象exception

          • false:否。默认值。不可以使用内置对象exception

      2. include : 页面包含的。导入页面的资源文件

        • <%@include file="top.jsp"%>

      3. taglib : 导入资源

  2. 注释:

    1. html注释: <!-- -->:只能注释html代码片段

    2. jsp注释:推荐使用 <%-- --%>:可以注释所有

  3. 内置对象

  • 在jsp页面中不需要创建,直接使用的对象

  • 一共有9个:

    变量名真实类型作用
    pageContextPageContext当前页面共享数据,还可以获取其他八个内置对象
    requestHttpServletRequest一次请求访问的多个资源(转发)
    sessionHttpSession一次会话的多个请求间
    applicationServletContext所有用户间共享数据
    responseHttpServletResponse响应对象
    pageObject当前页面(Servlet)的对象 this
    outJspWriter输出对象,数据输出到页面上
    configServletConfigServlet的配置对象
    exceptionThrowable异常对象

获取相对路径:pageContext.request.contextPath -> (HttpServletRequest.getcontextPath())

MVC:开发模式

  1. jsp演变历史

    1. 早期只有servlet,只能使用response输出标签数据,非常麻烦

    2. 后来有jsp,简化了Servlet的开发,如果过度使用jsp,在jsp中既写大量的java代码,又写html表,造成难于维护,难于分工协作

    3. 再后来,java的web开发,借鉴mvc开发模式,使得程序的设计更加合理性

  2. MVC:

  3. M:Model,模型。JavaBean

  • 完成具体的业务操作,如:查询数据库,封装对象

  1. V:View,视图。JSP

  • 展示数据

  1. C:Controller,控制器。Servlet

  • 获取用户的输入

  • 调用模型

  • 将数据交给视图进行展示

  1. 优缺点:

    1. 优点:

      1. 耦合性低方便维护,可以利于分工协作重用性高

      2. 缺点:

        1. 使得项目架构变得复杂,对开发人员要求高

EL表达式

  1. 概念:Expression Language 表达式语言

  2. 作用:替换和简化jsp页面中java代码的编写

  3. 语法:${表达式}

  4. 注意:

    • jsp默认支持el表达式的。如果要忽略el表达式

      1. 设置jsp中page指令中:isELIgnored="true" 忽略当前jsp页面中所有的el表达式

      2. ${表达式} :忽略当前这个el表达式

使用

  1. 使用

    1. 运算符:

      1. 算数运算符: + - * /(div) %(mod)

      2. 比较运算符: > < >= <= == !=

      3. 逻辑运算符: &&(and) ||(or) !(not)

      4. 空运算符: empty

      • 功能:用于判断字符串、集合、数组对象是否为null或者长度是否为0

      • ${empty list}:判断字符串、集合、数组对象是否为null或者长度为0

        为空就是true;不为空是false

      • ${not empty str}:表示判断字符串、集合、数组对象是否不为null 并且 长度>0

        为空就是false;不为空是true

    2. 获取值

    3. el表达式只能从域对象中获取值

    4. ${域名称.键名}:从指定域中获取指定键的值

    * 域名称:
      1. pageScope		--> pageContext
      2. requestScope 	--> request
      3. sessionScope 	--> session
      4. applicationScope --> application(ServletContext)
    * 举例:在request域中存储了name=张三
    * 获取:${requestScope.name}
    1. ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。

    2. . 获取对象、List集合、Map集合的值

      1. 对象:${域名称.键名.属性名}

      2. List集合:${域名称.键名[索引]}

        本质上会去调用对象的getter方法

      3.Map集合:

      • ${域名称.键名.key名称}

      • ${域名称.键名["key名称"]}

    3. 隐式对象:(了解)

      • el表达式中有11个隐式对象

        • pageContext:

          • 获取jsp其他八个内置对象

          • ${pageContext.request.contextPath}:动态获取虚拟目录

JSTL

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  1. 概念:JavaServer Pages Tag Library JSP标准标签库

    • 由Apache组织提供的开源的免费的jsp标签 <标签>

  2. 作用:用于简化和替换jsp页面上的java代码

  3. 使用步骤:

    1. 导入jstl相关jar

    2. 引入标签库:taglib指令: <%@ taglib %>

    3. 使用标签

使用:

  1. 常用的JSTL标签

  2. if:相当于java代码的if语句

    1. 属性:

      • test 必须属性,接受boolean表达式

        • 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容

  • 一般情况下,test属性值会结合el表达式一起使用

 	 2. 注意:
 
  		 * c:if标签没有else情况,想要else情况,则可以再定义一个c:if标签
  1. choose:相当于java代码的switch语句

    1. 使用choose标签声明 相当于switch声明

    2. 使用when标签做判断 相当于case

      1. 使用otherwise标签做其他情况的声明 相当于default

  2. foreach:相当于java代码的for语句

  3. 练习:

  • 需求:在request域中有一个存有User对象的List集合。需要使用jstl+el将list集合数据展示到jsp页面的表格table中

三层架构:软件设计架构

1. 界面层(表示层):用户看的得界面。用户可以通过界面上的组件和服务器进行交互
2. 业务逻辑层:处理业务逻辑的。
3. 数据访问层:操作数据存储文件。

案例:用户信息列表展示

1. 需求:用户信息的增删改查操作
2. 设计:
	1. 技术选型:Servlet+JSP+MySQL+JDBCTempleat+Duird+BeanUtilS+tomcat
	2. 数据库设计:
3. 开发:
	1. 环境搭建
	2. 编码
4. 测试
5. 部署运维

Filter:过滤器

概念:

  1. 概念:

    • web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。

    • 过滤器的作用:

      • 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤...

  2. 快速入门:

    1. 步骤:

      1. 定义一个类,实现接口Filter

      2. 复写方法

      3. 配置拦截路径的方法:

        1. web.xml

        2. 注解

实现:

	2. 代码:
		@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
		public class FilterDemo1 implements Filter {
		    @Override
		    public void init(FilterConfig filterConfig) throws ServletException {
		
		    }
		
		    @Override
		    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		        System.out.println("filterDemo1被执行了....");
		        //放行
			        filterChain.doFilter(servletRequest,servletResponse);
			}
		
		    @Override
		    public void destroy() {
		
		    }
		}

过滤器细节:

  1. web.xml配置 <filter> <filter-name>demo1</filter-name> <filter-class>cn.itcast.web.filter.FilterDemo1</filter-class> </filter> <filter-mapping> <filter-name>demo1</filter-name> <!-- 拦截路径 --> <url-pattern>/*</url-pattern> </filter-mapping>

    1. 过滤器执行流程

      1. 执行过滤器

      2. 执行放行后的资源

      3. 回来执行过滤器放行代码下边的代码

    2. 过滤器生命周期方法

      1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源

      2. doFilter:每一次请求被拦截资源时,会执行。执行多次

      3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源

    3. 过滤器配置详解

      • 拦截路径配置:

        1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行

        2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行

        3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行

        4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

      • 拦截方式配置:资源被访问的方式

        • 注解配置:

          • 设置dispatcherTypes属性 *1. REQUEST:默认值。浏览器直接请求资源 *2. FORWARD:转发访问资源

            1. INCLUDE:包含访问资源

            2. ERROR:错误跳转资源

            3. ASYNC:异步访问资源

        • web.xml配置

          • 设置<dispatcher></dispatcher>标签即可

    4. 过滤器链(配置多个过滤器)

      • 执行顺序:如果有两个过滤器:过滤器1和过滤器2

        1. 过滤器1

        2. 过滤器2

        3. 资源执行

        4. 过滤器2

        5. 过滤器1

      • 过滤器先后顺序问题:

        1. 注解配置:按照类名的字符串比较规则比较,值小的先执行

          • 如: AFilter 和 BFilter,AFilter就先执行了。

        2. web.xml配置: <filter-mapping>谁定义在上边,谁先执行

  2. 案例

    1. 案例1_登录验证

      • 需求:

        1. 访问day20_case案例的资源。验证其是否登录

        2. 如果登录了,则直接放行。

        3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。

    2. 案例2_敏感词汇过滤

      • 需求:

        1. 对day17_case案例录入的数据进行敏感词汇过滤

        2. 敏感词汇参考《敏感词汇.txt》

        3. 如果是敏感词汇,替换为 ***

      • 分析:

        1. 对request对象进行增强。增强获取参数相关方法

        2. 放行。传递代理对象

          • 增强对象的功能:

        • 设计模式:一些通用的解决固定问题的方式

        1. 装饰模式

        2. 代理模式

          • 概念:

            1. 真实对象:被代理的对象

            2. 代理对象:

            3. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的

        • 实现方式:

          1. 静态代理:有一个类文件描述代理模式

          2. 动态代理:在内存中形成代理类

            • 实现步骤:

              1. 代理对象和真实对象实现相同的接口

                1. 代理对象 = Proxy.newProxyInstance();

                2. 使用代理对象调用方法。

                3. 增强方法

            • 增强方式:

              1. 增强参数列表

              2. 增强返回值类型

              3. 增强方法体执行逻辑

敏感词案例:

```java
@WebFilter("/*")
public class MingGanCiHuiFilter implements Filter {
    //存敏感词汇的集合
    private List<String> list = new ArrayList<String>();

    public void destroy() {
    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //HttpServletRequest req1 = (HttpServletRequest) req;
        //增强request  -->增强request.getParameter()
        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(
                req.getClass().getClassLoader(),  //request的类加载器
                req.getClass().getInterfaces(),   //request的父类接口(干爹们)
                new InvocationHandler() {         //处理器:增强的代码
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        /**
                         * Object proxy:代理对象     req + 替换敏感词汇的buff
                         * Method method:代理对象中的方法的对象
                         * Object[] args :代理对象中的方法对象的参数
                         */
                        //获取代理对象中方法对象的名称
                        String name = method.getName();
                        //判断该方法是否为getParameter方法
                        if ("getParameter".equals(name)) {
                            //获取req对象中名字叫getParameter的方法返回值
                            String value = (String) method.invoke(req, args);//替换前调用

                            //判断value是否为null
                            if (value != null && value.length() > 0) {
                                //遍历集合
                                for (String ci : list) {
                                    //将value中的敏感词进行全部替换
                                   value = value.replaceAll(ci,"***");

                                    return value;//将替换后的内容返回给了代理对象,存在于请求行中
                                }
                            }
                        }
                        //敏感词汇替换之后再调用一次method.invoke(req,args)
                        return method.invoke(req,args);
                    }
                }
        );

        //最后放行增强之后的proxy_req
        chain.doFilter(proxy_req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
        try {

            //1.获取servletContext对象
            ServletContext context = config.getServletContext();

            //2.通过context对象获取src下面的 敏感词汇.txt文件 的资源路径
            String realPath = context.getRealPath("/WEB-INF/classes/敏感词汇.txt");

            //3.通过路径创建字符流对象
            BufferedReader br = new BufferedReader(new FileReader(realPath));

            //循环读
            String line;

            while ((line = br.readLine()) != null) {
                list.add(line);
            }


            System.out.println(list);
            br.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
```



Listener:监听器

  • 概念:web的三大组件之一。

    • 事件监听机制

      • 事件 :一件事情

      • 事件源 :事件发生的地方

      • 监听器 :一个对象

      • 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码

  • ServletContextListener:监听ServletContext对象的创建和销毁

    • 方法:

      • void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法

      • void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法

    • 步骤:

      1. 定义一个类,实现ServletContextListener接口

      2. 复写方法

      3. 配置

        1. web.xml <listener> <listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class> </listener>

      • 指定初始化参数<context-param>

        1. 注解:

          • @WebListener

监听器:

package cn.itcast.web.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;


@WebListener
public class ContextLoaderListener implements ServletContextListener {

    /**
     * 监听ServletContext对象创建的。ServletContext对象服务器启动后自动创建。
     *
     * 在服务器启动后自动调用
     * @param servletContextEvent
     */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //加载资源文件
        //1.获取ServletContext对象
        ServletContext servletContext = servletContextEvent.getServletContext();

        //2.加载资源文件
        String contextConfigLocation = servletContext.getInitParameter("contextConfigLocation");

        //3.获取真实路径
        String realPath = servletContext.getRealPath(contextConfigLocation);

        //4.加载进内存
        try{
            FileInputStream fis = new FileInputStream(realPath);
            System.out.println(fis);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("ServletContext对象被创建了。。。");
    }

    /**
     * 在服务器关闭后,ServletContext对象被销毁。当服务器正常关闭后该方法被调用
     * @param servletContextEvent
     */
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象被销毁了。。。");
    }
}

AJAX:

概念:

ASynchronous JavaScript And XML 异步的JavaScript 和 XML

  1. 异步和同步:客户端和服务器端相互通信的基础上

    • 同步:客户端必须等待服务器端的响应。在等待的期间客户端不能做其他操作。

      • 异步:客户端不需要等待服务器端的响应。在服务器处理请求的过程中,客户端可以进行其他的操作。

      Ajax 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 [1] 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。 传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。

      提升用户的体验

实现方式:

		2. JQeury实现方式
			1. $.ajax()
				* 语法:$.ajax({键值对});
				 //使用$.ajax()发送异步请求
		            $.ajax({
		                url:"ajaxServlet1111" , // 请求路径
		                type:"POST" , //请求方式
		                //data: "username=jack&age=23",//请求参数
		                data:{"username":"jack","age":23},
		                success:function (data) {
		                    alert(data);
		                },//响应成功后的回调函数
		                error:function () {
		                    alert("出错啦...")
		                },//表示如果请求响应出现错误,会执行的回调函数
		                dataType:"text"//设置接受到的响应数据的格式
		            });

			2. $.get():发送get请求	3. $.post():发送post请求==同理==
				* 语法:$.get(url, [data], [callback], [type])
                $.get(
		                "ajaxServlet1111" , // 请求路径
						{"username":"jack","age":23},
		                function (data) {
		                    alert(data);
		                },//响应成功后的回调函数
		                "json"//设置接受到的响应数据的格式
		            );
					* 参数:
						* url:请求路径
						* data:请求参数
						* callback:回调函数
						* type:响应结果的类型

只了解:

1. 原生的JS实现方式(了解)
					 //1.创建核心对象
		            var xmlhttp;
		            if (window.XMLHttpRequest)
		            {// code for IE7+, Firefox, Chrome, Opera, Safari
		                xmlhttp=new XMLHttpRequest();
		            }
		            else
		            {// code for IE6, IE5
		                xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
		            }
		
		            //2. 建立连接
		            /*
		                参数:
		                    1. 请求方式:GET、POST
		                        * get方式,请求参数在URL后边拼接。send方法为空参
		                        * post方式,请求参数在send方法中定义
		                    2. 请求的URL:
		                    3. 同步或异步请求:true(异步)或 false(同步)
		
		             */
		            xmlhttp.open("GET","ajaxServlet?username=tom",true);
		
		            //3.发送请求

​		            //4.接受并处理来自服务器的响应结果
​		            //获取方式 :xmlhttp.responseText
​		            //什么时候获取?当服务器响应成功后再获取
​		

		            //当xmlhttp对象的就绪状态改变时,触发事件onreadystatechange。
		            xmlhttp.onreadystatechange=function()
		            {
		                //判断readyState就绪状态是否为4,判断status响应状态码是否为200
		                if (xmlhttp.readyState==4 && xmlhttp.status==200)
		                {
		                   //获取服务器的响应结果
		                    var responseText = xmlhttp.responseText;
		                    alert(responseText);
		                }
		            }

JSON:

1. 概念:

JavaScript Object Notation JavaScript对象表示法 Person p = new Person(); p.setName("张三"); p.setAge(23); p.setGender("男");

var p = {"name":"张三","age":23,"gender":"男"};

  • json现在多用于存储和交换文本信息的语法

  • 进行数据的传输

  • JSON 比 XML 更小、更快,更易解析

2. 语法:

  1. 基本规则

    • 数据在名称/值对中:json数据是由键值对构成

      • 键用引号(单双都行)引起来,也可以不使用引号

        • 值得取值类型:

          1. 数字(整数或浮点数)

          2. 字符串(在双引号中)

          3. 逻辑值(true 或 false)

          4. 数组(在方括号中) {"persons":[{"name":"ll"},{"age":18}]}

          5. 对象(在花括号中) {"address":{"province":"陕西"....}}

          6. null

      • 数据由逗号分隔:多个键值对由逗号分隔

      • 花括号保存对象:使用{}定义json 格式

      • 方括号保存数组:[]

    1. 获取数据:

      1. json对象.键名

      2. json对象["键名"]

      3. 数组对象[索引]

      4. 遍历 //1.定义基本格式 var person = {"name": "张三", age: 23, 'gender': true};

        var ps = [{"name": "张三", "age": 23, "gender": true}, {"name": "李四", "age": 24, "gender": true}, {"name": "王五", "age": 25, "gender": false}];

           //获取ps中的所有值
            for (var i = 0; i < ps.length; i++) {
                var p = ps[i];
                for(var key in p){
                    alert(key+":"+p[key]);
                }
            }

3. JSON<==>Java

JSON解析器: * 常见的解析器:Jsonlib,Gson,fastjson,jackson

1. JSON转为Java对象
	1. **导入jackson的相关jar包**
	2. 创建Jackson核心对象 **ObjectMapper**
	3. 调用ObjectMapper的相关方法进行转换
		1. **readValue**(json字符串数据,Class)
2. Java对象转换JSON
	1. 使用步骤:
		1. 导入jackson的相关jar包
		2. 创建Jackson核心对象 **ObjectMapper**
		3. 调用ObjectMapper的相关方法进行转换
			1. 转换方法:
				* **writeValue**(参数1,obj):
                    参数1:
                        File:将obj对象转换为JSON字符串,并保存到指定的文件中
                        Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
                        OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
                * **writeValueAsString**(obj):将对象转为json字符串

			2. 注解:
				1. @JsonIgnore:排除属性。
				2. @**JsonFormat**:属性值得格式化
					* @JsonFormat(pattern = "yyyy-MM-dd")

			3. 复杂java对象转换
				1. List:数组
				2. Map:对象格式一致

案例:

* 校验用户名是否存在
	1. 服务器响应的数据,在客户端使用时,要想当做json数据格式使用。有两种解决方案:
		1. $.get(type):将最后一个参数type指定为"json"
		2. 在服务器端设置MIME类型
			response.setContentType("application/json;charset=utf-8");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值