javaweb

JSONMybatis

花卉管理系统

目前需要创建的包

dao

dao.impl

entity 存放实体

test 测试

util 工具

在实体类中,通常需要 实现 序列化接口

什么是mybatis

mybatis是一个半自动ORM框架

半自动:mybatis需要我们自己手写sql语句

注意: & 在xml中不能识别, 需要写成 &

普通环境搭建

步骤

  • 导包
  • 书写配置文件 mybatis.xml
  • 配置 Mapper.xml

配置文件mybatis.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai"></property>
                <property name="username" value="root"></property>
                <property name="password" value="tcx119"></property>
            </dataSource>
        </environment>
    </environments>

    <!--
        进行mapper文件扫描
    -->
    <mappers>
    	<!--
        resource: xml所在的目录
            读取本地磁盘的xml 要用 url(file:///D:1.xml)
    -->
        <mapper resource="cn/cqie/mapper/FlowerMapper.xml"></mapper>
    </mappers>

</configuration>

``Mapper.xml`

namespace规范参考

cn.cqie.mapper.FlowerMapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="a.b">

    <!--
        id: 方法名
        resultType: 返回值类型
        返回对象 写对象所在包的全路径
        返回集合 写集合的泛型
    -->

    <select id="selectAll" resultType="cn.cqie.entity.Flower" >
        select * from flower
    </select>
</mapper>

搭建优化

配置别名

在mybatis.xml中

    <typeAliases>
        <!-- 单独给某个文件起别名-->
        <typeAlias type="cn.cqie.entity.Flower" alias="a"></typeAlias>
        <!--给整个包下面的文件起别名   这时候别名的名称就是类的名称 不区分大小写-->
        <package name="cn.cqie.entity"/>
    </typeAliases>

属性的名称配置

jdbc.properties

m_driver=com.mysql.jdbc.Driver
m_url=jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
m_username=root
m_password = tcx119
导入jdbc.properties
<properties resource="jdbc.properties"/>

引入properties后的 value 变化

<property name="driver" value="${m_driver}"></property>
<property name="url" value="${m_url}"></property>
<property name="username" value="${m_username}"></property>
<property name="password" value="${m_password}"></property>

settings开启log4j的支持

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

三种查询方式

这里只弄了两种常用的

<select id="selectAll" resultType="flower">
    select * from flower
</select>

<select id="selectOne" resultType="flower">
    select * from flower where id = 1
</select>
//        List<Flower> list = sqlSession.selectList ("cn.cqieDay02.mapper.FlowerMapper.selectAll");
//        System.out.println (list);

        Object o = sqlSession.selectOne ("cn.cqieDay02.mapper.FlowerMapper.selectOne");
        System.out.println (o);

参数传递

传入单个参数

<select id="selectAll" resultType="flower" parameterType="int">
    select * from flower where id = #{param1}
</select>
List<Flower> list = sqlSession.selectList ("cn.cqieDay02.mapper.FlowerMapper.selectAll",1);
System.out.println (list);

传入对象

<select id="selectAll" resultType="flower" parameterType="flower">
    <!--id=#{对象中的属性名}  -->  
    select * from flower where id = #{id} and name=#{name}
</select>

#{id} #{name} 这里底层调用的 get方法

Flower flower = new Flower ();
flower.setId (1);
flower.setName ("meiguihua");
List<Flower> list = sqlSession.selectList ("cn.cqieDay02.mapper.FlowerMapper.selectAll",flower);
System.out.println (list);

传入map

<select id="selectAll" resultType="flower" >
    select * from flower where id = #{key1} and name=#{key1}
</select>
HashMap<String,Object> map = new HashMap<> ();
map.put ("key1",1);
map.put ("key2","meiguihua");
List<Flower> list = sqlSession.selectList ("cn.cqieDay02.mapper.FlowerMapper.selectAll",map);
System.out.println (list);

增删改操作(基于sqlSession)

insert

注意:mybatis默认不提交事务 ,需要我们自行提交

两种方式设置提交

  • 手动提交:在执行增加后,写 sqlSession.commit();
  • 自动提交:SqlSession sqlSession = factory.openSession (true); 把true写进去
<!--   增加操作-->
<insert id="insert">
   insert into flower values(DEFAULT,#{name},#{price},#{production})
</insert>

返回值类型可以省略

test

Flower flower = new Flower ();
flower.setName ("qianniuhua");
flower.setPrice (23);
flower.setProduction ("chn");
//增加
sqlSession.insert ("cn.cqieDay02.mapper.FlowerMapper.insert",flower);

delete

mapper

<!--     删除操作-->
   <delete id="delete">
       delete from flower where id=#{param1}
   </delete>

这个param1可以写成 args0, 建议写 param1

test

sqlSession.delete ("cn.cqieDay02.mapper.FlowerMapper.delete",5);

update

mapper

<!--    修改-->
<update id="update">
    update flower set name=#{name},price = #{price} ,production = #{production} where id = ${id}
</update>

test

flower.setName ("huahuawy");
flower.setPrice (999);
flower.setProduction ("chn");
flower.setId (4);
sqlSession.update ("cn.cqieDay02.mapper.FlowerMapper.update",flower);

Mapper代理实现增删改查

sqlSession进行增删改查的缺点

  • 无法实现多参传递
  • 书写的时候无接口,后期的维护就比较低

步骤:

  1. 在mapper包中编写接口,与xml文件
  2. 在mapper中的对应xml文件中关联接口,namespace="接口的路径" 直接copy reference
  3. mybatis.xml中扫描mapper中的对应xml文档
  4. 在mapper中对应xml文件中编写代码
  5. 编写test文件

注意:mapper中对应xml文件中的 id 应与 mapper 中接口的方法名对应(方法名要一样)

insert

//mapper中的接口
    //查询所有
    List<Flower> selectAll();
//test文件
 FlowerMapperInterface mapper = sqlSession.getMapper (FlowerMapperInterface.class);
mapper.insert(flower);

select,delete,update与insert类似

多参传递

传的都是值,以select为例

//mapper中的接口
//多参传递
    Flower selectOne(int id,String name);
//test文件
 //多参传递
        Flower flower = mapper.selectOne (10, "molihuahua");

注意:在xml中写sql语句时,select 的 一定要写返回类型

传的两个对象,以select为例

//mapper中的接口
 //传入两个对象
    Flower selectOne2(Flower f1,Flower f2);
//test文件
 //传入两个对象
   //传入两个对象
        System.out.println ("传入两个对象的结果");
        Flower f1 = new Flower ();
        Flower f2 = new Flower ();
        f1.setId (6);
        f2.setName ("qianniuhua");
        Flower selectOne2 = mapper.selectOne2 (f1, f2);
        System.out.println (selectOne2);

mybatis.xml文档的小优化

    <package name="cn.cqieDay02.mapper"></package>

@Param方式

Flower selectOne2(@Param("uu") int id,@Param("yy") String name);

sql语句中: #{uu} #

动态SQL

目前学习的内容sql语句都是直接写死的,但是在实际的开发过程中很多的sql语句都是根据不同的业务情况进行不同的改变的。

为了解决这个问题,就用sql语句的动态拼接

学习的标签:

if where when set trim foreach bind include sql

if标签

相当于 if() {}

when标签

相当于 if(){} else if(){}

Where标签的作用:会自动的增加where关键字,并且会把多余的第一个and去掉

foreach

另外一个动态 SQL 通用的必要操作是迭代一个集合, 通常是构建在 IN 条件中的。

eg

<select id="selectMore" resultType="flower">
        select * from flower where id in
        <foreach collection="list" open="(" close=")" separator="," item="it">
            #{it}
        </foreach>
    </select>

其余功能参考说明文档

bind

bind 就是在like后 ,通常在模糊查询中用

eg

<select id="selectMore2" resultType="flower">
        select * from flower
        <where>
            <if test="param1!=null and param1!='' ">
                <bind name="pa" value="'%'+param1+'%'"></bind>
                name like #{pa}
            </if>
        </where>
    </select>

还有种方式 就是用 $符号 (会有sql注入风险)

sql include

sql定义公共的SQL代码片段

include 处就是替换原有的

<select id="selectMore2" resultType="flower">
        select <include refid="sq1"></include> from flower
        <where>
            <if test="param1!=null and param1!='' ">
                <bind name="pa" value="'%'+param1+'%'"></bind>
                name like #{pa}
            </if>
        </where>
    </select>
    
    <sql id="sq1">
        id,name,price
    </sql>

多表查询

业务代码查询A

eg

就是先查询出所有的学生信息,然后根据学生信息查询班级信息。

public interface StudentMapper {
    List<Student> selectAll();
}
public interface ClazzMapper {
    Clazz selectOne(int clazzno);
}
//test文件
 StudentMapper studentMapper = sqlSession.getMapper (StudentMapper.class);
        ClazzMapper clazzMapper = sqlSession.getMapper (ClazzMapper.class);

        List<Student> list = studentMapper.selectAll ();
        for(Student stu:list){
            int clazzno = stu.getClazzno ();
            Clazz cla = clazzMapper.selectOne (clazzno);
            System.out.println (stu+ "---> " + cla);
        }

业务代码查询B

类似于A

//test文件
 StudentMapper studentMapper = sqlSession.getMapper (StudentMapper.class);
        ClazzMapper clazzMapper = sqlSession.getMapper (ClazzMapper.class);
 List<Clazz> clazzList = clazzMapper.selectAll ();
        for(Clazz cla:clazzList){
            int clazzno = cla.getClazzno ();
            List<Student> students = studentMapper.selectMore (clazzno);
//            System.out.println (cla+"-->"+ students);
            cla.setStudentList (students);
            System.out.println (cla);
        }

N+1方式查询

什么是N+1的查询方式?

如果没有N+1的方式我们想要实现多表的查询,自己书写查询的业务逻辑代码(java)

mybatis希望通过自己标签配置的方式来解决这个问题

[2]执行的操作

​ 查询学生所在班级的信息(一对一)

​ 查询班级中所有学生的信息(一对多)

使用的时候书写标签需要注意:

查询出来返回的是一个对象:association

查询出来返回的是一个集合:collection

总结: 业务装配方式和N+1查询方式

​ 共同点:执行SQL语句的条数上都是N+1条语句

​ 不同点:

​ 业务装配方式:是我们自己书写java代码的方式进行配置的

​ N+1方式:通过MyBatis标签配置的方式实现的

eg

查询学生所在班级的信息(一对一)

<!--   studentMapper.xml文件     -->
<select id="selectAll" resultMap="rm1">
        select * from student
    </select>
    
    <resultMap id="rm1" type="student">
	<!--        <id> </id> -->
        <association select="cn.cqieDay03.mapper.ClazzMapper.selectOne"  column="clazzno" javaType="clazz"  property="cla"></association>
        <!-- 返回的是集合就用collection -->
    </resultMap>
<!--        
	select:执行哪个方法
	column:希望查询结果的哪一列作为参数传递
	javaType:返回值类型
	properety:把返回的结果赋值给对象中哪一个属性
-->
<!--   clazzMapper.xml文件  -->
 <select id="selectOne" resultType="clazz">
        select * from clazz where clazzno = #{param1}
    </select>

image-20210905231349451

多表查询

<!-- StudentMapper.xml文件-->
<select id="selectAll2" resultMap="rm2">
        select * from student stu join clazz cla on stu.clazzno = cla.clazzno
    </select>
    <resultMap id="rm2" type="student">
<!--        书写的值就是接收数据库查询的数据,想要接收的数据字段不可以省去-->
        <id column="sid" property="sid"></id>
        <result column="sname" property="sname"></result>
        <result column="clazzno" property="clazzno"></result>
        <association  property="cla" javaType="clazz">
            
            <id column="clazzno" property="clazzno"></id>
            <result column="cname" property="cname"></result>
        </association>
    </resultMap>

image-20210906105330542

resultType与resultMap的使用场景

  • 如果你做的是单表的查询并且封装的实体和数据库的字段一一对应 resultType

  • 如果实体封装的属性和数据库的字段不一致 resultMap

  • 使用的是多表的联合查询 resultMap

  • 使用N+1查询的时候 resultMap

Mybatis中的缓存

sqlsession一级缓存

使用SqlSession对象操作数据库资源时,SqlSession对象会先去其缓存区查找是否有现成的符合要求的数据,如果有则返回,没有则按照需求进行数据库操作获取符合要求的资源,并将资源返回给用户的同时在其缓存中缓存,当我们使用同一个SqlSession对象操作同一个Sql资源时,就可以从缓存中直接获取数据库资源数据了

image-20210907202115991

factory的缓存(二级缓存)

使用的方法:

  • 在Mybatis.xml中开始二级缓存

  • 在对应的mapper.xml文件中<cache readOnly="true">

  • 关闭获得提交指定的sqlsesson对象

注意 当用户查询时,会先在Factory对象自己的缓存中查看是否有现成的数据,有则直接返回,没有则继续查看sqlSession中是否有,有则返回,没有则去数据库中获取资源,将资源返回的同时在SqlSession的缓存中缓存一份儿,当该SqlSession对象被commit或者close时将其缓存的数据刷入到Factory中。

查询数据顺序 二级-->一级--->数据库--->把数据保存到一级,当sqlsession关闭或者提交的时候,把数据刷入到二级缓存中

image-20210907201713117

ThreadLocal

网上查阅

Mybaties注解支持

接口中的代码

	@Select("select *  from  student")  
	List<Student>  selectAll();  
	  
	@Select("select *  from  student where  sid=#{param1}")  
	Student  selectOne(int id);  
	  
	@Insert("insert into  student   values(default,#{sname},#{clazzno})")  
	int  insert(Student  student);  
  
	@Update("update  student set  sname=#{sname} where  sid=#{sid}")  
	int  update(Student  student);  
	  
	@Delete("delete  from  student  where sid=#{param1}")  
	int  delte(int sid);

注解优缺点

  • 使用注解没有实现java代码个sql语句的解耦

  • 进行多表的查询比较的麻烦

  • 无法实现sql语句的动态拼接

JSP

发布项目到服务器并访问

需求说明:

  • 创建Web项目,开发静态页面
  • 部署到服务器Tomcat
  • 启动服务器Tomcat
  • 不同用户通过浏览器来访问Web项目

image-20210908232902855

本地地址:127.0.0.1

image-20210909105052921

JSP = Java Server Pages

Sun公司推出的动态网页技术,类似的技术还包括ASP、PHP。相对的技术是HTML(静态网页技术)

动态生成网页数据,而不是有动态效果的网页!

JSP是在HTML中嵌入Java脚本代码

JSP是服务器端技术(JavaScript是客户端技术)

由应用服务器来编译和执行嵌入的Java脚本代码,然后将生成的整个页面信息返回给客户端

JSP本质就是java

image-20210909123857910

统计网站访问人数

jsp文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>统计访问人数</title>
</head>
<body>
    <%! int count=0;
    %>
    <%
        out.print("网站访问总人数"+count++);
    %>
</body>
</html>

小总结

  • jsp的本质就是一个servlet(就是类)
  • 在jsp页面中书写java代码的方式
    • 小脚本 <% %>
    • 表达式
    • 声明式 <%! %>
  • 小脚本和声明式的区别
    • 小脚本声明的变量是局部变量,在声明式中声明的变量是成员变量
    • 小脚本中不可以定义方法,在声明式中可以定义方法
    • 小脚本可以使用jsp的内置对象,声明式中不可以 (比如 out)
  • 注释
    • java中的三种注释
    • HTML的注释
    • jsp注释 推荐使用:优点:节省网络的带宽,可以增快访问的速度

jsp标签

include

<!--动态包含 ---动作标识 -->

<% <jsp:include page="1.jsp"></jsp:include> %>

<!--静态包含---指令标识 -->

<%@include file="head.jsp" %>

forward param 使用方式同上

动态包含和静态包含的区别:

  • 静态的引入式把代码原封不动的复制到主文件中,动态的引入是相当于方法的调用

  • 静态的引入的方式引入文件和主文件中是不可以存在同名的变量 ,动态的引入可以存在

  • 静态的引入式不会产生class文件 ,动态的引入式产生class文件

  • 静态的引入产生的时机是第一个阶段 ,动态的引入式产生产生的时机是第三阶段

  • 共同点:

    都可以实现网页的引入

image-20210909143517789

image-20210909143628713

Jsp模拟登陆

login

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="doLogin.jsp">
        <p>
            请输入用户名:<input type="text" name="uname">
        </p>
        <p>
            请输入密码: <input type="text" name="pwd">
        </p>
        <p>
            <input type="submit" value="登录">
        </p>
        
    </form>
</body>
</html>

doLogin

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        String name = "1234";
        String pwd  = "1357";
        String uname = request.getParameter("uname");
        String pwd1 = request.getParameter("pwd");
        if (name.equals (uname)&&pwd.equals (pwd1)){
            out.print("登录成功");
        }else{
            out.print("登录失败");
        }
    %>
</body>
</html>

浏览器端控制的跳转方式有几种?

  • 直接输入URL地址
  • 提交form表单
  • 超链接方式

image-20210911155911251

Servlet

可以用做动态网页开发

流程

  • 首先写一个class类 去继承一个Httpservlet

  • 重写service方法,注意一定要把super.service()去掉

  • 进行动态网页的开发--那如何访问这个servlet呢?需要配置

  • 在web.xml中进行配置

MyServlet.java

package cn.cqie.servlet;
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;

/**
 * ClassName:
 * Description
 *
 * @Author admin
 * @create 2021/9/12 22:47
 * Version
 * project
 */
public class MyServlet  extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.service (req, resp);
        resp.setContentType ("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter ();
        out.print ("<html>");
            out.print ("<body>");
                out.print ("<h3>this is my first servlet 哈哈</h3>");
            out.print ("<body>");
        out.print ("<html>");
    }
}

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-name>a123</servlet-name>
        <servlet-class>cn.cqie.servlet.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>a123</servlet-name>
<!--            注意:路径之前一定要加 /-->
        <url-pattern>/abc</url-pattern>
    </servlet-mapping>
</web-app>

Servlet进行流程控制

image-20210913152037868

DoLogin.java


public class DoLogin extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //处理信息,检查是否匹配
        String name = "1234";
        String pwd  = "1357";
        String uname = request.getParameter("uname");
        String pwd1 = request.getParameter("pwd");
        if (name.equals (uname)&&pwd.equals (pwd1)){
//            out.print("登录成功");
//            转发功能
            request.getRequestDispatcher ("success.jsp").forward (request,response);
        }else{
//            out.print("登录失败");
//            转发功能
            request.getRequestDispatcher ("login.jsp").forward (request,response);
        }
    }
}

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-name>a123</servlet-name>
        <servlet-class>cn.cqie.servlet.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>a123</servlet-name>
<!--            注意:路径之前一定要加 /-->
        <url-pattern>/abc</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>DoLogin</servlet-name>
        <servlet-class>cn.cqie.servlet.DoLogin</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>DoLogin</servlet-name>
        <url-pattern>/DoLogin</url-pattern>
    </servlet-mapping>
</web-app>

生命周期

servlet是一个单实例 多线程的程序

​ servlet的生命周期

​ 【1】类加载

​ "com.bjsxt.servlet.LifeServlet"

​ Class clazz= Class.forName("com.bjsxt.servlet.LifeServlet");

​ 【2】实例化 (离不开反射)

​ Object obj= clazz.newInstance();

​ 【3】 初始化(离不开反射)

​ 【4】服务请求(service)(离不开反射)

​ 【5】 销毁操作(离不开反射)

类加载的时机

​ 【1】默认的情况是第一次访问servlet的时候进行类加载

​ 【2】0(当启动服务器时候加载) 数字越小加载的时机越往前

API

Servlet接口:所有servlet必须直接或间接实现的类。

init( ServletConfig config )

service(ServletRequest req, ServletResponse res)

destroy()

getServletInfo():获得Servlet信息。

getServletConfig():获得Servlet配置相关信息

GenericServlet抽象类:implements Servlet, ServletConfig

定义了一个通用的,不依赖于具体协议的Servlet,给出了除service()方法外的其余四个方法的实现。

public void init(ServletConfig config) thows SerletExcepiton

protected void init() thows SerletExcepiton

第一个是servlet接口的init(),调用第二个init(), 重写第二个init()即可

HttpServlet类

public void service(ServletRequest req, ServletResponse res)

protected void service(HttpServletRequest req, HttpServletResponse res)

protected void doGet(request,response)

protected void doPost(request,response)

public service()是父类的方法,protected service()是自己的方法。前者首先把参数分别转换为HttpServletRequest和HttpServletResponse ,再调用protected service();

protected service()根据HTTP请求方法的类型调用相应doXXX()方法

我们自己编写的servlet应该继承HttpServlet,一般要覆盖Service或者doPost/doGet方法。

参数读取

设置编码 UTF-8;

ParamServlet.java

public class ParamServlet extends HttpServlet {

    String enc1;
    @Override
    public void init() throws ServletException {

        enc1 = this.getServletContext ().getInitParameter ("enc");
        System.out.println (enc1);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType ("text/html;charset="+enc1);

    }
}

web.xml

 <context-param>
        <param-name>enc</param-name>
        <param-value>UTF-8</param-value>
    </context-param>

<servlet>
        <servlet-name>ParamServlet</servlet-name>
        <servlet-class>cn.cqie.servlet.ParamServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ParamServlet</servlet-name>
        <url-pattern>/ParamServlet</url-pattern>
    </servlet-mapping>

中文乱码问题

get方式和Post提交方式的区别

  • get数据的传输是不安全的 ,post数据传递更加安全

  • get方式数据传递有大小限制 post传输数据没有限制

  • get传输的数据速度比较快 post比较慢

解决post提交乱码

request.setCharacterEncoding

解决GET方式提交的乱码

方式1

byte [] bytes = str.getBytes("iso-8859-1");

String cstr = new String(bytes,"utf-8");

方式2

在server.xml中指定对应的服务器编码

URIEncoding="utf-8"

请求和响应

在JAVAEE 6 以上 支持@WebServlet(/abc) 注解

HttpServletRequest类

i. getRequestURI() 获取请求的资源路径
ii. getRequestURL() 获取请求的统一资源定位符(绝对路径)
iii. getRemoteHost() 获取客户端的ip 地址
iv. getHeader() 获取请求头
v. getParameter() 获取请求的参数
vi. getParameterValues() 获取请求的参数(多个值的时候使用)
vii. getMethod() 获取请求的方式GET 或POST
viii. setAttribute(key, value); 设置域数据
ix. getAttribute(key); 获取域数据
x. getRequestDispatcher() 获取请求转发对象

ServletAPI.java

public class ServletAPI extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取情求的资源路径
        System.out.println ("UTI==> "+req.getRequestURI ());
        //获取情求的资源统一定位符(
        System.out.println ("UTL==> "+req.getRequestURL ());
    }
}

image-20210922164632587

Base标签作用

image-20210922204425787

c.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <base href="http://localhost:8080/servlet/a/b/">
</head>
<body>
    我是a>> b  >> 下面的  c
    <a href="../../index.jsp">返回主页</a>
</body>
</html>

index

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  $END$123

  <a href="a/b/c.html">超链接跳转</a>
  <a href="http://localhost:8080/servlet/forward">转发跳转</a>
  </body>
</html>

web中的/

/ 斜杠 如果被浏览器解析,得到的地址是: http://ip:port

/ 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径

​ 1、/servlet1
​ 2、servletContext.getRealPath(“/”);
​ 3、request.getRequestDispatcher(“/”);

特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到http://ip:port/

HttpServletResponse 类

HttpServletResponse 类和HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个Response 对象传
递给Servlet 程序去使用。HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息,
我们如果需要设置返回给客户端的信息,都可以通过HttpServletResponse 对象来进行设置

两个输出流的说明

字节流 getOutputStream(); 常用于下载(传递二级制数据)

字符流 getWriter(); 常用于回传字符串(常用)

两个流同时只能使用一个。

往客户端回传数据

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter ();
        writer.write ("helllo ");
    }
}

解决乱码问题

resp.setContentType("text/html;charset=UTF-8");

注意:这个要放在获取流对象之前。 这个同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType ("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter ();
        System.out.println (resp.getCharacterEncoding ());
        writer.write ("你好呀");
    }
}

请求重定向

image-20210923222453514

请求重定向的第一种方案:
// 设置响应状态码302 ,表示重定向,(已搬迁)
resp.setStatus(302);
// 设置响应头,说明新的地址在哪里
resp.setHeader("Location", "http://localhost:8080");
请求重定向的第二种方案(推荐使用):
resp.sendRedirect("http://localhost:8080");

Listener监听器

1、Listener 监听器它是JavaWeb 的三大组件之一。JavaWeb 的三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监
听器。
2、Listener 它是JavaEE 的规范,就是接口
3、监听器的作用是,监听某种事物的变化。然后通过回调函数,反馈给客户(程序)去做一些相应的处理

MyServletListenerContextLisenerIMPL .java

public class MyServletListenerContextLisenerIMPL implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println ("ServletContext对象被创建了");
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println ("ServletContext对象被销毁了");
    }
}

web.xml

    <listener>
        <listener-class>cn.cqie.servlet.MyServletListenerContextLisenerIMPL</listener-class>
    </listener>

EL表达式

概念

什么是EL表达式,EL表达式的作用?

EL 表达式的全称是:Expression Language 是表达式语言

EL表达式的作用:EL表达式主要是代替jsp页面中的表达式脚本在jsp页面中进行输出。

因为EL表达式在输出数据的时候,要比jsp的表达式脚本简洁很多

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  $END$
  <%
    request.setAttribute("key1","值");
  %>
  request获取的值: <%= request.getAttribute ("key1")%> <br>
  EL获取的值是: ${key1}
  </body>
</html>

image-20210927230244395

EL表达式的格式: ${表达式}

EL表达式在输出null值时,输出的是空串,jsp表达式输出的是null

EL 表达式搜索域数据的顺序

EL表达式主要是在jsp页面中输出数据

主要是输出域对象中的数据

当四个域中都有相同的key的数据的时候,EL表达式会按照四个域的从小到大的顺序去进行搜索,找到就输出

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  $END$
  <%
    pageContext.setAttribute ("key1","pageContext");
    request.setAttribute("key1","request");
    session.setAttribute ("key1","session");
    application.setAttribute ("key1","application");
  %>
  EL获取的值是: ${key1}
  </body>
</html>

Empty

empty 运算可以判断一个数据是否为空,如果为空,则输出true,不为空输出false。
以下几种情况为空:
1、值为null 值的时候,为空
2、值为空串的时候,为空
3、值是Object 类型数组,长度为零的时候
4、list 集合,元素个数为零
5、map 集合,元素个数为零

<body>
<%
// 1、值为null 值的时候,为空
request.setAttribute("emptyNull", null);
// 2、值为空串的时候,为空
request.setAttribute("emptyStr", "");
// 3、值是Object 类型数组,长度为零的时候
request.setAttribute("emptyArr", new Object[]{});
// 4、list 集合,元素个数为零
List<String> list = new ArrayList<>();
// list.add("abc");
request.setAttribute("emptyList", list);
// 5、map 集合,元素个数为零
Map<String,Object> map = new HashMap<String, Object>();
// map.put("key1", "value1");
request.setAttribute("emptyMap", map);
%>
${ empty emptyNull } <br/>
${ empty emptyStr } <br/>
${ empty emptyArr } <br/>
${ empty emptyList } <br/>
${ empty emptyMap } <br/>
</body>

三元表达式

表达式1?表达式2:表达式3
如果表达式1 的值为真,返回表达式2 的值,如果表达式1 的值为假,返回表达式3 的值。

. 与 [ ] 运算

.点运算,可以输出Bean 对象中某个属性的值。
[]中括号运算,可以输出有序集合中某个元素的值。
并且[]中括号运算,还可以输出map 集合中key 里含有特殊字符的key 的值。

11个隐含对象

EL 个达式中11 个隐含对象,是EL 表达式中自己定义的,可以直接使用。
变量 类型 作用
pageContext PageContextImpl 它可以获取jsp 中的九大内置对象
pageScope Map<String,Object> 它可以获取pageContext 域中的数据
requestScope Map<String,Object> 它可以获取Request 域中的数据
sessionScope Map<String,Object> 它可以获取Session 域中的数据
applicationScope Map<String,Object> 它可以获取ServletContext 域中的数据
param Map<String,String> 它可以获取请求参数的值
paramValues Map<String,String[]> 它也可以获取请求参数的值,获取多个值的时候使用。
header Map<String,String> 它可以获取请求头的信息
headerValues Map<String,String[]> 它可以获取请求头的信息,它可以获取多个值的情况
cookie Map<String,Cookie> 它可以获取当前请求的Cookie 信息

initParam Map<String,String> 它可以获取在web.xml 中配置的上下文参数

pageScope ====== pageContext 域
requestScope ====== Request 域
sessionScope ====== Session 域
applicationScope ====== ServletContext 域

image-20210929175727488

文件的上传和下载

文件的上传和下载,是非常常见的功能。很多的系统中,或者软件中都经常使用文件的上传和下载。
比如:QQ 头像,就使用了上传。
邮箱中也有附件的上传和下载功能。
OA 系统中审批有附件材料的上传。

文件的上传介绍(重点)

  • 要有一个form 标签,method=post 请求
  • form 标签的encType 属性值必须为multipart/form-data 值
  • 在form 标签中使用input type=file 添加上传的文件
  • 编写服务器代码(Servlet 程序)接收,处理上传的数据。

encType=multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼
接,然后以二进制流的形式发送给服务器

uploaded.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="servletUploade" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="uname"><br>
    文件:<input type="file" name="douc"><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

ServletUpload.java

public class ServletUpload  extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println ("获取成功");
        System.out.println ("获取二进制");
        ServletInputStream inputStream = req.getInputStream ();
        byte[] buffer = new byte[102400];
        int read = inputStream.read (buffer);
        System.out.println (new String (buffer,0,read));
    }
}

commons-fileupload.jar常用API说明

commons-fileupload.jar 需要依赖commons-io.jar 这个包,所以两个包我们都要引入。

commons-fileupload.jar 和commons-io.jar 包中,我们常用的类有哪些?

作用
ServletFileUpload 用于解析上传的数据
FileItem 表示每一个表单项
boolean ServletFileUpload.isMultipartContent(HttpServletRequest request) 判断当前上传的数据格式是否是多段的格式
public List parseRequest(HttpServletRequest request) 解析上传数据
boolean FileItem.isFormField() 判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。
true 表示普通类型的表单项
false 表示上传的文件类型
String FileItem.getFieldName() 获取表单项的name 属性值
String FileItem.getString() 获取当前表单项的值
String FileItem.getName() 获取上传的文件名
void FileItem.write( file ) 将上传的文件写到参数file 所指向抽硬盘位置

ServletUpload.java

public class ServletUpload  extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       System.out.println ("获取成功");
        System.out.println ("获取二进制");
        ServletInputStream inputStream = req.getInputStream ();
        byte[] buffer = new byte[102400];
        int read = inputStream.read (buffer);
        System.out.println (new String (buffer,0,read));


        //先判断上传的数据是否多段数据(只有是多段的数据,才是文件上传的)
        if (ServletFileUpload.isMultipartContent (req)){
//            创建FileItemFactory 工厂实现类
            DiskFileItemFactory fileItemFactory = new DiskFileItemFactory ();
            // 创建用于解析上传数据的工具类ServletFileUpload 类
            ServletFileUpload servletFileUpload = new ServletFileUpload (fileItemFactory);
            try {
                // 解析上传的数据,得到每一个表单项FileItem
                List<FileItem> list = servletFileUpload.parseRequest (req);
                // 循环判断,每一个表单项,是普通类型,还是上传的文件
                for (FileItem fileItem : list) {
                    if(fileItem.isFormField ()){
                        // 普通表单项
                        System.out.println ("表单的name属性: "+fileItem.getFieldName ());
                        // 参数UTF-8.解决乱码问题
                        System.out.println ("表单项的value值: "+fileItem.getString ("UTF-8"));
                    }else{
                        //上传的文件
                        System.out.println ("表单的name属性: "+fileItem.getFieldName ());
                        System.out.println ("上传的文件名: "+fileItem.getName ());
                        fileItem.write (new File ("D://ForJavawebFiles//"+fileItem.getName ()));
                    }
                }

            } catch (Exception e) {
                e.printStackTrace ();
            }
        }
    }
}

免用户名登录

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/doLogin" method="post" >
    用户名:<input type="text" name="username" value="${cookie.username.value}"><br>
    密码:<input type="text" name="password" ><br>
    <input type="submit" value="登录">
</form>
</body>
</html>

DoLogin.java

public class DoLogin extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter ("username");
        String password = req.getParameter ("password");
        if("tcx123".equals (username)&&"123".equals (password)){
            //登录成功
            Cookie cookie = new Cookie ("username",username);
            cookie.setMaxAge (60*60);
            resp.addCookie (cookie);
            System.out.println ("登录成功");
        }else{
            System.out.println ("登录失败");
        }
    }
}

Session

什么是session

  • 一个接口(HttpSession)
  • 是会话

Session的创建和获取

request.getSession()

​ 第一次调用是:创建session 会话

​ 之调用都是:获取前面创建好的Session会话对象

isNew() 判断是不是刚创建出来的(新的)

​ true: 表示刚创建

​ false:获取之前的创建

每一个会话都有一个身份证号码。也就是ID值,ID值是惟一的。

getId() 得到session的id 值

Session域对象的存取

SessionServlet.java

public class SessionServlet extends BaseServlet {
    protected void setAttribute(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.getSession ().setAttribute ("key1","value1");
        resp.getWriter ().write ("已经往Session中保存了数据");
    }
    protected void getAttribute(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Object attribute = req.getSession ().getAttribute ("key1");
        resp.getWriter ().write ("从Session 中获取出key1 的数据是:" + attribute);
    }
    protected void createOrGetSession(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        HttpSession session = req.getSession ();
        boolean aNew = session.isNew ();
        resp.getWriter ().write ("session的id: "+session.getId ());
        resp.getWriter ().write ("session是否是新的: "+aNew);
//        System.out.println ("session的id: "+session.getId ());
//        System.out.println ("session是否是新的: "+aNew);
    }
}

Session生命周期控制

public void setMaxInactiveInterval(int interval) 设置Session 的超时时间(以秒为单位),超过指定的时长,Session
就会被销毁。
值为正数的时候,设定Session 的超时时长。
负数表示永不超时(极少使用)
public int getMaxInactiveInterval() 获取Session 的超时时间
public void invalidate() 让当前Session 会话马上超时无效。
Session 默认的超时时长是多少!
Session 默认的超时时间长为30 分钟。
因为在Tomcat 服务器的配置文件web.xml 中默认有以下的配置,它就表示配 置了当前Tomcat 服务器下所有的Session
超时配置默认时长为:30 分钟。

<session-config>
<session-timeout>30</session-timeout>
</session-config>

如果说。你希望你的web 工程,默认的Session 的超时时长为其他时长。你可以在你自己的web.xml 配置文件中做
以上相同的配置。就可以修改你的web 工程所有Seession 的默认超时时长。

<!--表示当前web 工程。创建出来的所有Session 默认是20 分钟超时时长-->
<session-config>
<session-timeout>20</session-timeout>
</session-config>

Session销毁

    
//在SessionServlet.java文件下
	protected void deleteNow(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.getSession ().invalidate ();
        resp.getWriter ().write ("session已经超时");
    }

浏览器和Session之间的技术内幕

Session 技术,底层其实是基于Cookie 技术来实现的。

image-20211005163910809

Filter

什么是过滤器

1、Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器

2、Filter 过滤器它是 JavaEE 的规范。也就是接口

3、Filter 过滤器它的作用是:拦截请求,过滤响应。

拦截请求常见的应用场景有:

1、权限检查

2、日记操作

3、事务管理

​ ……等等

Filter的初体验

要求:要求:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必

​ 须是用户登录之后才允许访问。

思考:根据之前我们学过内容。我们知道,用户登录之后都会把用户登录的信息保存到 Session 域中。所以要检查用户是否

登录,可以判断 Session 中否包含有用户登录的信息即可!!!

Filter的工作流程

image-20211009125451421

AdminFilter.java

public class AdminFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /**
     *doFilter 方法,专门勇于拦截请求,可以做权限申请
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();
        Object user = session.getAttribute("user");
        if(user==null){
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return ;
        }else{
            //让程序继续往下访问用户的目标资源
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {

    }
}

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">
    <!--filter 标签用于配置一个 Filter 过滤器-->
    <filter>
        <!--给 filter 起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置 filter 的全类名-->
        <filter-class>cn.cqie.test.AdminFilter</filter-class>
    </filter>
    <!--filter-mapping 配置 Filter 过滤器的拦截路径-->
    <filter-mapping>
        <!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
        <filter-name>AdminFilter</filter-name>
        <!--url-pattern 配置拦截路径 / 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
         /admin/* 表示请求地址为:http://ip:port/工程路径/admin/* -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>
</web-app>

Filter 过滤器的使用步骤:

1、编写一个类去实现 Filter 接口

2、实现过滤方法 doFilter()

3、到 web.xml 中去配置 Filter 的拦截路径

完善的用户登录

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    登录界面
    <form action="http://localhost:8080/Filter/loginServlet" method="post">
        用户名:<input type="text" name="username"><br>
        密码: <input type="password" name="password"><br>
        <input type="submit">
    </form>
</body>
</html>

LoginServlet.java

public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if("123".equals(username)&&"123".equals(password)){
            req.getSession().setAttribute("user",username);
            resp.getWriter().write("登录成功 !!");
        }else{
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }
    }
}

Filter 的生命周期

Filter 的生命周期包含几个方法

​ 1、构造器方法

​ 2、init 初始化方法

​ 第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)

​ 3、doFilter 过滤方法

​ 第 3 步,每次拦截到请求,就会执行

​ 4、destroy 销毁

​ 第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,会销毁 Filter 过滤器)

FilterCongif类

FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。

Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。

FilterConfig 类的作用是获取 filter 过滤器的配置内容

​ 1、获取 Filter 的名称 filter-name 的内容

​ 2、获取在 Filter 中配置的 init-param 初始化参数

​ 3、获取 ServletContext 对象

java代码

public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter的初始化方法");

        System.out.println("filter-name  "+filterConfig.getFilterName());
        System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));
        System.out.println(filterConfig.getServletContext());
    }

web.xml

<filter>
        <!--给 filter 起一个别名-->
        <filter-name>AdminFilter</filter-name>
        <!--配置 filter 的全类名-->
        <filter-class>cn.cqie.test.AdminFilter</filter-class>
        <init-param>
            <param-name>username</param-name>
            <param-value>tcx</param-value>
        </init-param>
    </filter>
    <!--filter-mapping 配置 Filter 过滤器的拦截路径-->
    <filter-mapping>
        <!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
        <filter-name>AdminFilter</filter-name>
        <!--url-pattern 配置拦截路径 / 表示请求地址为:http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
         /admin/* 表示请求地址为:http://ip:port/工程路径/admin/* -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

注意: 的位置

FilterChain 过滤器链

image-20211009142638279

Filter的拦截路径

精确匹配:

​ <url-pattern>/target.jsp</url-pattern>

​ 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp

目录匹配:

​ <url-pattern>/admin/*</url-pattern>

​ 以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/admin/*

后缀名匹配:

​ <url-pattern>*.html</url-pattern>

​ 以上配置的路径,表示请求地址必须以.html 结尾才会拦截到

​ <url-pattern>*.do</url-pattern>

​ 以上配置的路径,表示请求地址必须以.do 结尾才会拦截到

​ <url-pattern>*.action</url-pattern>

​ 以上配置的路径,表示请求地址必须以.action 结尾才会拦截到

​ Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在!!!

JSON

JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。JSON

采用完全独立于语言的文本格式,而且很多语言都提供了对 json 的支持(包括 C, C++, C#, Java, JavaScript, Perl, Python

等)。 这样就使得 JSON 成为理想的数据交换格式。

json 是一种轻量级的数据交换格式。

轻量级指的是跟 xml 做比较。

数据交换指的是客户端和服务器之间业务数据的传递格式

JSON在JavaScript中的使用

json定义:json 是由键值对组成,并且由花括号包围,每个键由引号引起来,键和值之间使用冒号进行分隔,多组键值对之间用逗号进行分隔。

JSON的两个常用方法:

JSON的存在有两种形式。

  • 对象的形式存在,叫做json对象
  • 字符串的形式存在,叫做json字符串

一般我们要操作JSON中的数据的时候,需要JSON对象的格式。

一般我们要在客户端和服务器之间进行数据交换的时候,使用JSON字符串

JSON.stringify() 把JSON对象转换成json字符串

JSON.parse() 把JSON字符串转换成JSON对象

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: tiancx
  Date: 2021/10/9
  Time: 15:11
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
    <script>
      var jsonObj = {
        "key1":12,
        "key2":"abc",
        "key3":true,
        "key4":[11,"arr",false],
        "key5":{ "key5_1" : 551, "key5_2" : "key5_2_value" },
        "key6":[{ "key6_1_1":6611, "key6_1_2":"key6_1_2_value"},
          {"key6_2_1":6621, "key6_2_2":"key6_2_2_value" }] };
      // alert(jsonObj.key1);
      // alert(jsonObj.key4);
      //json 中数组的遍历
      // for(var i=0;i<jsonObj.key4.length;i++){
      //   alert(jsonObj.key4[i]);
      // }
      // alert(jsonObj.key5.key5_1);
      // alert(jsonObj.key6);
      // var jsonItem = jsonObj.key6[0];
      // alert( jsonItem.key6_1_2 );
      //json 转换成字符串
      // alert(JSON.stringify(jsonObj.key1));
      //把json字符串转换为json对象
      // var jsonObj2 = JSON.parse(JSON.stringify(jsonObj));
      // alert(jsonObj2.key1);
    </script>
  </head>
  <body>
  $END$

  </body>
</html>

JSON在java中的使用

JsonTest.java

package cn.cqie.json;

import cn.cqie.pojo.Person;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JsonTest {

    @Test
    public void test1(){
        Person yx = new Person(20, "yx");
        System.out.println(yx);
        Gson gson = new Gson();
        //将java对象转换成json 字符串
        String s = gson.toJson(yx);
        System.out.println(s);
        //将 json 字符串转换为 java对象
        Person person = gson.fromJson(s, Person.class);
        System.out.println(person);
    }
    @Test
    public void test02(){
        List<Person> personList = new ArrayList<>();
        personList.add(new Person(26,"yx"));
        personList.add(new Person(20,"yq"));
        //java对象转换成 json 字符串
        Gson gson = new Gson();
        String s = gson.toJson(personList);
        System.out.println(s);
        //将 json字符串转换为 java对象
        List<Person> list = gson.fromJson(s, new TypeToken<List<Person>>() {
        }.getType());
        System.out.println(list);

    }
@Test
    public void Test03(){
        Map<Integer,Person> map = new HashMap<>();
        map.put(1,new Person(26,"yx"));
        map.put(2,new Person(20,"yq"));
        //java对象转换成 json 字符串
        Gson gson = new Gson();
        String toJson = gson.toJson(map);
        System.out.println(toJson);

         Map<Integer,Person> personMap2= gson.fromJson(toJson, new TypeToken<Map<Integer, Person>>() {
    }.getType());
    System.out.println(personMap2.get(1));

}
}

AJAX请求

AJAX 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发

技术。

ajax 是一种浏览器通过 js 异步发起请求,局部更新页面的技术。

Ajax 请求的局部更新,浏览器地址栏不会发生变化

局部更新不会舍弃原来页面的内容

posted @ 2021-10-01 12:13  后端小知识  阅读(59)  评论(0编辑  收藏  举报
返回顶端