通过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 data = new Hashtable();
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 返回的数据类型的泛型
* @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 返回的数据类型的泛型
* @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()方法中捕获异常一起解决
如果发生异常,在页面展示出友好的错误信息
在 web.xml 中我们可以通过错误页面配置来进行管理。
新建目录pages/error
在error目录下新建 error404.jsp error500.jsp
为发生异常时显示的页面
注意:TransactionFilter的doFilter方法中要把异常抛给Tomcat,否则无法显示异常信息,因为doFilter方法中已经把异常抓到了。
json 是由键值对组成,并且由花括号(大括号)包围。
每个键由引号引起来,键和值之间使用冒号进行分隔,多组键值对之间进行逗号进行分隔。
json 定义示例:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<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>Titletitle>
<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>Titletitle>
<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 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 personMap2 = gson.fromJson(personMapJsonString, new TypeToken
二十四、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>
一般不会使用原生的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>Titletitle>
<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">Singleoption>
<option value="Single2">Single2option>
select>
<br>
下拉多选:
<select name="multiple" multiple="multiple">
<option selected="selected" value="Multiple">Multipleoption>
<option value="Multiple2">Multiple2option>
<option selected="selected" value="Multiple3">Multiple3option>
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 可以在页面中局部更新,不再需要跳转页面
首先将gson jar包添加到书城项目下
原来写的验证用户名是否可用 不用删除,因为那是点击注册之后验证的。
而这里的ajax是在点击验证之前,输入用户名 焦点消失之后就立刻验证。
002-使用 AJAX修改 把商品添加到购物车
修改CartServlet:
原来的加入购物车功能实现:
使用ajax实现加入购物车功能:
二者的区别只是在最后不同,其他的都一样:原来的是重定向到指定页面,而现在不需要跳转页面。
修改pages/client/index.jsp:
对页面,表单进行国际化
第一种:在浏览器的设置中 设置页面的语言
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.ResourceBundle" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Titletitle>
head>
<body>
<%
// 从请求头中获取 Locale 信息(语言)
Locale locale = request.getLocale();
System.out.println(locale);
// 获取读取包(根据 指定的 baseName 和 Locale 读取 语言信息)
ResourceBundle i18n = ResourceBundle.getBundle("i18n", locale);
%>
<a href="">中文a>|
<a href="">englisha>
<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")%>" />
<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>Titletitle>
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">englisha>
<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")%>" />
<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 heretitle>
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">englisha>
<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="" reset" />" />
<input type="submit" value="" submit" />" />
td>
tr>
form>
table>
<br /> <br /> <br /> <br />
center>
body>
html>
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)