JavaWeb学习笔记(9)-B站尚硅谷

二十二、书城项目第八阶段

001-使用 Filter 过滤器拦截/pages/manager/所有内容,实现权限检查

通过Filter拦截/pages/manager/下的所有内容,只有用户登录之后,才能访问。
即 点击后台管理 只有用户登录之后才能进入后台。

在src/com.atguigu/下创建一个package--->filter
在filter下创建ManagerFilter进行拦截
package com.atguigu.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

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

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        //对pages/manager/下的所有内容进行拦截,只有登录之后才能访问
        //即登录之后,才能进入后台管理

        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        Object user = httpServletRequest.getSession().getAttribute("user");

        if (user == null) {
    
    
            //如果user为空,即用户未登录,跳转到登录页面
            httpServletRequest.getRequestDispatcher("/pages/user/login.jsp").forward(servletRequest,servletResponse);
        } else {
    
    
            //用户登录了,则不拦截
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {
    
    

    }
}

在这里插入图片描述

002-ThreadLocal的使用

这个大致看看理解一下就好了,看003
在这里插入图片描述

ThreadLocal中保存的数据,在线程销毁后,会由JVM虚拟机自动释放。
public class OrderService {
    
    
	public void createOrder(){
    
    
		String name = Thread.currentThread().getName();
		System.out.println("OrderService 当前线程[" + name + "]中保存的数据是:" + ThreadLocalTest.threadLocal.get());
		new OrderDao().saveOrder();
	}
}

public class OrderDao {
    
    
	public void saveOrder(){
    
    
		String name = Thread.currentThread().getName();
		System.out.println("OrderDao 当前线程[" + name + "]中保存的数据是:" + ThreadLocalTest.threadLocal.get());
	}
}

public class ThreadLocalTest {
    
    
	// public static Map<String,Object> data = new Hashtable<String,Object>();
	public static ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
	private static Random random = new Random();
	
	public static class Task implements Runnable {
    
    
	
		@Override
		public void run() {
    
    
			// 在 Run 方法中,随机生成一个变量(线程要关联的数据),然后以当前线程名为 key 保存到 map 中
			Integer i = random.nextInt(1000);
			// 获取当前线程名
			String name = Thread.currentThread().getName();
			System.out.println("线程["+name+"]生成的随机数是:" + i);
			// data.put(name,i);
			threadLocal.set(i);
		
			try {
    
    
				Thread.sleep(3000);
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			}
			
			new OrderService().createOrder();
			// 在 Run 方法结束之前,以当前线程名获取出数据并打印。查看是否可以取出操作
			// Object o = data.get(name);
			Object o = threadLocal.get();
			System.out.println("在线程["+name+"]快结束时取出关联的数据是:" + o);
		}
	}

	public static void main(String[] args) {
    
    
		for (int i = 0; i < 3; i++){
    
    
			new Thread(new Task()).start();
		}
	}
}

003-使用 Filter 和 ThreadLocal 组合管理事务

(1)使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完成

希望 订单的生成,订单项的生成,和图书的销量和库存的变化,要么同时成功,要么同时失败。
因为有时会出现订单生成但订单项未生成等情况。
这就涉及到数据库的事务问题。

在这里插入图片描述
OrderServlet,OrderServiceImpl,OrderDaoImpl,BaseDao,BookDaoImpl,OrderItemDaoImpl都在同一个线程中执行。
在这里插入图片描述

所有获取的连接对象Connection,都可以使用ThreadLocal创建的同一个对象。这样就实现了在同一个线程内执行。

JdbcUtils 工具类的修改:
	添加了Thread
	getConnection()方法修改了
	原来的close()方法删除了
	新增了commitAndClose()方法和rollbackAndClose()方法
	最后Connection连接关闭了,但是ResultSet和PreparedStatement资源没关。不知道为什么
package com.atguigu.utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtils {
    
    
    //获取数据库连接池中的连接
    private static DruidDataSource dataSource;

    private static ThreadLocal<Connection> conns = new ThreadLocal<Connection>();

    static {
    
    
        try {
    
    
            Properties properties = new Properties();
            //从流中加载数据
            //这里路径要写成绝对路径
            properties.load(new FileInputStream("E:\\IDEA\\Projects\\JavaWeb-BzhanTeach\\09-书城项目第二阶段\\src\\druid.properties"));

            //创建数据库连接池
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);

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

    //返回null 获取连接失败
    public static Connection getConnection(){
    
    
        Connection conn = conns.get();

        if (conn == null){
    
    
            try {
    
    
                conn = dataSource.getConnection();//从数据库连接池中获取连接

                conns.set(conn);//保存到ThreadLocal对象中,供后面的jdbc操作使用

                conn.setAutoCommit(false);//设置为手动管理事务

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

        return conn;
    }

    /*    //释放连接,释放资源
    public static void close(Connection conn, PreparedStatement ps, ResultSet rs){
        DbUtils.closeQuietly(rs);
        DbUtils.closeQuietly(ps);
        DbUtils.closeQuietly(conn);
    }*/

    //提交事务,并关闭释放连接
    public static void commitAndClose(){
    
    
        Connection conn = conns.get();

        if (conn != null){
    
    //不等于null 说明之前使用过连接,操作过数据库
            try {
    
    
                conn.commit();//提交事务
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }finally{
    
    
                try {
    
    
                    conn.close();//关闭连接,释放资源
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }

        //一定要执行remove操作,否则会出错。(因为Tomcat底层使用了线程池)
        //web中的线程是重复使用,remove是为保证下次线程得不到上一次线程在ThreadLocal中set的值
        conns.remove();
    }

    //回滚事务,并关闭释放连接
    public static void rollbackAndClose(){
    
    
        Connection conn = conns.get();

        if (conn != null){
    
    //不等于null 说明之前使用过连接,操作过数据库
            try {
    
    
                conn.rollback();//回滚事务
            } catch (SQLException e) {
    
    
                e.printStackTrace();
            }finally{
    
    
                try {
    
    
                    conn.close();//关闭连接,释放资源
                } catch (SQLException e) {
    
    
                    e.printStackTrace();
                }
            }
        }

        conns.remove();
    }
}

testJdbcUtils不需要了,可删去。
修改BaseDao:
	所有的finally和关闭连接都删去,不需要写了(因为如果在这里关闭连接了,后面的相关程序就获取不到连接了)
	把所有的捕捉异常都改为上抛异常(因为如果在这里就把异常捕捉了,后面就捕捉不到异常了)或者在catch里面使用 throw new RuntimeExceptioon(e); 同时删去最后的return
package com.atguigu.dao;

import com.atguigu.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

public abstract class BaseDao {
    
    

    //使用DBUtils操作数据库
    private QueryRunner queryRunner = new QueryRunner();

    /**
     * 该方法用来执行:insert/update/delete sql语句
     * @return 如果返回-1,说明执行失败;返回其他,表示影响了几条数据。
     */
    public int update(String sql, Object... args){
    
    
        Connection conn = JdbcUtils.getConnection();

        try {
    
    
            return queryRunner.update(conn,sql,args);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
            throw new RuntimeException(e); //上抛异常
        }
    }

    /**
     * 查询sql语句,返回一条查询结果
     * @param type 返回的对象类型
     * @param sql  执行的sql语句
     * @param args sql语句对应的参数值(填充占位符)
     * @param <T>  返回的数据类型的泛型
     * @return
     */
    public <T> T queryForOne(Class<T> type, String sql, Object... args){
    
    
        Connection conn = JdbcUtils.getConnection();

        try {
    
    
            return queryRunner.query(conn, sql, new BeanHandler<T>(type), args);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
            throw new RuntimeException(e); //上抛异常
        }
    }

    /**
     * 查询sql语句,返回多条查询结果
     * @param type 返回的对象类型
     * @param sql  执行的sql语句
     * @param args sql语句对应的参数值(填充占位符)
     * @param <T>  返回的数据类型的泛型
     * @return
     */
    public <T> List<T> queryForList(Class<T> type, String sql, Object... args){
    
    
        Connection conn = JdbcUtils.getConnection();

        try {
    
    
            return queryRunner.query(conn, sql, new BeanListHandler<T>(type), args);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
            throw new RuntimeException(e); //上抛异常
        }
    }

    //针对返回一列一行的sql语句(针对 select count(*) from 表名)(针对 count(*) 这样的函数)
    public Object queryForSingleValue(String sql, Object... args){
    
    
        Connection conn = JdbcUtils.getConnection();

        try {
    
    
            return queryRunner.query(conn, sql, new ScalarHandler(), args);
        } catch (SQLException e) {
    
    
            e.printStackTrace();
            throw new RuntimeException(e); //上抛异常
        }
    }
}

捕获OrderServlet程序中的OrderService.createOrder()方法中的异常:
这个看看就好,先别写,往下看。

在这里插入图片描述

(2)使用 Filter 过滤器统一给所有的 Service 方法都加上 try-catch,来进行事务的管理

有很多Service方法,不可能一个一个加try...catch
通过给 filterChain.doFilter()添加try...catch就相当于给所有的Service方法都添加了try...catch
因为filterChain.doFilter()方法的作用之一会调用Servlet程序(也就是会使用其中的Service方法)

在这里插入图片描述

在filter package下创建 TransactionFilter:
package com.atguigu.filter;

import com.atguigu.utils.JdbcUtils;

import javax.servlet.*;
import java.io.IOException;

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

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    

        try {
    
    
            filterChain.doFilter(servletRequest, servletResponse);
            JdbcUtils.commitAndClose(); // 提交事务 关闭连接
        }catch (Exception e){
    
    
            JdbcUtils.rollbackAndClose(); // 回滚事务 关闭连接
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {
    
    

    }
}

在这里插入图片描述


在这里插入图片描述
dao层,service层和web层的servlet出现异常都要抛出,在doFilter()方法中捕获异常一起解决

(3)将所有异常都统一交给 Tomcat,让 Tomcat 展示友好的错误信息

如果发生异常,在页面展示出友好的错误信息

在 web.xml 中我们可以通过错误页面配置来进行管理。

在这里插入图片描述

新建目录pages/error
在error目录下新建 error404.jsp error500.jsp
为发生异常时显示的页面

在这里插入图片描述
在这里插入图片描述

注意:TransactionFilter的doFilter方法中要把异常抛给Tomcat,否则无法显示异常信息,因为doFilter方法中已经把异常抓到了。
在这里插入图片描述

二十三、JSON

001-什么是JSON

在这里插入图片描述

002-JSON在JavaScript中的使用

(1)JSON的定义

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

json 定义示例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        //json的定义
        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"
            }]
        };
    </script>
</head>
<body>

</body>
</html>

(2)JSON的访问

json 本身是一个对象。
json 中的 key 我们可以理解为是对象中的一个属性。
json 中的 key 访问就跟访问对象的属性一样: json 对象.key

json 访问示例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        //json的定义
        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"
            }]
        };

        //json的访问
        alert(typeof(jsonObj));// object (json 就是一个对象)

        alert(jsonObj.key1); //12
        alert(jsonObj.key2); // abc
        alert(jsonObj.key3); // true

        alert(jsonObj.key4);// 得到数组[11,"arr",false]
        // json 中 数组值的遍历
        for(var i = 0; i < jsonObj.key4.length; i++) {
      
      
            alert(jsonObj.key4[i]);
        }

        alert(jsonObj.key5.key5_1);//551
        alert(jsonObj.key5.key5_2);//key5_2_value

        alert( jsonObj.key6 );// 得到 json 数组
        // 取出来每一个元素都是 json 对象
        var jsonItem = jsonObj.key6[0];
        alert( jsonItem.key6_1_1 ); //6611
        alert( jsonItem.key6_1_2 ); //key6_1_2_value
    </script>
</head>
<body>

</body>
</html>

(3)JSON的两个常用方法

json 的存在有两种形式:
	一种是:对象的形式存在,我们叫它 json 对象。
	一种是:字符串的形式存在,我们叫它 json 字符串。
	
	JSON.stringify() 	把 json 对象转换成为 json 字符串
	JSON.parse() 		把 json 字符串转换成为 json 对象
		
一般我们要操作 json 中的数据的时候,需要 json 对象的格式。
一般我们要在客户端和服务器之间进行数据交换的时候,使用 json 字符串。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        //json的定义
        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"
            }]
        };


        // 把 json 对象转换成为 json 字符串
        var jsonObjString = JSON.stringify(jsonObj); // 特别像 Java 中对象的 toString
        alert(jsonObjString)

        // 把 json 字符串 转换成为 json 对象
        var jsonObj2 = JSON.parse(jsonObjString);
        alert(jsonObj2.key1);// 12
        alert(jsonObj2.key2);// abc

    </script>
</head>
<body>

</body>
</html>

003-JSON在Java中的使用

JSON在服务器的使用(客户端与服务器端数据的交换格式)

首先要添加jar包gson-2.2.4.jar
在WEB-INF下创建lib目录,将jar包添加进去,记得add as library

Person类:
package com.atguigu.bean;

public class Person {
    
    

    private Integer id;
    private String name;

    public Person() {
    
    
    }

    public Person(Integer id, String name) {
    
    
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
    
    
        return id;
    }

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

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public String toString() {
    
    
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

(1)javaBean 和 json 的互转

package com.atguigu.json;

import com.atguigu.bean.Person;
import com.google.gson.Gson;
import org.junit.jupiter.api.Test;

public class JsonTest {
    
    
    @Test
    public void test1(){
    
    
        Person person = new Person(1,"国哥好帅!");

        // 创建 Gson 对象实例
        Gson gson = new Gson();

        // toJson 方法可以把 java 对象转换成为 json 字符串
        String personJsonString = gson.toJson(person);
        System.out.println(personJsonString);

        // fromJson 把 json 字符串转换回 Java 对象
        // 第一个参数是 json 字符串
        // 第二个参数是转换回去的 Java 对象类型
        Person person1 = gson.fromJson(personJsonString, Person.class);
        System.out.println(person1);
    }
}

(2)List 和 json 的互转

fromJson(String Json, Class<T> classOfT) ---> json与javabean互转时使用这个
fromJson(String Json, Type typeOf) ---> json 与 集合 互转时使用这个
package com.atguigu.json;

import com.atguigu.bean.Person;
import com.google.gson.reflect.TypeToken;

import java.util.List;

// List 或 ArrayList 都可以
public class PersonListType extends TypeToken<List<Person>>{
    
    
    //这个类什么都不用写
    //只用写这个类继承 TypeToken,然后把 json要转换为的类型的泛型放进去即可
}

package com.atguigu.json;

import com.atguigu.bean.Person;
import com.google.gson.Gson;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

public class JsonTest {
    
    
    @Test
    // List 与 json 互转
    public void test2() {
    
    
        List<Person> personList = new ArrayList<>();

        personList.add(new Person(1, "国哥"));
        personList.add(new Person(2, "康师傅"));

        Gson gson = new Gson();

        // 把 List 转换为 json 字符串
        String personListJsonString = gson.toJson(personList);
        System.out.println(personListJsonString);

        // 把 json 字符串 转换为 List
        // gson.fromJson(personListJsonString, personList.getClass()写这个不行)
        List<Person> list = gson.fromJson(personListJsonString, new PersonListType().getType());

        System.out.println(list);

        Person person = list.get(0);
        System.out.println(person);
    }
}

(3)map 和 json 的互转

package com.atguigu.json;

import com.atguigu.bean.Person;
import com.google.gson.reflect.TypeToken;

import java.util.Map;

// Map 或 HashMap 都可以
public class PersonMapType extends TypeToken<Map<Integer, Person>> {
    
    
}
package com.atguigu.json;

import com.atguigu.bean.Person;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.junit.jupiter.api.Test;

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

public class JsonTest {
    
    
    @Test
    // map 与 json 互转
    public void test3(){
    
    
        Map<Integer,Person> personMap = new HashMap<>();
        personMap.put(1, new Person(1, "国哥好帅"));
        personMap.put(2, new Person(2, "康师傅也好帅"));

        Gson gson = new Gson();

        // 把 map 集合转换成为 json 字符串
        String personMapJsonString = gson.toJson(personMap);
        System.out.println(personMapJsonString);

        // 把 json 转换为 map
        Map<Integer,Person> personMap2 = gson.fromJson(personMapJsonString, new PersonMapType().getType());

        System.out.println(personMap2);

        Person p = personMap2.get(1);
        System.out.println(p);
    }
}
如果json与集合互转,会产生很多空的类,比如:PersonListType和PersonMapType
可以使用匿名内部类的方法,这样就不用写空类了。
即使用 Map<Integer,Person> personMap2 = gson.fromJson(personMapJsonString, new TypeToken<Map<Integer,Person>>(){}.getType());
替换 Map<Integer,Person> personMap2 = gson.fromJson(personMapJsonString, new PersonMapType().getType()); 和删除对应的空类

二十四、AJAX请求

001-什么是AJAX请求?

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

ajax 是一种浏览器通过 js 异步发起请求,局部更新页面的技术。
	Ajax 请求的局部更新,浏览器地址栏不会发生变化
	局部更新不会舍弃原来页面的内容

	同步:下一个程序的执行 要等到上一个程序执行结束之后 才能执行
	异步:类似于多线程并发,下一个程序的执行 不需要等待 上一个程序的执行完成,会直接执行

002-原生AJAX请求示例

在这里插入图片描述

ajax.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript">
        // 在这里使用 javaScript 语言发起 Ajax 请求,访问服务器 AjaxServlet 中 javaScriptAjax方法
        function ajaxRquest(){
    
    
            //使用ajax向服务器发起请求步骤:
            // 1.首先创建 XMLHttpRquest
            var xmlHttpRequest = new XMLHttpRequest();

            // 2.调用open方法设置请求参数
            // 第三个参数:是否异步
            // 异步就是程序执行到这个ajax请求时,不需要等待该请求的响应可以立即执行往下程序,同步则必须等待响应的返回才能往下执行
            xmlHttpRequest.open("Get","http://localhost:8080/018_json_ajax_i18n/ajaxServlet?action=javaScriptAjax",true);

            //向服务器发送请求之后,服务器向浏览器响应(回传数据),浏览器如接收?
            // 4.在send方法前绑定 onreadystatechange事件,处理请求完成后的操作(最好写在send之前,否则可能会出现一些问题)
            xmlHttpRequest.onreadystatechange = function(){
    
    
                //readyState 保存XMLHttpRequest的状态信息;==4表示 请求已完成 且响应已就绪
                //status == 200 表示 ok
                // 满足这两个条件才代表响应已就绪,可以进行后续操作(处理响应来的数据)
                if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200) {
    
    
                    // 使用xmlHttpRequest的属性responseText获得响应
                    // var jsonObj = JSON.parse(xmlHttpRequest.responseText);

                    // 响应来的是一个字符串,想要获取响应的具体信息,使用JSON转换
                    var jsonObj = JSON.parse(xmlHttpRequest.responseText);

                    // 把响应的数据显示在页面上
                    document.getElementById("div01").innerHTML = "编号:" + jsonObj.id + " , 姓名:" + jsonObj.name;
                }
            }

            // 3.调用send方法发送请求
            xmlHttpRequest.send();
        }
    </script>
</head>
<body>
    <button onclick="ajaxRquest()">ajax Request</button>
    <div id="div01"></div>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

003-jQuery中的Ajax请求

一般不会使用原生的ajax,而是使用jQuery框架来使用ajax
在这里插入图片描述

$.ajax 方法:五个参数
	url 表示请求的地址
	type 表示请求的类型 GET 或 POST 请求
	data 表示发送给服务器的数据
		格式有两种:
		一:name=value&name=value
		二:{key:value}
		
	success 请求成功,响应的回调函数
	
	dataType 响应的数据类型
		常用的数据类型有:
			text 表示纯文本
			xml 表示 xml 数据
			json 表示 json 对象
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="script/jquery-3.6.0.js"></script>
    <script type="text/javascript">
        $(function(){
      
      
            // ajax请求
            $("#ajaxBtn").click(function(){
      
      

                $.ajax({
      
      
                    url:"http://localhost:8080/018_json_ajax_i18n/ajaxServlet",
                    // data:"action=jQueryAjax",
                    data:{
      
      action:"jQueryAjax"},
                    type:"GET",
                    success:function (data) {
      
      //data是服务器返回的数据(响应的数据)
                        // 如果dataType为json,就不用将data转换为json了,可以直接显示具体信息,不需要像原来那样使用JSON.parse()了
                        $("#msg").html("编号:" + data.id + " , 姓名:" + data.name);
                    },
                    dataType : "json"
                });

            });

			// ajax--get请求
            $("#getBtn").click(function(){
      
      
            
            });

            // ajax--post请求
            $("#postBtn").click(function(){
      
      
            
            });

            // ajax--getJson请求
            $("#getJSONBtn").click(function(){
      
      
                // 调用
                alert("getJSON btn");

            });

            // ajax请求
            $("#submit").click(function(){
      
      
                // 把参数序列化
                alert("serialize()");
            });
        });
    </script>
</head>
<body>
    <div>
        <button id="ajaxBtn">$.ajax请求</button>
        <button id="getBtn">$.get请求</button>
        <button id="postBtn">$.post请求</button>
        <button id="getJSONBtn">$.getJSON请求</button>
    </div>
    <br>
    <br>
    <form id="form01" >
        用户名:<input name="username" type="text" /><br/>
        密码:<input name="password" type="password" /><br/>
        下拉单选:
        <select name="single">
            <option value="Single">Single</option>
            <option value="Single2">Single2</option>
        </select>
        <br>
        下拉多选:
        <select name="multiple" multiple="multiple">
            <option selected="selected" value="Multiple">Multiple</option>
            <option value="Multiple2">Multiple2</option>
            <option selected="selected" value="Multiple3">Multiple3</option>
        </select>
        <br>
        复选:
        <input type="checkbox" name="check" value="check1"/> check1
        <input type="checkbox" name="check" value="check2" checked="checked"/> check2<br/>
        单选:
        <input type="radio" name="radio" value="radio1" checked="checked"/> radio1
        <input type="radio" name="radio" value="radio2"/> radio2<br/>
    </form>
    <button id="submit">提交--serialize()</button>
</body>

在这里插入图片描述


$.get 方法和$.post 方法(是对$.ajax的进一步封装):4个参数
	url 请求的 url 地址
	data 发送的数据
	callback 成功的回调函数
	type 返回的数据类型

在这里插入图片描述
在这里插入图片描述


$.getJSON 方法(通过get请求 返回json类型的数据):
	url 请求的 url 地址
	data 发送给服务器的数据
	callback 成功的回调函数

在这里插入图片描述
在这里插入图片描述


表单序列化 serialize()
serialize()可以把表单中所有表单项的内容都获取到,
	并以 name=value&name=value 

在这里插入图片描述
在这里插入图片描述
Ajax 可以在页面中局部更新,不再需要跳转页面

二十五、书城项目第九阶段

001-使用 AJAX 验证用户名是否可用

在这里插入图片描述

首先将gson jar包添加到书城项目下

在这里插入图片描述
在这里插入图片描述

原来写的验证用户名是否可用 不用删除,因为那是点击注册之后验证的。
而这里的ajax是在点击验证之前,输入用户名 焦点消失之后就立刻验证。

002-使用 AJAX修改 把商品添加到购物车

在这里插入图片描述

修改CartServlet:

原来的加入购物车功能实现:

在这里插入图片描述

使用ajax实现加入购物车功能:

在这里插入图片描述

二者的区别只是在最后不同,其他的都一样:原来的是重定向到指定页面,而现在不需要跳转页面。


修改pages/client/index.jsp:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二十六、i18n国际化(了解内容)

001-什么是 i18n 国际化

在这里插入图片描述

002-国际化相关要素介绍

在这里插入图片描述

003-国际化资源 properties 测试

在这里插入图片描述


在这里插入图片描述
在这里插入图片描述

004-通过请求头国际化页面

对页面,表单进行国际化

第一种:在浏览器的设置中 设置页面的语言
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.ResourceBundle" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    // 从请求头中获取 Locale 信息(语言)
    Locale locale = request.getLocale();
    System.out.println(locale);
    
    // 获取读取包(根据 指定的 baseName 和 Locale 读取 语言信息)
    ResourceBundle i18n = ResourceBundle.getBundle("i18n", locale);
%>
<a href="">中文</a>|
<a href="">english</a>
<center>
    <h1><%=i18n.getString("regist")%></h1>
    <table>
        <form>
            <tr>
                <td><%=i18n.getString("username")%></td>
                <td><input name="username" type="text" /></td>
            </tr>
            <tr>
                <td><%=i18n.getString("password")%></td>
                <td><input type="password" /></td>
            </tr>
            <tr>
                <td><%=i18n.getString("sex")%></td>
                <td>
                    <input type="radio" /><%=i18n.getString("boy")%>
                    <input type="radio" /><%=i18n.getString("girl")%>
                </td>
            </tr>
            <tr>
                <td><%=i18n.getString("email")%></td>
                <td><input type="text" /></td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="reset" value="<%=i18n.getString("reset")%>" />&nbsp;&nbsp;
                    <input type="submit" value="<%=i18n.getString("submit")%>" /></td>
            </tr>
        </form>
    </table>
    <br /> <br /> <br /> <br />
</center>
国际化测试:
<br /> 1、访问页面,通过浏览器设置,请求头信息确定国际化语言。
<br /> 2、通过左上角,手动切换语言
</body>
</html>


第二种:点击左上方的语言进行语言切换

在这里插入图片描述

<%@ page import="java.util.Locale" %>
<%@ page import="java.util.ResourceBundle" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
	// 从请求头中获取 Locale 信息(语言)
	Locale locale = null;
	String country = request.getParameter("country");
	
	if ("cn".equals(country)) {
		locale = Locale.CHINA;
	} else if ("usa".equals(country)) {
		locale = Locale.US;
	} else {
		locale = request.getLocale();
	}
	System.out.println(locale);
	
	// 获取读取包(根据 指定的 baseName 和 Locale 读取 语言信息)
	ResourceBundle i18n = ResourceBundle.getBundle("i18n", locale);
%>
<a href="i18n.jsp?country=cn">中文</a>|
<a href="i18n.jsp?country=usa">english</a>
<center>
	<h1><%=i18n.getString("regist")%></h1>
	<table>
		<form>
			<tr>
				<td><%=i18n.getString("username")%></td>
				<td><input name="username" type="text" /></td>
			</tr>
			<tr>
				<td><%=i18n.getString("password")%></td>
				<td><input type="password" /></td>
			</tr>
			<tr>
				<td><%=i18n.getString("sex")%></td>
				<td>
				<input type="radio" /><%=i18n.getString("boy")%>
				<input type="radio" /><%=i18n.getString("girl")%>
				</td>
			</tr>
			<tr>
				<td><%=i18n.getString("email")%></td>
				<td><input type="text" /></td>
			</tr>
			<tr>
				<td colspan="2" align="center">
				<input type="reset" value="<%=i18n.getString("reset")%>" />&nbsp;&nbsp;
				<input type="submit" value="<%=i18n.getString("submit")%>" />
				</td>
			</tr>
		</form>
	</table>
	<br /> <br /> <br /> <br />
</center>
国际化测试:
<br /> 1、访问页面,通过浏览器设置,请求头信息确定国际化语言。
<br /> 2、通过左上角,手动切换语言
</body>
</html>

005-JSTL 标签库实现国际化

在这里插入图片描述

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
	<title>Insert title here</title>
</head>
<body>
	<%--1 使用标签设置 Locale 信息--%>
	<fmt:setLocale value="${param.locale}" />
	<%--2 使用标签设置 baseName--%>
	<fmt:setBundle basename="i18n"/>
	
	<a href="i18n_fmt.jsp?locale=zh_CN">中文</a>|
	<a href="i18n_fmt.jsp?locale=en_US">english</a>
	
	<center>
		<h1><fmt:message key="regist" /></h1>
		<table>
			<form>
				<tr>
					<td><fmt:message key="username" /></td>
					<td><input name="username" type="text" /></td>
				</tr>
				<tr>
					<td><fmt:message key="password" /></td>
					<td><input type="password" /></td>
				</tr>
				<tr>
					<td><fmt:message key="sex" /></td>
					<td>
					<input type="radio" /><fmt:message key="boy" />
					<input type="radio" /><fmt:message key="girl" />
					</td>
				</tr>
				<tr>
					<td><fmt:message key="email" /></td>
					<td><input type="text" /></td>
				</tr>
				<tr>
					<td colspan="2" align="center">
					<input type="reset" value="<fmt:message key="reset" />" />&nbsp;&nbsp;
					<input type="submit" value="<fmt:message key="submit" />" />
					</td>
				</tr>
			</form>
		</table>
		<br /> <br /> <br /> <br />
	</center>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/m0_52041525/article/details/124647599