课堂 笔记(一)

dubbo 存储结构

**树形存储结构**

在这里插入图片描述

md5加密

导入的包 为 import org.springframework.util.DigestUtils;

   public void saveUser(User user) {

        String md5Password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        user.setPassword(md5Password).setEmail(user.getPhone());
        userMapper.insert(user);
    }
}

服务器

服务器:分为服务器硬件 和 服务器软件。在硬件服务器(计算机)上安装了服务器软件,才可以对外提供服务。
(1) 服务器硬件:是指在互联网上具有独立IP地址的计算机,比如我们自己用的计算机也可以作为服务器使用。

(2) 服务器软件:就是一个计算机程序,比如MySQL服务器软件,tomcat服务器软件。服务器软件分为很多类型,比如:ftp服务器,数据库服务器,web服务器软件,邮件服务器等。

WEB服务器

(1) web服务器是指驻留在互联网上的某种类型的计算机程序。当浏览器访问服务器,请求服务器上的文件时,服务器将会处理该请求,并将请求的文件响应给浏览器,并会附带一些信息告诉浏览器如何查看该文件(即文件的类型)

(2) web服务器是可以向 “发出请求的浏览器提供文档” 的程序,比如在访问百度时,其实就是在访问百度的服务器。
tomcat就是一个web服务器软件,是由apache组织提供的一款服务器软件,特点:小巧灵活,免费开源,简单易用。

TOMCAT

tomcat服务器运行需要jdk的支持,版本对应为:
tomcat5 需要jdk4以上支持
tomcat6 需要jdk5以上支持
tomcat7 需要jdk6以上支持
tomcat8 需要jdk7以上支持
启动、关闭tomcat服务器:

通过 [tomcat根目录]\bin\startup.bat 可以启动tomcat服务器;

通过 [tomcat根目录]\bin\shutdown.bat 可以关闭tomcat服务器;
默认端口 8080
修改端口
找到 [tomcat安装目录]/conf/server.xml 文件并打开该文件,将文件中的 69 行的 <Connector> 标签上的 port 属性的值改为 80即可。改完后,保存文件,重新启动服务器

<Connector port="80" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

cmd 查找进程 杀死进程的方法

打开一个cmd窗口,通过 netstat -ano 命令查看当前系统中活动的进程,找到80端口对应的进程编号(PID),根据进程编号将进程结束即可!
在这里插入图片描述
执行命令

taskkill /f /pid 进程编号

get提交和post提交的区别

主要区别体现在请求参数传输过程的不相同

GET提交:

  • 将数据通过问号拼接在地址栏URL地址的后面,相对非常不安全。
  • 将数据拼接在地址栏URL地址的后面,数据量是有限制的,通常不能超过1KB或者4KB。

POST提交:(form)

  • POST提交是通过请求实体将数据提交给服务器,不会显示在地址栏上,因此相对更加安全。
  • POST提交通过请求实体提交数据,数据量理论上是没有限制的。

Request

request是代表HTTP请求信息的对象,response是代表HTTP响应信息的对象。
当浏览器发请求访问服务器中的某一个Servlet时,服务器将会调用Servlet中的service方法来处理请求。在调用service方法之前会创建出request和response对象
在请求处理完,响应结束时,服务器会销毁request和response对象

请求参数

所谓的请求参数,就是浏览器发送给服务器的数据(不区分请求方式),例如:通过表单向服务器提交的用户名、密码等,或者在超链接后面通过问号提交的数据,都是请求参数。

http://localhost/day10/TestParam?user=zhangsan&pwd=123&like=篮球&like=足球

获取请求参数

(1)request.getParameter(String paramName)
– 根据请求参数的名字获取对应的参数值,返回值是一个字符串
– 如果一个参数有多个值,该方法只会返回第一个值
– 如果获取的是一个不存在的参数,返回值为null
(2)request.getParameterValues(String paramName)
– 根据请求参数的名字获取该名字对应的所有参数值组成的数组,返回值是一个字符串数组,其中包含了这个参数名对应的所有参数值
– 如果获取的是一个不存在的参数,返回值为null

实现求请转发

(1)转发是一次请求,一次响应
(2)请求转发前后,浏览器的地址栏地址不会发生变化。(浏览器–访问–> A --转发–> B,地址栏地址始终指向A的地址)
(3)请求转发前后的request对象是同一个(转发前在A中的request和转发到B后,B中的request对象和A中的request对象是同一个。基于这一点,可以通过request从A带数据到B)
(4)请求转发前后的两个资源必须属于同一个Web应用,否则将无法进行转发。(A–转发–>B,A和B必须属于同一个Web应用!)

request.getRequestDispatcher(url地址/转发到资源的地址).forward(req, res);

作为域对象使用

request在实现转发时,通过request.setAttribute方法和request.getAttribute方法带数据到目的地时,就是通过request对象中的map集合带数据,这个request对象上的map集合以及request对象所在的范围即称之为是一个域对象。

如果一个对象具备可以被访问的范围,通过这个对象上的map集合可以在整个范围内实现数据的共享。这样的对象就叫做域对象。

在request对象上提供了往域对象(map)中存数据的方法以及取数据的方法

request.setAttribute(String attrName, Object attrValue);
-- 往request域中存入一个域属性,属性名(key)只能是字符串,属性值(value)可以是任意类型。
request.getAttribute(String attrName);
-- 根据属性名(key)获取对应的属性值(value)。返回的是一个Object类型的对象。

request域对象所具备的三大特征:

**生命周期:**在服务器调用Servlet程序的service方法之前,会创建代表请求的request对象,在请求处理完,响应结束时,会销毁request对象。

**作用范围:**在一次请求范围内,都可以获取到同一个request对象。

**主要功能:**和请求转发配合使用,从Servlet带数据到JSP(带数据到目的地)

Resonse

response是代表HTTP响应信息的对象。

1.向客户端发送数据

PrintWriter out = response.getWriter();
由于服务器在通过response获取的流发送数据时,默认使用iso8859-1编码,而这个编码中没有中文字符,所以在通过response获取的流发送中文数据时,会出现乱码问题。

解决方法是:在响应数据之前,通知服务器使用utf-8发送数据。

/*  通知服务器在响应数据时,使用utf-8编码
 * 也能通知浏览器使用utf-8接收服务器发送的数据 */
response.setContentType( "text/html;charset=utf-8" );
PrintWriter out = response.getWriter();
out.write( "你好" );

实现重定向

当浏览器向服务器发请求访问某一个资源A,资源A在响应时通知浏览器需要再进一步请求才能获取到对应的资源,浏览器再次发请求访问服务器中的资源B,最终由资源B响应浏览器要获取的资源,这个过程叫做重定向。
(1)重定向是两次请求、两次响应
(2)重定向前后,浏览器的地址栏地址会发生变化。(因为两次请求都是通过浏览器发起,浏览器知道这个跳转的过程,因此地址栏地址会变化)
(3)重定向前后的request对象不是同一个(因为重定向是两次请求,服务器会根据两次请求创建两个不同的request对象,request对象不是同一个,也就不能在重定向时通过request带数据到目的地。)
(4)重定向前后的两个资源可以是来自不同的web应用,甚至可以是来自不同的服务器。(进行跳转的两个资源之间没有限制)

response.sendRedirect(所重定向到资源的URL地址);

jar 包的插入 在不知道坐标的情况下 可以访问如下网址 访问

http://mvnrepository.com

3、示例:添加c3p0的jar包的坐标到项目中

  • 访问上面其中的一个网址,在搜索框中搜索 “c3p0”

  • 在搜索出来的内容中,选择所需要的版本并点击版本,查看该版本的c3p0
    jar包所对应的坐标:

  • 将坐标直接拷贝到项目的pom.xml文件中即可:

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

Cookie Session

什么是会话

当浏览器发请求访问服务器开始,一直到访问服务器结束,浏览器关闭为止,这期间浏览器和服务器之间产生的所有请求和响应加在一起,就称之为浏览器和服务器之间的一次会话。

cookie 工作原理

  1. Cookie是将会话中产生的数据保存在客户端,是客户端技术。
  2. Cookie是基于两个头进行工作的:分别是Set-Cookie响应头和Cookie请求头
  3. 通过Set-Cookie响应头将cookie从服务器端发送给浏览器,让浏览器保存到内部;而浏览器一旦保存了cookie,以后浏览器每次访问服务器时,都会通过cookie请求头,将cookie信息再带回服务器中。在需要时,在服务器端可以获取请求中的cookie中的数据,从而实现某些功能。

cookie API

1、创建Cookie对象

Cookie c = new Cookie(String name, String value);
// 创建cookie的同时需要指定cookie的名字和cookie要保存的值

2、将Cookie添加到response响应中

response.addCookie( Cookie c );
// 将cookie添加到响应中,由服务器负责将cookie信息发送给浏览器,再由浏览器保存到内部(可以多次调用该方法,添加一个以上的cookie)

3、获取请求中的所有cookie对象组成的数组

// cookie的API中没有提供直接删除cookie的方法,可以通过别的方式间接删除cookie
// 删除名称为cart的cookie:可以向浏览器再发送一个同名的cookie(即名称也叫做cart),并设置cookie的最大生存时间为零,由于浏览器是根据cookie的名字来区分cookie,如果前后两次向浏览器发送同名的cookie,后发送的cookie会覆盖之前发送的cookie。而后发送的cookie设置了生存时间为零,因此浏览器收到后也会立即删除!
//创建一个名称为cart的cookie
Cookie c = new Cookie("cart", "");
//设置cookie的最大生存时间为零
c.setMaxAge( 0 );
//将cookie添加到响应中,发送给浏览器
response.addCookie( c );
out.write( "成功删除了名称为cart的cookie..." );

5、Cookie的常用方法

cookie.getName(); // 获取cookie的名字 返回值字符串
cookie.getValue(); // 获取cookie中保存的值
cookie.setValue(); // 设置/修改cookie中保存的值(没有setName方法,因为cookie的名字无法修改)
cookie.setMaxAge(); //设置cookie的最大生存时间
//创建一个Cookie对象,将商品信息保存到cookie中
Cookie cookie = new Cookie( "cart", prod  );
//设置cookie的最大生存时间, **单位:秒**
cookie.setMaxAge( 60*60*24 );
//将cookie对象添加到response响应中
response.addCookie( cookie );
---------------
//实现cookie的共享
/**
     * 1.url地址:http://www.jt.com/user/doLogin?r=0.04360522021726099
     * 2.参数:  {username:_username,password:_password},
     * 3.返回值结果:  SysResult
     *
     * 需求1:  将cookie名称为 "JT_TICKET"数据输出到浏览器中,要求7天超时.
     * 并且实现"jt.com"数据共享
     *
     * Cookie特点:
     *  1.浏览器中只能查看当前网址下的Cookie信息
     *  2.doMain 表示cookie共享的策略
     *    doMain:www.jd.com   当前的Cookie数据只能在当前域名中使用
     *    doMain:.jd.com      当前Cookie是共享的可以在域名为jd.com结尾的域名中共享.
     *
     *  * * */
    @RequestMapping("/doLogin")
    @ResponseBody
    public SysResult doLogin(User user, HttpServletResponse response){

        //完成用户登录操作 之后获取ticket密钥信息
        String ticket = userService.doLogin(user);
        if(StringUtils.isEmpty(ticket)){
            //如果为null,则说明用户名或密码有问题
            return SysResult.fail();
        }

        //1.创建Cookie对象
        Cookie cookie = new Cookie("JT_TICKET",ticket);
        //2.设定cookie存活的时间   value=-1  当用户关闭会话时,cookie删除
        //2.设定cookie存活的时间   value= 0  立即删除cookie
        //2.设定cookie存活的时间   value= >0 设定cookie超时时间
        cookie.setMaxAge(7*24*60*60);
        //3.在jt.com的域名中实现数据共享.
        cookie.setDomain("jt.com");
        cookie.setPath("/"); //一般情况下都是/ 表示/以后的路径都能访问到该cookie
        //4.将数据保存到浏览器中
        response.addCookie(cookie);
        return SysResult.success();
    }

session

获取session对象:

request.getSession() 
// 获取一个session对象;如果在服务器内部有当前浏览器对应的session,则直接返回该session对象;如果没有对应session,则会创建一个新的session对象再返回;

Session是一个域对象,因此session中也提供了存取数据的方法。

session.setAttribute(String attrName, Object attrValue); 
// 往session域中添加一个域属性,属性名只能是字符串类型,属性值可以是任意类型。
session.getAttribute(String attrName);
// 根据属性名获取域中的属性值,返回值是一个Object类型

特征:
(1)生命周期:

**创建session:**第一次调用request.getSession()方法时,会创建一个session对象。(当浏览器在服务器端没有对应的session时,调用request.getSession()方法服务器会创建一个session对象。)

销毁session:

  1. 超时销毁:默认情况下,当超过30分钟没有访问session,session就会超时销毁。(30分钟是默认时间,可以修改,但不推荐修改)

  2. 自杀:调用session的invalidate方法时,会立即销毁session。

  3. 意外身亡:当服务器非正常关闭时(硬件损坏,断电,内存溢出等导致服务器非正常关闭),session会随着服务器的关闭而销毁;

    当服务器正常关闭,在关闭之前,服务器会将内部的session对象序列化保存到服务器的work目录下,变为一个文件。这个过程叫做session的钝化(序列化);再次将服务器启动起来,钝化着的session会再次回到服务器,变为服务器中的对象,这个过程叫做session的活化(反序列化)。

**(2)作用范围:**在一次会话范围内(获取到的都是同一个session对象)

**(3)主要功能:**在整个会话范围内实现数据的共享

获取不到之前的session的问题

session是基于Cookie工作的。

在服务器创建一个session后,会为session分配一个独一无二的编号,称之为session的id,在此次响应时,服务器会将session的id以一个名称为JSESSIONID的cookie发送给浏览器保存到浏览器内部。

由于保存sessionid的cookie默认是会话级别的cookie,在浏览器关闭后,cookie会跟着销毁,sessionid也丢失了。因此下次访问服务器,没有session的id就获取不到之前的session。也获取不到session中的商品信息
解决方法:我们可以创建一个名称为JSESSIONID的cookie,其中保存session的ID,并设置cookie的最大存活时间,让cookie保存到硬盘上(即使浏览器关闭,cookie也不会销毁),这样下次访问服务器时,还可以将sessionid带给服务器,服务器可以通过sessionid获取到之前的session。 从session中获取到商品信息
在这里插入图片描述

事物隔离级别

1、READ UNCOMMITTED(读未提交数据)
安全性最差,可能出现任何事务并发问题(比如脏读、不可以重复读、幻读等)

但性能最好(不使用!!)
2、READ COMMITTED(读已提交数据)(Oracle默认)

安全性较差

性能较好

可以防止脏读,但不能防止不可重复读,也不能防止幻读;

3、REPEATABLE READ(可重复读)(MySQL默认)

安全性较高

性能较差

可以防止脏读不可重复读,但不能防止幻读问题;

4、SERIALIZABLE(串行化)

安全性最高,不会出现任何并发问题,因为它对同一数据的访问是串行的,非并发访问;

性能最差;(不使用!!)

MySQL的默认隔离级别为REPEATABLE READ,即可以防止脏读和不可重复读

mybatis 中的占位符

在mybatis中占位符有两个,分别是 #{} 占位符 和 ${} 占位符:

  • #{}:相当于JDBC中的问号(?)占位符,是为SQL语句中的参数值进行占位,大部分情况下都是使用#{}占位符; 并且当#{}占位符是为字符串或者日期类型的值进行占位时,在参数值传过来替换占位符的同时,会进行转义处理(在字符串或日期类型的值的两边加上单引号)

  • ${}:是为SQL片段进行占位,将传过来的SQL片段直接拼接在${}占位符所在的位置,不会进行任何的转义处理。(由于是直接将参数拼接在SQL语句中,因此可能会引发SQL注入攻击问题)

mybatis foreach

在这里插入图片描述
示例:

<!-- 练习14: 根据员工的id批量删除员工信息
	delete from emp where id in (1,3,5,7)
	collection: 如果传的参数仅仅是一个数组或者List集合, collection可以指定为
		array或list; 如果传的是多个参数,用map封装,collection则指定为map中的key
	open: 指定生成的SQL片段以什么符号开始
	close: 指定生成的SQL片段以什么符号结束
	item: 指定变量接收数组或集合中的元素
	separator: 指定一个间隔符, 在将数组或集合中的每个元素拼接到SQL片段之后, 
		在后面拼接一个间隔符
 -->
<delete id="deleteByIds">
	delete from emp where id in
	<foreach collection="array" open="(" item="id" separator="," close=")">
		#{id}
	</foreach>
</delete>

mybatis 单独实现 数据读取

/** 练习1(快速入门):  查询emp表中的所有员工, 返回一个List<Emp>集合
 * @throws IOException */
@Test
public void findAll() throws IOException {
	//1.读取mybatis的核心配置文件(mybatis-config.xml)
	InputStream in = Resources
			.getResourceAsStream("mybatis-config.xml");
	//2.通过配置信息获取一个SqlSessionFactory工厂对象
	SqlSessionFactory fac = 
			new SqlSessionFactoryBuilder().build( in );
	//3.通过工厂获取一个SqlSession对象
	SqlSession session = fac.openSession();
	//4.通过namespace+id找到要执行的sql语句并执行sql语句
	List<Emp> list = session
			.selectList("EmpMapper.findAll");
	//5.输出结果
	for(Emp e : list) {
		System.out.println( e );
	}
}
--------------------------
//`mybatis-config文件详细配置如下:`
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
<!-- MyBatis的全局配置文件 -->
<configuration >
	<!-- 1.配置环境,可配置多个环境(比如:develop开发、test测试) -->
	<environments default="develop">
		<environment id="develop">
			
			<!-- 1.1.配置事务管理方式:JDBC/MANAGED
			JDBC:将事务交给JDBC管理(推荐)
			MANAGED:自己管理事务
			  -->
			<transactionManager type="JDBC"></transactionManager>
			
			<!-- 1.2.配置数据源,即连接池 JNDI/POOLED/UNPOOLED
				JNDI:已过时
				POOLED:使用连接池(推荐)
				UNPOOLED:不使用连接池
			 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/yonghedb?characterEncoding=utf-8"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 2.导入Mapper配置文件,如果mapper文件有多个,可以通过多个mapper标签导入 -->
	<mappers>
		<mapper resource="EmpMapper.xml"/>
	</mappers>
</configuration>

工厂解耦模式

程序中new对象的方式造成了这种程序之间的依赖程度提升,即提升了程序之间的耦合性。

使用工厂+配置文件+接口解耦代码如下:

package com.tedu.factory;

import java.io.InputStream;
import java.util.Properties;
/**
 * ---------------------------------------------------------
 * Bean: 可重用组件(计算机英语)
 * JavaBean:使用Java语言编写的可重用组件,例如:service层、dao层等
 * JavaBean:通常分为业务Bean和实体Bean
 * 		业务Bean:处理业务逻辑,service层、dao层
 * 		实体Bean:封装数据,例如,为了封装员工信息而编写的Emp实体类.
 * ---------------------------------------------------------
 * 解除耦合:
 * (1)需要提供配置文件,在配置文件中配置service和dao的实现类
 * 		配置内容为:唯一标识=实现类的全限定类名(key=value结构)
 * (2)通过工厂读取配置文件中配置的全限定类名,利用反射创建对象。
 * 		xml配置文件、properties配置文件
 */
public class BeanFactory {
	//声明一个Properties对象,在静态代码块中对其进行初始化
	private static Properties prop;
	static {
		try {
			//为prop进行实例化
			prop = new Properties();
			//获取配置文件的流对象
			InputStream in = BeanFactory.class.getClassLoader()
					.getResourceAsStream("config.properties");
			//将配置文件中的内容读取到Properties对象中
			prop.load( in );
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("初始化Properties对象失败!");
		}
	}
	
	/**
	 * 根据config.xml文件中的key获取对应class类的实例
	 * @param key 
	 * @return
	 */
	public static Object getBean(String key) {
		Object bean = null;
		try {
			String className = prop.getProperty( key );
			bean = Class.forName(className).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return bean;
	}
}

在源码目录下创建一个config.properties文件,文件内容配置如下:

EmpService=com.tedu.service.EmpServiceImpl
EmpDao=com.tedu.dao.EmpDaoImpl

将EmpController类中通过 “new对象的形式获取了EmpService接口子类的实例” 以及在EmpServiceImpl类中通过 “new对象的形式获取了EmpDao接口子类的实例” 改为使用BeanFactory工厂获取Service和Dao层的实例。如下

 获取Service接口的子类实例
 * ——这里使用new对象的方式造成了程序之间的耦合性提升 */
//private EmpService service = new EmpServiceImpl();
private EmpService service = (EmpService)BeanFactory.getBean("EmpService");
/* 获取Dao接口的子类实例
 * ——这里使用new对象的方式造成了程序之间的耦合性提升 */
//private EmpDao dao = new EmpDaoImpl();
private EmpDao dao = (EmpDao)BeanFactory.getBean( "EmpDao" );

spring ioc 控制反转

把创建对象的权利交给框架。也就是指将对象的创建、对象的存储、对象的管理交给了spring容器。
核心配置文件:创建xml 文件 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- 将EmpService接口的实现类的实例交给spring创建 -->
    <bean id="empService" class="com.tedu.service.EmpServiceImpl"></bean>
	
	<!-- 将EmpDao接口的实现类的实例交给spring创建 -->
    <bean id="empDao" class="com.tedu.dao.EmpDaoImpl"></bean>
	
</beans>

通过下面代码 获取bean

public class TestSpring {
	/**
	 * 使用spring的IOC解决程序中的耦合问题
	 */
	@Test
	public void testIOC() {
		//获取spring的核心容器对象
		ApplicationContext ac = 
				new ClassPathXmlApplicationContext(
						"applicationContext.xml");
		//通过spring的核心容器获取EmpService接口的子类实例
		EmpService service = (EmpService) ac.getBean("empService");
		EmpDao dao = (EmpDao) ac.getBean("empDao");
		System.out.println( service );
		System.out.println( dao );
	}
}

单实例 多实例

在Spring容器中管理的Bean对象的作用域,可以通过scope属性或用相关注解指定其作用域。
在这里插入图片描述

spring 执行流程

在这里插入图片描述
(1).用户发送请求 至 前端控制器(DispatcherServlet);
提示:DispatcherServlet的作用:接收请求,调用其它组件处理请求,响应结果,相当于转发器、中央处理器,是整个流程控制的中心
(2).前端控制器(DispatcherServlet)收到请求后调用处理器映射器(HandlerMapping)
处理器映射器(HandlerMapping)找到具体的Controller(可以根据xml配置、注解进行查找),并将Controller返回给DispatcherServlet;
(3).前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)。处理器适配器经过适配调用具体的Controller;(Controller–> service --> Dao --> 数据库)
Controller执行完成后返回ModelAndView,
提示:Model(模型数据,即Controller处理的结果,Map) View(逻辑视图名,即负责展示结果的JSP页面的名字)
处理器适配器(HandlerAdapter)将controller执行的结果(ModelAndView)返回给前端控制器(DispatcherServlet);
(4).前端控制器(DispatcherServlet)将执行的结果(ModelAndView)传给视图解析器(ViewReslover)
视图解析器(ViewReslover)根据View(逻辑视图名)解析后返回具体JSP页面
(5).前端控制器(DispatcherServlet)根据Model对View进行渲染(即将模型数据填充至视图中);
前端控制器(DispatcherServlet)将填充了数据的网页响应给用户。

mvc 的请求转发 和重定向

/* 测试请求转发(forward) */
@RequestMapping("testForward")
public String testForward(){
	System.out.println("测试请求转发(forward)...");
	return "forward:hello";
}
/* 测试请求重定向(redirect) */
@RequestMapping("testRedirect")
public String testRedirect(){
	System.out.println("测试请求重定向(redirect)...");
	return "redirect:hello";
}

springboot 中优化掉了web.xml 定义web.xml的方法

实现 WebMvcConfigurer 接口

package com.jt.handler;

import com.jt.pojo.User;
import com.jt.util.CookieUtil;
import com.jt.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import redis.clients.jedis.JedisCluster;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//拦截器的类(业务)      拦截器的配置文件(拦截什么请求)
@Component
public class UserInterceptor implements HandlerInterceptor {

    private static final String TICKET = "JT_TICKET";
    private static final String JTUSER = "JT_USER";
    @Autowired
    private JedisCluster jedisCluster;

    /**
     *  实现pre的方法
     *  返回值说明:
     *          return  false 表示拦截 需要配合重定向一齐使用
     *          return  ture  表示放行
     *  需求1: 如果用户没有登录,则重定向到系统登录页面
     *  判断条件: 如何判断用户是否登录.  1.检查Cookie中是否有记录   2.Redis中是否有记录.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Cookie cookie = CookieUtil.getCookieByName(request, TICKET);
        if(cookie != null){ //不为null.则表示用户可能登录.
            String ticket = cookie.getValue(); //cookie中存储的是Redis的key ticket密钥
            if(jedisCluster.exists(ticket)){

                //如果redis中的数据存在,则说明用户已经登录.可以放行请求.
                //获取真实的用户信息
                String userJSON = jedisCluster.get(ticket);
                //将json转化为对象
                User user = ObjectMapperUtil.toObject(userJSON, User.class);
                request.setAttribute(JTUSER, user);
                return true;
            }else{
                //Cookie中的记录与Redis中的记录不一致.应该删除Cookie中的数据.
                CookieUtil.deleteCookie(TICKET, "/", "jt.com",response);
            }
       }

        response.sendRedirect("/user/login.html");
        return false;   //表示拦截
    }
}

springboot 定义拦截器

有三种 拦截器 分别为 preHandle postHandle afterHandle 拦截的示意图
在这里插入图片描述

  1. 首先在xml中 编辑拦截器配置文件
  2. 编辑拦截器配置文件
package com.jt.handler;

import com.jt.pojo.User;
import com.jt.util.CookieUtil;
import com.jt.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import redis.clients.jedis.JedisCluster;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//拦截器的类(业务)      拦截器的配置文件(拦截什么请求)
@Component
public class UserInterceptor implements HandlerInterceptor {

    private static final String TICKET = "JT_TICKET";
    private static final String JTUSER = "JT_USER";
    @Autowired
    private JedisCluster jedisCluster;

    /**
     *  实现pre的方法
     *  返回值说明:
     *          return  false 表示拦截 需要配合重定向一齐使用
     *          return  ture  表示放行
     *  需求1: 如果用户没有登录,则重定向到系统登录页面
     *  判断条件: 如何判断用户是否登录.  1.检查Cookie中是否有记录   2.Redis中是否有记录.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Cookie cookie = CookieUtil.getCookieByName(request, TICKET);
        if(cookie != null){ //不为null.则表示用户可能登录.
            String ticket = cookie.getValue(); //cookie中存储的是Redis的key ticket密钥
            if(jedisCluster.exists(ticket)){
                return true;
            }else{
                //Cookie中的记录与Redis中的记录不一致.应该删除Cookie中的数据.
                CookieUtil.deleteCookie(TICKET, "/", "jt.com",response);
            }
       }

        response.sendRedirect("/user/login.html");
        return false;   //表示拦截
    }
}

ThreadLocal 介绍

说明:如果利用Request对象的方式进行数据的传参,一般只能在Controller中进行动态的数据接收.
如果在业务执行过程中需要该数据,则通过参数的形式继续向下传递.导致接口方法中的参数个数较多.
虽然该写法没有任何的问题. 该操作是否可以优化???

ThreadLocal

名字: 本地线程变量
作用: 在当前线程内,实现数据的共享.
在这里插入图片描述

编辑 ThreadLocal 工具 API

package com.jt.util;

import com.jt.pojo.User;

public class UserThreadLocal {

    //1.定义本地线程变量!!!!!
    private static ThreadLocal<User> threadLocal = new ThreadLocal<>();
                   //ThreadLocal<Map>
    //2.定义数据新增的方法
    public static void set(User user){

        threadLocal.set(user);
    }

    //3.获取数据
    public static User get(){

        return threadLocal.get();
    }

    //4.移除方法 使用threadLocal时切记将数据移除.否则极端条件下,容易产出内存泄露的问题
    public static void remove(){

        threadLocal.remove();
    }
	 //实现数据的移除
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        UserThreadLocal.remove();
    }
}

将数据保存到 ThreadLocal中

在这里插入图片描述

参数接受 说明

js表单数据
在这里插入图片描述
接受的 pojo
在这里插入图片描述
用 order接收数据

  @RequestMapping("/submit")
    @ResponseBody
    public SysResult submit(Order order){

        //利用拦截器的方式赋值.
        Long userId = UserThreadLocal.get().getId();
        order.setUserId(userId);
        //1.完成订单入库,并且返回orderId
        String orderId = orderService.saveOrder(order);
        return SysResult.success(orderId);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值