欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA个人学习笔记(不断更新)

程序员文章站 2022-03-07 20:01:13
...

JAVAWEB

request.getSession() 
实现了:
如果request有JssesionId这个cookie则根据Jssession获得session
如果没有,创建一个session并且 response返回的时候会返回JssesionId
每一个session的唯一标志就是JssesionId//个人理解

常用API

方法名 参数 返回值 备注
Arrays.asList(Object…obj); 三个相同的类型数据 List 三个相同的类型数据
selectByPrimaryKey(Integer) 主键 Object 通用Mapper方法
StringUtils.join(List,",") 数组,分隔符 String 工具类,将字符串数,用分隔符分割,拼接成字符串
str.subString(startIndex.endIndex) 不解释,看方法名就懂

中间件

rabbitmq:

JAVA个人学习笔记(不断更新)

后端

java

Stream流:https://www.cnblogs.com/heliusKing/p/10990221.html

多线程

线程工具类:
public class ThreadUtils {
		private static final ExecutorService es = Executors.newFixedThreadPool(10);//创建线程池
		public static void execute(Runnable runnable) {//接收一个runnable
		es.submit(runnable);//开启一个线程
	}
}
	 方法调用如下:
	 ThreadUtils.execute(() -> {           
                createHtml(spuId);
        });//lambada表达式,代表新建了一个继承了Runnable的子类对象,里面重写的方法存放的内容就是createHtml(spuId);
	Runnable的源码:
  public interface Runnable
{
 
    public abstract void run();
}
	//其它以后复习	

IO流

踩到的坑:判断字符串是否相等

StringA==StringB错误!

a==b a.equals(b)
a和b为基础数据类型: 比较值 不可用
a和b为对象: 比较地址 根据a重写的方法判断
包装类和String待补充

ThereadLocal :

该类创建的对象是线程共有的(一般放在static final中)

但是该类的属性ThreadLocalMap中的元素不是线程共有的 是每一个线程独一份的

set和get的时候就是为这个属性添加字段(事实上是个数组)

一个项目中可以有多个ThreadLocal的实例,每个实例存放同一种类型在不同线程中的数据

杂七杂八

日志操作

private static final Logger LOGGER=LoggerFactory.getLogger(GoodsHtmlService.class);
LOGGER.error("页面静态化出错: {}" + e,spuId);//至于怎么讲日志输出到控制台 以后再研究

关于RS256算法:公钥加密,私钥解密

? 私钥加密,公钥验证:

? A根据明文和私钥生成signed。生成数据:明文.signed。发送数据到B。

? B用公钥解析数据,没有出错,则代表是A过来的,错了则不是。

关于JWT:是一个token,token的生成可以支持多种算法。RS256是其中一种。内部怎么支持的我们不关心,只关心怎么使用。

cors跨域问题:

? ajax请求 : 返回数据时要求一级二级域名都相同

? cookie: 要求domain的一级域名相同

框架相关

Spring

对象创建过程

Class clazz=Class.forName(classStr);
Object obj=clazz.newInstance();

obj参照@Autowired 从容器中取得对应的对象 确认执行哪个set方法 执行set方法给obj赋值

obj执行@PostConstruct修饰的方法

最后封装到容器中去(over)

spring mvc

JAVA个人学习笔记(不断更新)

8 9 视图解析器:只是将返回的String类型的字符串解析成一个地址,并且返回。

10:这个地方才是对数据的渲染

1 2 3 4 5 6 7:这里都可以看成是在执行controller的内容

Mybatis

? 通用Mapper的 @Transient会在查询时忽略该字段。因为查询时,会要求数据库对每一个值都赋值,如果不忽略,数据库没有给该字段赋值,则报错。

slect(record) 根据某些条件查询,比如说name=“zhangsan”,条件之间默认是并集

selectByPrimaryKey(id) 根据主键查询,返回一个

selectByExample 模糊查询,排序等,用Example设置条件

Mybatis启动原理:
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionfactory=sqlSessionFactioryBuilder.build(inputstream)

sqlSessionFactory:负责从流(配置类)中获得信息:(连接信息,map类名+方法名,以及其所对应的sql语句和封装到的实体类的全限定类名)组成下面这样的结构

JAVA个人学习笔记(不断更新)

这些信息会封装到Configuration然后往下传

Configuration
JAVA个人学习笔记(不断更新)

这里将每个方法的K V结构封装起来 存入到mappers中


SqlSession sqlSession=SqlSessionFactory.openSession;
UserMapper mapper=sqlSession.getMapper(IUserDao.class);//返回一个代理对象。这个mapper是动态的代理,当执行这个mapper里的方法的时候,会进行方法加强.具体流程如下:
User user = mapper.selectAll();
1、获取连接
2、拼接类名和方法名作为Key检索config中的Map获得Sql语句以及返回的参数类型,作为返回值。

关于动态代理,生成代理对象的方法

return (T) Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
        new Class[]{daoInterfaceClass},new MapperProxy(cfg.getMappers(),connection));
        //三个参数分别是:1、要加强的对象的类加载器 2、要加强对象的所有接口的字节码数组 3、这个对象中的invoke方法即是加强的方法,这里也可以用lambda表达式。这个对象实现了InvocationHandler.
        public class MapperProxy implements InvocationHandler {

    //map的key是全限定类名+方法名
    private Map<String,Mapper> mappers;
    public Connection conn;

    public MapperProxy(Map<String,Mapper> mappers,Connection conn){
        this.mappers = mappers;
        this.conn = conn;
    }

    /**
     * 用于对方法进行增强的,我们的增强其实就是调用selectList方法
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //1.获取方法名
        String methodName = method.getName();
        //2.获取方法所在类的名称
        String className = method.getDeclaringClass().getName();
        //3.组合key
        String key = className+"."+methodName;
        //4.获取mappers中的Mapper对象
        Mapper mapper = mappers.get(key);
        //5.判断是否有mapper
        if(mapper == null){
            throw new IllegalArgumentException("传入的参数有误");
        }
        //6.调用工具类执行查询所有
        return new Executor().selectList(mapper,conn);
    }
}
        

综上所述

Sqlsessionfactory的作用

1、获得以下几种信息:(这些信息都是来源于Mybaits的配置文件)

? 1、配置Mapper所在的包 (封装map)

? 2、连接

2、创建sqlsession

sqlsession的作用:生成代理对象

在Mybatis中通过配置一个xml来指定:

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

    <!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
    <typeAliases>
        <package name="com.itheima.domain"></package>
    </typeAliases>

    <!--配置环境-->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务 -->
            <transactionManager type="JDBC"></transactionManager>

            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置映射文件的位置 -->
    <mappers>
        <package name="com.itheima.dao"></package>
    </mappers>
</configuration>

而当其结合Spring 的时候

在Spring配置文件中配置SqlsessionFactory的数据源。

配置文件的位置怎么传过去的呢?我认为Spring中的SqlsessionFactory的实现自动会去读取mapperScanner的信息,然后获取其中的对象。

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driver}"/>
    <property name="jdbcUrl" value="${jdbc.url}"/>
    <property name="user" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
<!-- 把交给IOC管理 SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!-- 传入PageHelper的插件 -->
    <property name="plugins">
        <array>
            <!-- 传入插件的对象 -->
            <bean class="com.github.pagehelper.PageInterceptor">
                <property name="properties">
                    <props>
                        <prop key="helperDialect">oracle</prop>
                        <prop key="reasonable">true</prop>
                    </props>
                </property>
            </bean>
        </array>
    </property>
</bean>
<!-- 扫描dao接口 -->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.itheima.ssm.dao"/>
</bean>

而在springboot中

? 1、SqlsessionFactory自动配置了,

? 2、DateSource自动配置了,但是属性值需要我们导入。

? 3、至于Mapper,可以在Mapper上添加mapper类,也可以在引导类上配置@MapperScan

关于sqlsession的线程安全问题:sqlsession是线程不安全的,所以用sqlsessionFactory,每一个线程访问,就给一个sqlsession。

?

SpringBoot

SpringBoot配置:

注入

String或int等基本数据类型的注入:

配置类:(通过这种方式写入到ioc容器)

@ConfigurationProperties(prefix = "spring.sms")	//在这个类中用getter和setter
public class SmsProperties {
    private String accessKeyId;
    private String accessKeySecret;
    private String signName;
    private String verifyCodeTemplate;
    //getter和setter省略
    }

属性导入类:(从ioc拿出来注入到属性导入类中)

@Component
@EnableConfigurationProperties(SmsProperties.class)	//在这个类中用Autowired导入配置类的属性
public class SmsUtils {
    @Autowired
    private SmsProperties prop;
}
//*想要获得注入属性后的SmsUtils实例,必须使用Bean注入:
@Autowired
    private SmsUtils smsUtils ;

对象的注入:(代更新)

@Bean

@Autowired

如果想要自定义springmvc的拦截器
1、定义一个类继承WebMvcConfigurer并重写其中的addInterceptors方法 并添加@Configuration

Result风格:

https://www.jianshu.com/p/91600da4df95

JAVA个人学习笔记(不断更新)

1、后台要指定请求方式

2、可以用?id=1&username=aa拼接参数传递或者可以/1/aa传递 二者只能选一种,也可以传递对象,这个看情况。

@GetMapping("/check/{data}/{type}")
public ResponseEntity<Boolean> checkUserData(
        @PathVariable("data") String data,
        @PathVariable(value = "type" ,required = false) Integer type)

@GetMapping("check")
public ResponseEntity<Void> register(@RequestParam("data") String data,
@RequestParam("type") Integer type)

@PostConstruct 在Bean创建之后执行

springBoot中的拦截器和过滤器:

过滤器实现Filter接口然后注册到容器中 两种注册方式都可以 (在Zuul中一般使用ZuulFilter, 跨域问题使用CorsFilter 方法注入 使用带参构造

拦截器先定义一个拦截器继承HandlerInterceptorAdapter ,然后定义一个类继承WebMvcConfigurer,重写addInterceptors方法写入

@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class MvcConfig implements WebMvcConfigurer {
    @Autowired
    private JwtProperties jwtProperties;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor(jwtProperties)).addPathPatterns("/**");
    }
}//这里的JwtProperties在注册拦截器的时候才使用

SpringData JPA

redis:

1、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、配置

spring:
redis:
host: 192.168.64.129

3、使用

private StringRedisTemplate redisTemplate;//创建模板,String代表序列化成String类型的数据
BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(key);//获得一条记录,如果没有,则创建May<String,Map<Object,Object>>
hashOps.values();//这些方法可以顾名思义,但是要记住,hashOps所有方法都是操作hashOps内部的
hashOps.haskey();

?

前端

JAVASCRIPT

? elasticsearch安装:https://blog.csdn.net/qq_43636087/article/details/103439087

解构表达式:

? 即是将对象用一个定义好的模板接收,然后对象里的元素会被拆分出来

对象:
const person = {
name:"jack",
age:21,
language: ['java','js','css']
} 

// 解构表达式获取值
const {name,age,language} = person;//前半段就是接收的模板
// 打印
console.log(name);
console.log(age);
console.log(language);

数组:
let arr = [1,2,3]
const [x,y,z] = arr;// x,y,z将与arr中的每个位置对应来取值
// 然后打印
console.log(x,y,z);
在函数的参数中使用:
1、
const person = {
	name:"jack",
	age:21,
	language: ['java','js','css']
} 
function hello(person) {
	console.log("hello," + person.name)
}
var hi = ({name}) => console.log("hello," + name);//用解构模板接受了,函数中可以使用
2、
 ly.http.post("/search/page", this.search).then({data})=>{
                    this.goodsList=data.items;
            });//这里promise对象最后会调用then这个回调函数,然后传入resp(响应对象),这里用{data}接收,获得里面的data

this.filters.find(f=>f.k==="品牌";});///filters是一个数组,filter是回调函数,f代表集合中每个元素,f从filters集合中获得k属性为品牌的对象。
const keys = Object.keys(this.search.filter);
return this.filters.filter(f => !keys.includes(f.k));//filters是一个数组,filter是回调函数,f代表集合中每个元素,把filters数组中的符合!keys.includes(f.k)的f元素抽取出来,组成一个新的集合
list.push//给集合赋值。
javascript给Map加属性:
	obj["属性名"]=“属性值”,
	obj.属性名=属性值
const index = Object.values(this.indexes).join("_");//获得index的value值组成的数组,并将其拼接成字符串 如果this.indexes的key是数组的话,那么新组成的数组会按照key的从小到大的顺序排列
const object = {5:35,7:12,8:12,3:80};
Object.values(object) 的结果是 [80, 35, 12, 12]

在vue中:发送ajax请求后,可以指定transformResponse参数,处理后台传过来的数据
 ly.http.post("/order/order", this.order,{
                        transformResponse: [
                            function(data){
                                return data;
                            }
                        ]
                    }).then
在es6中 Object.assign(A,B,C);将B,C对象的属性 拼接到A后面去
 范例:
 		Object.assign(this.order, obj, {
        orderDetails,
        totalPay: this.totalPay,
        actualPay: this.actualPay,
        });
es6中this指向:<http://www.imooc.com/article/288214?block_id=tuijian_wz#comment
checkbox:
	在原生vue中:checked属性表示是否绑定
	在vue中:<input type="checkbox" v-model="selected" name="" :value="cart" />  value的数据是否在v-model中 如果在 就选中 如果不在 就不选中 
        
对数组arrays遍历并依次用回调函数处理其元素,其中,前一个元素是上一次运算的结果,如果是第一次运算,则是该函数的第二个参数
   arrays.reduce((c1, c2) => c1 + c2.price * c2.num, 0);


? webpack:类似于tomcat

? npm: 类似于maven

? webpack+nom:类似于maven集成tomcat

消息队列

? https://segmentfault.com/a/1190000013039660
JAVA个人学习笔记(不断更新)

JAVA个人学习笔记(不断更新)

关于回调函数和promise以及异步:

1、[添加链接描述](https://blog.csdn.net/liwusen/article/details/54142748?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task)


2、[添加链接描述](https://www.baidu.com/s?wd=js%E5%BC%82%E6%AD%A5%E6%93%8D%E4%BD%9C&rsv_spt=1&rsv_iqid=0xee8725b6002268ec&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&oq=js%25E5%25BC%2582%25E6%25AD%25A5&inputT=6082&rsv_t=33faFD7XzbzseJE4NT49JI5KCESV/CzErUHlFudWJyzhY/lcqW7NXcbExCSTLoJ2g4m4&rsv_sug3=16&rsv_sug1=14&rsv_sug7=100&rsv_pq=b25f4dd7000251fc&rsv_sug2=0&rsv_sug4=6201)
promise:
var p=new Promise(function(resolved))
//在这里进行处理。也许可以使用ajax
setTimeout(function(){
   var result=10*5;
   if(result===50){
      resolve(50);							//异步成功并返回数据
   }else{
     reject(new Error('Bad Math'));			  //异步失败
  }
},1000);
});
p.then(function(result){
    console.log('Resolve with a values of %d',result);
});
p.catch(function(){
   console.error('Something went wrong');
});

在promise里面定义代码;p.then(“成功后的回调函数”).catch(“失败后的回调函数”);

promise使用时直接调用里面的函数

async await
async function f() {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => resolve('done!'), 1000)
    })
    let result = await promise // 直到promise返回一个resolve值(*)
    alert(result) // 'done!' 
}
f()

async 返回一个promise,async里面可以用await,代表执行完这个promise才能继续执行
this: