JavaWeb_day6_事务&ajax&Listener&filter

Js和jQuery分别实现分类商品和是否热门

 

同步和异步

同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发第二个请求

异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求

 

JS原生的Ajax技术

  1. 创建Ajax引擎对象
  2. 为Ajax引擎对象绑定监听
  3. 绑定提交地址
  4. 发送请求
  5. 接受响应数据

<script>

    function fn1(){

              //1、创建ajax引擎对象

              var xmlHttp = new XMLHttpRequest();

              //2、绑定监听

              xmlHttp.onreadystatechange = function(){

                     if(xmlHttp.readyState==4&&xmlHttp.status==200){

                            //5、接受相应数据

                            var res = xmlHttp.responseText;

                            document.getElementById("span1").innerHTML = res;

                     }

              }

              //3、绑定地址

              xmlHttp.open("GET","${pageContext.request.contextPath }/ajaxServlet",true);

              //4、发送请求

              xmlHttp.send();

       }

</script>

post访问要在send前复制这句

xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");

 

get方式:请求参数在url后边拼写,send方法为空参              xmlHttp.open("GET","${pageContext.request.contextPath }/ajaxServlet?username=tom",true);

post方式:请求参数在send方法中定义                                xmlHttp.send("username=tom");

true表示异步,false表示同步

 

 

Json是一种与语言无关的数据交换格式

作用:使用Ajax进行前后台数据交换,移动端与服务端的数据交换

Json的两种格式:

  1. 对象格式:{"key1":obj,"key2":obj,"key3":obj...};
  2. 数组/集合格式:[{},{}..];

Json的key是字符串,value是object
获取数据:

json对象.键名

json对象["键名"]

数组对象[索引]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="./js/jquery-3.3.1.min.js"></script>
</head>
<body>

</body>
<script>
	//定义基本格式
	var person1={"name":"郭叶兵","age":27,"address":"上海"};
	//获取name的值
 	alert(person1.name);
	alert(person1["name"]); 
	//嵌套格式  {}---->[]
	 var person2={"person":[
	{"name":"张三","age":27,"address":"上海"},
	{"name":"李四","age":28,"address":"天津"},
	{"name":"王五","age":29,"address":"北京"}
	                      ]
	              }; 
	//获取name是王五
	//alert(person2.person[2].name);
	//嵌套格式  []---->{}     
	var person3=[
		{"name":"张三","age":27,"address":"上海"},
		{"name":"李四","age":28,"address":"天津"},
		{"name":"王五","age":29,"address":"北京"}
	             ];
	//获取name是王五
	alert(person3[2].name);
</script>
</html>

获取person对象中所有的键和值

<script>
	//定义基本格式
	var person1={"name":"郭叶兵","age":27,"address":"上海"};
	
	
	var person3=[
		{"name":"张三","age":27,"address":"上海"},
		{"name":"李四","age":28,"address":"天津"},
		{"name":"王五","age":29,"address":"北京"}
	             ];
	//获取person对象中所有的键和值
	//for in 循环
	for(var key in person1){
		//这种方式获取不行,因为相当于  person1."name"
		//alert(key+":"+person1.key); 
		alert(key+":"+person1[key]);
	}
	
	//获取person对象中所有的键和值
	for(var i=0;i<person3.length;i++){
		var p=person3[i];
		for(var key in p){
			alert(key+":"+p[key]);
		}
	}
	
</script>

 

 

 

 

Jquery的Ajax技术

ajax的get和post的区别:

post不会乱码,get需要编解码,但是post编解码反而出错

$.get(url, [data], [callback], [type])

$.post(url, [data], [callback], [type])

$.ajax( { option1:value1,option2:value2... } );

常用的option有如下:

async:是否异步,默认是true代表异步

data:发送到服务器的参数,建议使用json格式

dataType:服务器端返回的数据类型,常用text和json

success:成功响应执行的函数,对应的类型是function类型

type:请求方式,POST/GET

url:请求服务器端地址

//使用json的转换工具将对象或集合转成json格式的字符串

  1. Jsonlib   sun公司自己的
  2. Gson  google
  3. Fastjson 阿里巴巴
  4. jackson

Jsonlib:JSONArray(集合)    JSONObject(单一对象)

Gson:对象和集合都是同一个方法

jackson的使用(jackson核心对象ObjectMapper)

 

1.JSON转为Java对象

readValue(json字符串数据,Class)

2.Java对象转为JSON

writeValue(参数1,obj):

writeValueAsString(obj)

注解:

@JsonIgnore:排除属性

@JsonFormat:属性值的格式化

复杂的java对象转换

list:数组

map:对象格式一致

public class Demo {
	//Java对象转为JSON字符串
	@Test
	public void show1() throws Exception{
		Person p=new Person();
		p.setName("张三");
		p.setAge(20);
		p.setGender("男");
	ObjectMapper mapper=new ObjectMapper();	
	  /*
            转换方法:
            writeValue(参数1,obj):
                参数1:
            File:将obj对象转换为JSON字符串,并保存到指定的文件中
            Writer:将obj对象转换为JSON字符串,并将json数据填充到字符输出流中
            OutputStream:将obj对象转换为JSON字符串,并将json数据填充到字节输出流中
            writeValueAsString(obj):将对象转为json字符串
         */
	String json=mapper.writeValueAsString(p);
	System.out.println(json);
	//{"name":"张三","age":20,"gender":"男"}
	
	//writeValue,将数据写到d://a.txt文件中
    //mapper.writeValue(new File("d://a.txt"),p);

    //writeValue.将数据关联到Writer中
    //mapper.writeValue(new FileWriter("d://b.txt"),p);
	
	}

}

 

 

 

监听器Listener

8大监听器(6+2)

3大域的监听器       ServletRequest  HttpSession  ServletContex

与session有关的监听器(对象感知监听器)

session中的对象有4种状态

绑定状态:将对象被放到session域中

解绑状态:将对象从session域中移除了

钝化状态:是将session内存中的对象持久化(序列化)到磁盘

活化状态:就是将磁盘上的对象再次恢复到session内存中

绑定与解绑的监听器HttpSessionBindingListener,不需要再web.xml里面配置

钝化与活化的监听器HttpSessionActivationListener   要记得实现serializable

 

2)监听器的编写步骤(重点):

  1. 编写一个监听器类去实现监听器接口
  2. 覆盖监听器的方法
  3. 需要在web.xml中进行配置---注册

 

<!-- 注册监听器 -->

  <listener>

    <listener-class></listener-class>

  </listener>

 

ServletContexListener监听器的作用:

初始化资源:加载数据库和spring的配置文件

任务调度:定时器  Timer/TimerTask

 

前六个监听器需要配置,但是对象感知监听器不需要配置

 

下面这个看看就行了,通过配置文件的方式

<Context>

 <!-- maxIdleSwap:session中的对象多长时间不使用就钝化 -->

 <!-- directory:钝化后的对象的文件写到磁盘的哪个目录下  配置钝化的对象文件在            work/catalina/localhost/钝化文件 -->

 <Manager className="org.apache.catalina.session.PersistentManager"          maxIdleSwap="1">

  <Store className="org.apache.catalina.session.FileStore" directory="itcast205" />

 </Manager>

</Context>

1分钟访问就会被钝化,然后再次访问就会被激活了   (在原有钝化基础上起作用)

 

邮箱服务器

邮件发送的协议:

协议:就是数据传输的约束

发送邮件的协议:SMTP             接受邮件的协议:POP3  

 

过滤器filter

写一个类实现filter接口

实现方法(着重实现doFilter方法)

在web.xml里面配置(主要对哪些资源拦截)

放行 chain.doFilter(request, response);

注解:在类上添加    /*  拦截所有

@WebFilter("/*") //访问所有的资源之前,多会执行该过滤器

获取任何位置

类.class.getClassLoader().getResource(“”).getPath()

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

可以增强参数 返回值 方法体的逻辑

代理对象

public class ProxyTest {

    public static void main(String[] args) {
        //1.创建真实对象
        Lenovo lenovo = new Lenovo();
        //2.动态代理增强lenovo对象
        /*
            三个参数:
                1. 类加载器:真实对象.getClass().getClassLoader()
                2. 接口数组:真实对象.getClass().getInterfaces()
                3. 处理器:new InvocationHandler()
         */
        SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
            /*
                代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                    参数:
                        1. proxy:代理对象
                        2. method:代理对象调用的方法,被封装为的对象
                        3. args:代理对象调用的方法时,传递的实际参数
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /*System.out.println("该方法执行了....");
                System.out.println(method.getName());
                System.out.println(args[0]);


*/
                //判断是否是sale方法
                if(method.getName().equals("sale")){
                    //1.增强参数
                    double money = (double) args[0];
                    money = money * 0.85;
                    System.out.println("专车接你....");
                    //使用真实对象调用该方法
                    String obj = (String) method.invoke(lenovo, money);
                    System.out.println("免费送货...");
                    //2.增强返回值
                    return obj+"_鼠标垫";
                }else{
                    Object obj = method.invoke(lenovo, args);
                    return obj;
                }

            }
        });

        //3.调用方法

       /* String computer = proxy_lenovo.sale(8000);
        System.out.println(computer);*/

        proxy_lenovo.show();
    }
}

 

结果:如果调用的show方法,不会被增强,原样输出

如果调用的sale方法,

 

结果:

辅助理解

打印的结果

在src下面放一个文件,里面放敏感词汇

/**
 * 敏感词汇过滤器
 */
@WebFilter("/*")
public class SensitiveWordsFilter implements Filter {


    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.创建代理对象,增强getParameter方法

        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //增强getParameter方法
                //判断是否是getParameter方法
                if(method.getName().equals("getParameter")){
                    //增强返回值
                    //获取返回值
                    String value = (String) method.invoke(req,args);
                    if(value != null){
                        for (String str : list) {
                            if(value.contains(str)){
                                value = value.replaceAll(str,"***");
                            }
                        }
                    }
                    
                    return  value;
                }

                //判断方法名是否是 getParameterMap

                //判断方法名是否是 getParameterValue

                return method.invoke(req,args);
            }
        });

        //2.放行
        chain.doFilter(proxy_req, resp);
    }
    private List<String> list = new ArrayList<String>();//敏感词汇集合
    public void init(FilterConfig config) throws ServletException {

        try{
            //1.获取文件真实路径
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
            //2.读取文件
            BufferedReader br = new BufferedReader(new FileReader(realPath));
            //3.将文件的每一行数据添加到list中
            String line = null;
            while((line = br.readLine())!=null){
                list.add(line);
            }

            br.close();

            System.out.println(list);

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

    }

    public void destroy() {
    }

}

问题

1.使用jdbc的事务来操作数据库

2.使用dbutils的事务来操作数据库

3.使用三层架构完成转账的操作           1)先写没有事务的     2)然后写个事务的     发现结果还对            3)在转账之间写个i=1/0,控制台报错就对了      

4.修改ul下面的li的值

5.使用原生ajax来访问  

6.使用原生ajax来访问      并且生成随机数放在后面随机数

7.使用原生ajax来访问      分别用get和post方式来传数据   

8.将json格式里面的java对象描述 为json格式的并取值

9.使用get和post方式返回字符串   

10.使用get和post方式返回对象

11.使用ajax方式访问服务器返回json对象的字符串 

12.异步校验用户名是否存在

12.2:站内搜索(鼠标抬起的时候,会自动去数据库查询)

13.写一个监听器并且写一个银行计息

14.使用ServletContextAttributeListener来监听属性的变化

15.测试感知监听器HttpSessionBindingListener的绑定与解绑  

16.测试感知监听器HttpSessionActivationListener的钝化和活化

17.使用监听器定时完成定时发送生日祝福

18.filter快速入门

19.自动登录    有个过滤器 如果带了username和password的cookie 那么就用filter来增强

怎么解决用户名是中文的情况  由于cookie不能有中文       先编码然后在解码

20.校验用户名是否存在

    1.使用jdbc的事务来操作数据库

public class Answer1 {
	@Test
		public void show1(){
		Connection conn=null;
			try {
				Class.forName("com.mysql.jdbc.Driver");
				 conn=DriverManager.getConnection("jdbc:mysql:///javaweb_day3","root","root");
				 //使用jdbc手动开启事务
				 conn.setAutoCommit(false);
				 String sql="update shiwu set name='zs' where id=1 ";
				 Statement stat=conn.createStatement();
				 int count=stat.executeUpdate(sql);
				 if(count>0){
					 System.out.println("修改数据成功");
					 //提交事务
					 conn.commit();
				 }
			} catch (Exception e) {
				try {
					//回滚事务
					conn.rollback();
				} catch (SQLException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			}
		}
}

2.使用dbutils的事务来操作数据库

public class Answer2 {
	@Test
	public void show() {
		QueryRunner qr=new QueryRunner();
		String url="com.mysql.jdbc.Driver";
		String user="root";
		String password="root";
		String sql="update shiwu set name='zhangsan' where id=1 ";
		Connection conn=null;
		try {
			conn = DriverManager.getConnection(url,user,password);
			//开启事务
			conn.setAutoCommit(false);
			qr.update(conn, sql);
			//提交事务
			conn.commit();
		} catch (SQLException e) {
			//回滚事务
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}
		
		
	}

}

3.使用三层架构完成转账的操作          

public class TransferServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		request.setCharacterEncoding("utf-8");
		String out=request.getParameter("out");
		String in=request.getParameter("in");
		String stringMoney=request.getParameter("money");
		double money=Double.parseDouble(stringMoney);
		System.out.println(out+in+money);
		TransferService service=new TransferService();
		boolean flag=service.transfer(out,in,money);
		if(flag){
			response.getWriter().write("恭喜你转账成功");
		}else{
			response.getWriter().write("您转账失败!!");
		}
	}

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







public class TransferService {
	String url="jdbc:mysql:///javaweb_day3";
	String user="root";
	String password="root";
	Connection conn=null;
	boolean flag=true;
	
	static{
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public boolean transfer(String out, String in, double money) {
		TransferDao dao=new TransferDao();
		try {
			conn=DriverManager.getConnection(url, user, password);
			//开启事务
		    conn.setAutoCommit(false);
			dao.out(conn,out,money);
			int i=1/0;
			dao.in(conn,in,money);
		} catch (Exception e) {
			flag=false;
			//回滚事务
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally{
			//提交事务
			try {
				conn.commit();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return flag;
	}
}






public class TransferDao {
	public void out(Connection conn, String out, double money) throws SQLException {
		QueryRunner qr = new QueryRunner();
		String sql = "update shiwu set money=money-? where name=?";
		qr.update(conn, sql,money ,out);
	}

	public void in(Connection conn, String in, double money) throws SQLException {
		QueryRunner qr = new QueryRunner();
		String sql = "update shiwu set money=money+? where name=?";
		qr.update(conn, sql,money ,in);
	}
}




<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
	<form action="${pageContext.request.contextPath }/transferServlet" method="post">
		转出账户:<input type="text" name="out"><br>
		转入账户:<input type="text" name="in"><br>
		转出金额:<input type="text" name="money"><br>
		<input type="submit" value="确认转账"><br>
	</form>


</body>
</html>

4.修改ul下面的li的值

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
	<script type="text/javascript">
		window.onload=function(){
			document.getElementById("btn").getElementsByTagName("li")[0].innerHTML="我是大神";
		}
		
	</script>

<body>

<ul id="btn">
	<li>我是弱鸡</li>
</ul>


</body>
</html>

5.使用原生ajax来访问  

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
	<script type="text/javascript">
		function change1(){
			//1、创建ajax引擎对象 ---- 所有的操作都是通过引擎对象
			var xmlHttp=new XMLHttpRequest();
			//2、绑定监听 ---- 监听服务器是否已经返回相应数据
			xmlHttp.onreadystatechange=function(){
				if(xmlHttp.readyState==4 &&xmlHttp.status==200){
					//5、接受响应数据
					var hh=xmlHttp.responseText;
						alert(hh);
				}
			}
			//3、绑定地址
			xmlHttp.open("post","${pageContext.request.contextPath}/answerServlet",true);
			//4、发送请求
			xmlHttp.send();
		}
		
	</script>

<body>

<input type="button" value="异步访问" onclick="change1()"><br>

</body>
</html>





//服务器响应的数据
public class AnswerServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().write("hello guoyebing...");
	}

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

6.使用原生ajax来访问      并且生成随机数放在后面随机数

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>  <!-- 2.使用原生ajax来访问      并且生成随机数放在后面随机数 -->
	<script type="text/javascript">
		function change1(){
			//1、创建ajax引擎对象 ---- 所有的操作都是通过引擎对象
			var xmlHttp=new XMLHttpRequest();
			//2、绑定监听 ---- 监听服务器是否已经返回相应数据
			xmlHttp.onreadystatechange=function(){
				if(xmlHttp.readyState==4 &&xmlHttp.status==200){
					//5、接受响应数据
					var hh=xmlHttp.responseText;
					document.getElementById("bt").innerHTML=hh;
				}
			}
			//3、绑定地址
			xmlHttp.open("post","${pageContext.request.contextPath}/answerServlet",true);
			//4、发送请求
			xmlHttp.send();
		}
		
	</script>

<body>

<input type="button" value="异步访问" onclick="change1()"><span id="bt"></span>

</body>
</html>



public class AnswerServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().write(Math.random()+" ");
	}

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

7.使用原生ajax来访问      分别用get和post方式来传数据   

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>  <!-- 2.使用原生ajax来访问      并且生成随机数放在后面随机数 -->
	<script type="text/javascript">
		function change1(){
			//1、创建ajax引擎对象 ---- 所有的操作都是通过引擎对象
			var xmlHttp=new XMLHttpRequest();
			//2、绑定监听 ---- 监听服务器是否已经返回相应数据
			xmlHttp.onreadystatechange=function(){
				if(xmlHttp.readyState==4 &&xmlHttp.status==200){
					//5、接受响应数据
					var hh=xmlHttp.responseText;
					document.getElementById("bt1").innerHTML=hh;
				}
			}
			//3、绑定地址
			xmlHttp.open("get","${pageContext.request.contextPath}/answerServlet?name=zhangsan",true);
			//4、发送请求
			xmlHttp.send();
		}
		
		
		function change2(){
			//1、创建ajax引擎对象 ---- 所有的操作都是通过引擎对象
			var xmlHttp=new XMLHttpRequest();
			//2、绑定监听 ---- 监听服务器是否已经返回相应数据
			xmlHttp.onreadystatechange=function(){
				if(xmlHttp.readyState==4 &&xmlHttp.status==200){
					//5、接受响应数据
					var hh=xmlHttp.responseText;
					document.getElementById("bt2").innerHTML=hh;
				}
			}
			//3、绑定地址
			xmlHttp.open("post","${pageContext.request.contextPath}/answerServlet",true);
			//4、发送请求
			xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
			xmlHttp.send("name=lisi");
		}
		
	</script>

<body>

<input type="button" value="异步get访问获取参数" onclick="change1()"><span id="bt1"></span><br>
<input type="button" value="异步post访问获取参数" onclick="change2()"><span id="bt2"></span>
</body>
</html>



public class AnswerServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String name=request.getParameter("name");
		response.getWriter().write(name);
	}

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

8.将json格式里面的java对象描述 为json格式的并取值

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
  
  <script language="JavaScript">
	/**
	 * 案例一
	 *  {key:value,key:value}
	 *  
	 * class Person{
	 * 	  String firstname = "张";
	 *    String lastname = "三丰";
	 *    Integer age = 100;
	 * }
	 * 
	 * Person p = new Person();
	 * System.out.println(p.firstname);
	 */
	
	var person={"firstname":"张","lastname":"三丰","age":100};
	 
/* 	取出lastname的值 */
	alert(person.lastname);

  </script>


  <!-- ======================= -->
  <script language="JavaScript">
  	/**
	 * 案例二
	 *  [{key:value,key:value},{key:value,key:value}]
	 */
	 
	 var persons=[
					{"firstname":"张","lastname":"三丰","age":100},
					{"firstname":"李","lastname":"四","age":25}
	              ];
	//取出lastname=三丰		age=25
  	
	alert(persons[0].lastname);
	alert(persons[1].age);
  </script>


<!-- ======================= -->
  <script language="JavaScript">
   /**
	 * 案例三
	 * {
	 *   "param":[{key:value,key:value},{key:value,key:value}]
	 * } 
	 */
	 
	 var json={
			 "baobao":[
			           {"name":"建宁","age":18,"addr":"紫荆城"},
			           {"name":"阿珂","age":16,"addr":"山西"},
			           {"name":"小双","age":20,"addr":"扬州"},
			           ]
	 };
	 
	//取name=阿珂
	alert(json.baobao[1].name);
	//取addr=扬州
	alert(json.baobao[2].addr);
  </script>


 <!-- ================ -->
  <script language="JavaScript">
   /**
	 * 案例四
	 * {
	 *   "param1":[{key:value,key:value},{key:value,key:value}],
	 *   "param2":[{key:value,key:value},{key:value,key:value}],
	 *   "param3":[{key:value,key:value},{key:value,key:value}]
	 * }
	 */
	 var json={
			 "baobao":[
			           {"name":"建宁","age":18,"addr":"紫荆城"},
			           {"name":"阿珂","age":16,"addr":"山西"},
			           {"name":"小双","age":20,"addr":"扬州"},
			           ],
             "bingbing":[
			           {"name":"大神","age":18,"addr":"紫荆城"},
			           {"name":"小神","age":16,"addr":"山西"}
			           ]
			           
	 };
	 
	//取bingbing下的小神
	alert(json.bingbing[1].name);
  </script>


<!-- =================== -->
  <script language="JavaScript">
 	/**
	 * 案例五
	 * {
	 *   "param1":"value1",
	 *   "param2":{},
	 *   "param3":[{key:value,key:value},{key:value,key:value}]
	 * } 
	 */
	 var json = {
				"key1":"value1",
				"key2":{"firstname":"张","lastname":"三丰","age":100},
				"key3":[
	 		          	{"name":"小双","age":28,"addr":"扬州"},
	 		          	{"name":"建宁","age":18,"addr":"紫禁城"},
	 		          	{"name":"阿珂","age":10,"addr":"山西"},
	 		          ]
		 };
		 //取三丰
		 alert(json.key2.lastname);
		 //取阿珂
		 alert(json.key3[2].name);
  </script>

9.使用get和post方式返回字符串   

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery-1.8.3.min.js"></script> 
<title>Insert title here</title>
    <script type="text/javascript">
    		function get(){           
  				$.get("${pageContext.request.contextPath}/answerServlet",
                        {"name":"张三","age":15},  //请求参数
                        function(data){           //执行成功后的回调函数
  		    		        alert(data);
  		    	        },"text")    //返回的数据类型
    		    }
    		function post(){
		    	$.post("${pageContext.request.contextPath}/answerServlet",
                         {"name":"张三","age":15},function(data){
		    		        alert(data);
		    	            },"text")
    		    }
    </script>
</head>
	<body>
		<input type="button" value="get方式返回字符串  " onclick="get()"><br>
		<input type="button" value="post方式返回字符串  " onclick="post()">
   </body>
</html>  



public class AnswerServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		String name=request.getParameter("name");
		response.getWriter().write(name);
	}

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

10.使用get和post方式返回对象

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery-1.8.3.min.js"></script> 
<title>Insert title here</title>
   <script>
			function get(){
				$.get(
						"${pageContext.request.contextPath}/answerServlet",
						{"name":"zs","age":"14"},
						function(data){
							alert(data.name);
						},
						"json"
						);
			}
	
			
			function post(){
				$.post(
					"${pageContext.request.contextPath}/answerServlet",
					{"name":"zs","age":"14"},
					function(data){
						alert(data.name);
					},
					"json"
					);
				}
	
	</script>
</head>
	<body>
		<input type="button" value="get方式返回字符串  " onclick="get()"><br>
		<input type="button" value="post方式返回字符串  " onclick="post()">
   </body>
</html>  


public class AnswerServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//java代码只能返回一个json格式的字符串{"name":"李四","age":18}转译得到下面的
		response.getWriter().write("{\"name\":\"李四\",\"age\":18}");
	}

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


11.使用ajax方式访问服务器返回json对象的字符串 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery-1.8.3.min.js"></script> 
<title>Insert title here</title>
   <script>
			function ajax(){
				$.ajax({
					url:"${pageContext.request.contextPath}/answerServlet",
					async:true, //默认是true,不需要配置
					type:"post", //默认是get
                    data:{"name":"张三","age":15},
					dataType:"json",
					success:function(data){
						alert(data.name);
					}
				});
			}
	
			
			
	
	</script>
</head>
	<body>
		<input type="button" value="ajax方式返回字符串  " onclick="ajax()">
</html>  


public class AnswerServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//java代码只能返回一个json格式的字符串{"name":"李四","age":18}转译
		response.getWriter().write("{\"name\":\"李四\",\"age\":18}");
	}

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

12.异步校验用户名是否存在(部分代码)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="${pageContext.request.contextPath }/jquery-1.8.3.min.js"></script> 
<title>Insert title here</title>
   <script>
   $(function(){
	 //为输入框绑定事件
	   $("#username").blur(function(){
		 //1、失去焦点获得输入框的内容
		   var username=$("#username").val();
		 //2、去服务端校验该用户名是否存在---ajax
			 $.post("${pageContext.request.contextPath}/answerServlet",{"username":username},function(data){
				 var isExist = data.isExist;
				 //3、根据返回的isExist动态的显示信息
				var usernameInfo = ""; 
				if(isExist){
					//该用户存在
					usernameInfo = "该用户名已经存在";
					$("#usernameInfo").css("color","red"); 
				}else{
					 usernameInfo = "该用户可以使用"
					$("#usernameInfo").css("color","green"); 
				}
				 $("#usernameInfo").html(usernameInfo); 
			},"json"); 
	   });
   });
	</script>
	

	
</head>
	<body>
		<form action="${pageContext.request.contextPath }/answerServletDemo" method="post">
			用户名:<input type="text" name="username" id="username"><span id="usernameInfo"></span> <br>
			密码:<input type="password" name="password"><br>
			<input type="button" value="提交">
		</form>
	</body>
</html>  







public class AnswerServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String username=request.getParameter("username");
		UserService service=new UserService();
		boolean isExist=false;
		try {
		 isExist=service.checkUsername(username);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		response.getWriter().write("{\"isExist\":"+isExist+"}");
	}

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




public class UserService {

	public boolean checkUsername(String username) throws SQLException {
		UserDao dao=new UserDao();
		Long isExist = dao.checkUsername(username);
		return isExist>0?true:false;
	}

}





public class UserDao {

	public Long checkUsername(String username) throws SQLException {
		QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
		String sql = "select count(*) from user where username=?";
		Long query = (Long) runner.query(sql, new ScalarHandler(), username);
		return query;
	}

}

12.2 站内搜索

//前端代码   只是部分代码,里面的height不要固定,到时候随着内容的变化而自动变化
<form class="navbar-form navbar-right" role="search" style="position:relative">
	<div class="form-group" >
	<input type="text" class="form-control" placeholder="Search"  id="search">
		<div  style="position:absolute;z-index:1000;background:#fff; width:179px;height:200px;border:1px solid #ccc;">
	</div>
		<button type="submit" class="btn btn-default">Submit</button>
</form>


<script>
 $(function(){
	$("#search").keyup(function(){
		var pname=$("#search").val();
		var content="";
		$.ajax({
			url:"${pageContext.request.contextPath}/searchServlet",
			data:{"pname":pname},
			type:"post",
			dataType:"json",
			success:function(data){
				if(data.length>0){
					for(var i=0;i<data.length;i++){
						content+="<div style='padding:5px;cursor:pointer' onclick='clickFn(this)' onmouseover='overFn(this)' onmouseout='outFn(this)'>"+data[i]+"</div>";
					}
					$("#showDiv").html(content);
				}
			}
		});
	});
}); 
</script>



public class SearchServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String pname = request.getParameter("pname");
		ProductService service=new ProductServiceImpl();
		List<Object> productList=null;
		try {
			productList = service.findByPname(pname);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		JSONArray json=JSONArray.fromObject(productList);
		String jsonStr= json.toString();
		response.setContentType("text/html;charset=utf-8");
		System.out.println(jsonStr);
		response.getWriter().write(jsonStr);
	}

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


public class ProductServiceImpl implements ProductService {
	ProductDao dao=new ProductDaoImpl();
	//根据关键字查询商品
	public List<Object> findByPname(String pname) throws SQLException {
		return dao.findByPname(pname);
	}

}


public class ProductDaoImpl implements ProductDao {

	@Override
	public List<Object> findByPname(String pname) throws SQLException {
		QueryRunner runner=new QueryRunner(DataSourceUtils.getDataSource());
		String sql="select * from product where pname like ? limit 0,8";
		List<Object> query=runner.query(sql, new ColumnListHandler("pname"),"%"+pname+"%");
		return query;
	}

}

13.写一个监听器并且写一个银行计息

public class MyContextListener implements ServletContextListener{
	public void contextInitialized(ServletContextEvent arg0) {
		Timer timer=new Timer();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String currentTime ="2019-08-17 13:45:00";    
		Date dateTime=null;
		try {
			dateTime = sdf.parse(currentTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		timer.scheduleAtFixedRate(new TimerTask(){
			public void run() {
				System.out.println("银行计息了.....");
		}
		}, dateTime,24*60*60*1000);
		
		

		/*开启一个计息任务调度----每天晚上12点 计息一次
			Timer timer = new Timer();
			task:任务  firstTime:第一次执行时间  period:间隔执行时间
			timer.scheduleAtFixedRate(task, firstTime, period);
			timer.scheduleAtFixedRate(new TimerTask() {
					@Override
					public void run() {
						System.out.println("银行计息了.....");
					}
				} , new Date(), 5000);*/
		
	}

	public void contextDestroyed(ServletContextEvent arg0) {
		
	}

	

}

14.使用ServletContextAttributeListener来监听属性的变化

public class TestServletContextAttributeListener extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext context=this.getServletContext();
		//存数据
		context.setAttribute("name", "zs");
		//改数据
		context.setAttribute("name", "lisi");
		//删除数据
		context.removeAttribute("name");
	}

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






public class Answer2 implements ServletContextAttributeListener{

	public void attributeAdded(ServletContextAttributeEvent arg0) {
		//放到域中的属性
		System.out.println(arg0.getName());//放到域中的name
		System.out.println(arg0.getValue());//放到域中的value
	}

	public void attributeRemoved(ServletContextAttributeEvent arg0) {
		System.out.println(arg0.getName());//删除的域中的name
		System.out.println(arg0.getValue());//删除的域中的value
	}

	public void attributeReplaced(ServletContextAttributeEvent arg0) {
		System.out.println(arg0.getName());//获得修改前的name
		System.out.println(arg0.getValue());//获得修改前的value
	}

}

15.测试感知监听器HttpSessionBindingListener的绑定与解绑  

public class Person implements HttpSessionBindingListener{

	private String id;
	private String name;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public void valueBound(HttpSessionBindingEvent arg0) {
		//将对象绑定到域中   此方法会被运行
		System.out.println("person被绑定了");
	}

	public void valueUnbound(HttpSessionBindingEvent arg0) {
		//将对象从域中移除 此方法会被运行
		System.out.println("person被解绑了");
	}

}




public class TestHttPSessionBindingListener extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session=request.getSession();
		Person person=new Person();
		person.setId("100");
		person.setName("zhangsan");
		session.setAttribute("person", person);
          session.removeAttribute("person");
	}

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

16.测试感知监听器HttpSessionActivationListener的钝化和活化

public class Customer implements HttpSessionActivationListener,Serializable{

	private String id;
	private String name;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
	//钝化
	public void sessionWillPassivate(HttpSessionEvent se) {
		System.out.println("customer被钝化了");
	}
	//活化
	public void sessionDidActivate(HttpSessionEvent se) {
		System.out.println("customer被活化了");
	}
	
	
}





public class TestHttpSessionActivationListener extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession();
		
		//将customer放到session中
		Customer customer =new Customer();
		customer.setId("200");
		customer.setName("lucy");
		session.setAttribute("customer", customer);
		System.out.println("customer被放到session域中了");
	}

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





public class TestHttpSessionActivationListener2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//从session域中获得customer
		HttpSession session = request.getSession();
		Customer customer = (Customer) session.getAttribute("customer");
		
		System.out.println(customer.getName());
	}

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

17.使用监听器定时完成定时发送生日祝福

public class Customer {
    //set和get方法省略
	private int id ;
	private String username;
	private String password ;
	private String realname ;
	private String birthday ;
	private String email ;
}





public class BirthdayListener implements ServletContextListener{

	public void contextDestroyed(ServletContextEvent arg0) {
		
	
	}

	public void contextInitialized(ServletContextEvent arg0) {
		Timer timer=new Timer();
		timer.scheduleAtFixedRate(new TimerTask(){
			@Override
			public void run() {
				//1. 为当前的生日的用户发邮件
				//获得今天的日期
				SimpleDateFormat format = new SimpleDateFormat("MM-dd");
				String currentDate = format.format(new Date());
				//根据当前时间从数据查询今天过生日的人
				QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
				String sql = "select * from customer where birthday like ?";
				List<Customer> customerList = null;
				try {
					customerList = runner.query(sql, new BeanListHandler<Customer>(Customer.class) ,"%"+currentDate+"%");   //05-18 后面的%没有也行
				} catch (SQLException e) {
					e.printStackTrace();
				}
				//2、发邮件
				if(customerList!=null&&customerList.size()>0){
					for(Customer c : customerList){
						String emailMsg = "亲爱的:"+c.getRealname()+",生日快乐!";
						try {
							MailUtils.sendMail(c.getEmail(),  emailMsg);
							System.out.println(c.getRealname()+"邮件发送完毕");
						} catch (MessagingException e) {
							e.printStackTrace();
						}
					}
				}
			}
			
		}, new Date(), 1000*30);
		//实际开发中起始时间是一个固定的时间
		//实际开发中间隔时间是1天
	}

}

18.filter快速入门

//web.xml配置文件  拦截所有 
 <filter>
    <filter-name>QuickFilter</filter-name>
    <filter-class>cn.itcast.answer4.Answer1Filter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>QuickFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>






public class TestServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().write("hello Filter");
		System.out.println("我有没有被拦截啊");
	}

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







public class Answer1Filter implements Filter{

	public void destroy() {
		
	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("过滤器的拦截起作用了...");
		chain.doFilter(request, response);  //放行
	}

	public void init(FilterConfig arg0) throws ServletException {
		
	}

}

19.自动登录

登录成功前后,显示不同

页面登录错误提示

public class LoginServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		UserService service=new UserService();
		request.setCharacterEncoding("utf-8");
		String username=request.getParameter("username"); //中文 张三
		String password=request.getParameter("password");
		HttpSession session=request.getSession();
		User user=null;
		try {
			user = service.login(username,password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		if(user!=null){
			String autoLogin=request.getParameter("autoLogin");
			//说明勾上了
			if(autoLogin!=null){
				//由于cookie不能存汉字,因此先编码
				String cookie_code=URLEncoder.encode(username,"utf-8");
				Cookie cookie_username=new Cookie("cookie_username",cookie_code);
				Cookie cookie_password=new Cookie("cookie_password",user.getPassword());
				//设置cookie的持久化时间
				cookie_username.setMaxAge(60*60);
				cookie_password.setMaxAge(60*60);
				//设置cookie的携带路径
				cookie_username.setPath(request.getContextPath());
				cookie_password.setPath(request.getContextPath());
				//发送cookie
				response.addCookie(cookie_username);
				response.addCookie(cookie_password);
			}
			//登录成功要将用户名保存到session域中
			session.setAttribute("user", user);
			response.sendRedirect(request.getContextPath());
			
		}else{
			request.setAttribute("msg", "用户名或者密码错误");
			request.getRequestDispatcher("/login.jsp").forward(request, response);
		}
		
	}

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





//自动登录增强
public class AutoLogin implements Filter {

    public AutoLogin() {
    }

	public void destroy() {
	}

	public void doFilter(ServletRequest arg1, ServletResponse arg2, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request=(HttpServletRequest) arg1;
		HttpServletResponse response=(HttpServletResponse) arg2;
		HttpSession session=request.getSession();
		//获得cookie中用户名和密码 进行登录的操作
		Cookie[] cookies=request.getCookies();
		String cookie_username=null;
		String cookie_password=null;
		if(cookies!=null){
			for(Cookie cookie:cookies){
				if("cookie_username".equals(cookie.getName())){
					cookie_username=cookie.getValue();
					//恢复中文用户名
					cookie_username=URLDecoder.decode(cookie_username,"utf-8");
				}
				if("cookie_password".equals(cookie.getName())){
					cookie_password=cookie.getValue();
				}
				
			}
		}
		
		//判断username和password是否是null
		if(cookie_username!=null && cookie_password !=null){
			UserService service=new UserService();
			User user=null;
			try {
				user=service.login(cookie_username, cookie_password);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			//将登录的用户的user对象存到session中
			session.setAttribute("user", user);
		}
		//放行
		chain.doFilter(arg1, arg2);
	}

	public void init(FilterConfig fConfig) throws ServletException {
	}

}

20.

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guoyebing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值