0%

SSM框架-mybites框架

配置

步骤:

  1. 创建maven工程并且引入坐标

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>x.x.x</version>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
    </dependency>
    <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
    </dependency>
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11 </version>
    </dependency>
  1. 创建实体类和dao的接口

  2. 创建Mybatis的主配置文件(SqlMapConfig.xml)

    1
    2
    @Select("select * from user")
    public List<User> getAll();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/><!--通过xml的方式-->
<mapper class="org.mybatis.example.BlogDao"/><!--通过注解的方式,class为注解的类-->
</mappers>
</configuration>
  1. 创建映射配置文件(IUserDao.xml)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.mybatis.example.BlogMapper">
    <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
    </select>
    </mapper>

注意事项:

  1. 创建映射配置文件时,文件的目录结构要和dao层的目录结构相同,方便mybatis的自动寻找。
  2. 映射配置文件的mapper标签namespace属性取值dao接口的权限定类名
  3. 映射配置文件的操作配置(select),id属性取值dao接口类的方法名

使用

1
2
3
4
5
6
7
8
9
10
11
12
  // 配置文件
InputStream in =Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建SqlSessionFactory 对象 并且得到session对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
// 通过session对象获取到dao接口的动态代理对象
IUser userimpl = sqlSession.getMapper(IUser.class);
// 使用动态代理类得到数据
List<user> all = userimpl.getAll();
// 关闭资源
sqlSession.close();
in.close();

读取配置文件

  1. 使用类加载器读取,他只能读取类路径下的配置文件。
  2. 使用ServletContext对象的getRealPath()方法读取配置文件。

mybatis使用代理dao的方式实现的增删改查方式

  1. 创建代理对象(可以使用dom4j的技术来解析xml文件)

    连接数据库的信息(xml文件中)connection

    mapper映射配置信息

    通过mapper配置信息找到所对应的sql语句 和 封装的实体类限定名 prepareStatement

  1. 使用代理对象调用增删改查方法

——————————东软

dispatchServlet 是 springmvc的核心拦截器,拦截所有的请求

handlerMapping 相当于MAP , key 为 url ,value 为 Handler

  • Handler 里面有类名,方法名,参数列表

handlerMapping 将 Handler 返回给 dispatchServlet

dispatchServlet 将获取到的对象给 HandlerAdapter

HandlerAdapter 解析 Handler 里面的类名,方法名,参数列表 并进行调用

HandlerAdapter 调用完的返回值给 dispatchServlet

dispatchServlet 将返回值 给 视图解析器

视图解析器 通过返回值找到相应的页面进行转发。

handlerMapping

注意 :需要配置handlerMapping的配置文件 namespace 或者(servlet名字-service) WEB-INF目录下面

1
2
3
4
5
6
7
8
9
10
1.开启注解驱动
<mvc:annotation-driven></mvc:annotation-driven>
2、包扫瞄(只有包里面加了@Controller注解的类才会被扫描到,方法上加上@RequestMapping注解)
<context:component-scan base-package="被扫描的包名"></context:component-scan>
3、配置视图解析器
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"> </property>
<property name="prefix" value="/WEB-INF/pages"></property>
<property name="suffix" value=".jsp"></property>
</bean>

向作用域里放入变量

1
2
3
4
5
6
7
8
// 1、使用HttpServletRequest
HttpServletRequest.setAttribute(key,value)
// 2、使用ModalMap
ModalMap.setAttribute(key,value)
//3、使用ModalAndView,需要先new一个对象 并且返回值改变为ModalAndView
ModalAndView modalAndView = new ModalAndView("abcd") // abcd 是js页面
modalAndView.addObject(key,value)

使用springmvc 重定向 return “redirect:xxx”

AJAX

使用了前后端分离,就不能进行转发和重定向了,应该向前台发送json或者xml来传送字符流。

可以使用fastJson来进行对象与json之间的转换。

使用 JSONObject.toJSONString()

如果想直接返回json数组,而不想转发或者重定向到jsp页面上。可以使用@ResponseBody注解或者使用response.getWriter().write(json字符串)

前后端分离会产生跨域请求问题:解决方法(使用filter)filter所在包org.catalina.filters.CorsFilter

VUEJS

vuejs是分区域进行控制的,可以绑定数据

1
var Vue =   new VUE({“el”:"#app","data":{"abcd":"123456"})

数据使用

使用for循环或if 要在标签里面写,与jstl不同,jstl是进行包裹。

1
2
3
<tr v-for="student in list">
<td>{{student.name}}</td>
</tr>

使用v-model进行双向绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// @click 代表使用vue里面的方法,如果使用vue作用域中的内容,则不再需要{{}} eg:@click=del(student.id)
var Vue = new VUE({
“el”:"#app",
"data":{
"abcd":"123456",
"student":{
"name":"",
"age":"",
}
},
"methods":{
"submit":function(){

}
}
)

数据库

模糊查询 添加条件 用concat函数进行字符串拼接

IOC控制反转 使用setting注入和构造注入,建造xml文件,每一个对象是一个bean (要有id 和 class)

1
2
3
4
5
6
7
8
9
10
11
12
<bean id="i3" class="com.neuedu.test.I3">
<!-- setter注入,条用set方法为私有属性赋值 -->
<!-- 注意name不是属性的名字,是setter方法去掉set首字母大写 与el表达式相同-->
<property name="name" value="abc"></property>
<!-- 构造方法给私有属性赋值-->
<constructor name="name" value="abc"></constructor>
</bean>
<bean id="mainBoard" class="com.neuedu.test.MainBoard">
<!-- 如果属性是一个对象的话,value改成ref -->
<property name="cpu" ref="i3"></property>

</bean>

使用配置文件实现工厂模式

导包 spring-context (applicationContext.xml 是写bean的xml,名字随便取)

1
2
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml")
MainBoard mainBoard = (MainBoard)context.getBean('mainBoard')

使用spring的IOC(控制反转)

1
<context:component-scan base-package="com.neuedu.test" ></context:component-scan>

类上添加@Component @Repository @Service @Controller 这四种注解的其中一种都能被扫描进去

依赖的属性要写上@Autowired @Resource 注解

main方法无法提前解析配置文件,所以只能使用JUNIT进行测试。还要导入spring的测试包。spring testContex framework, 而且需要在测试类上加上@RunWith(SpringJUnit4ClassRunner.class) 为了告诉启动时加载xml配置文件。@contextConfiguration(locations=”classpath:applicationContext.xml”) 为了告诉配置文件在哪里。

监听器(可以实现服务器启动解析配置文件)需要在web.xml文件中配置listener节点

创建过程 实现 listener接口

​ web.xml中配置listener(org.springframework.web.context.ContextLoaderListener)

​ 还要配置一个参数告诉监听器配置文件是哪一个。

1
2
3
4
5
6
7
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicatinContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

stringUtils类可是判断是否字符串为空,需要导包 org.apache.commons.lang3.StringUtils

YML 语言

​ key: value格式(value前必须有空格,可以有多个,不能用tab键替代)

​ 大小写敏感

​ 字符串默认不需要使用引号,单引号和双引号的区别是单引号不支持转移字符

​ 注释方式:#

YML支持的三种数据类型

​ 字面量:直接量,单个不能被拆分的值(数字、字符串、布尔)

​ 对象:键值对形式存在

1
2
3
4
5
6
#对象的写法
friend:
name: lisi
sex:
#或者
friend: {name: lisi,sex: }

​ 数组:字面量/对象的组合

1
2
3
4
5
6
7
#数组的写法
pets:
- 小狗
- 小猫
- 小猪
# 或者
pets: [小狗,小猫,小猪]

Value注入:${字面量}、${配置文件中取值}、#{spEL表达式}

1
2
3
<bean id="Person">
<property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/ #{SpEL}"> </property>
</bean>

React、mobx之间的关系

React和mobx之间相辅相成,react将应用状态转化为可渲染的组件树进行视图的更新,mobx用来存储和更新应用状态。

mobx的基本使用

mobx的流程

1521798430-5a42021889036_articlex

更简单的来讲

2784418971-595ed7833ff78_articlex

​ Mobx中有三个核心概念,observable、observer、action。(为了简单没有涉及到computed等概)

  • observable:通过observable(state)定义组件的状态,包装后的状态是一个可观察数据(Observable Data).

  • observer:通过observer(ReactComponent)定义组件。

  • action:通过action来修改状态。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // 通过 observable 定义组件的状态
    const user = mobx.observable({
    name: "Jay",
    age: 22
    })

    // 通过 action 定义如何修改组件的状态
    const changeName = mobx.action(name => user.name = name)
    const changeAge = mobx.action(age => user.age = age)

    // 通过 observer 定义 ReactComponent 组件。
    const Hello = mobxReact.observer(class Hello extends React.Component {
    componentDidMount(){
    // 视图层通过事件触发 action
    changeName('Wang') // render Wang
    }

    render() {
    // 渲染
    console.log('render',user.name);
    return <div>Hello,{user.name}!</div>
    }
    })

    ReactDOM.render(<Hello />, document.getElementById('mount'));

    // 非视图层事件触发,外部直接触发 action
    changeName('Wang2')// render Wang2
    // 重点:没有触发重新渲染
    // 原因:Hello 组件并没有用到 `user.age` 这个可观察数据
    changeAge('18') // no console

    observable

    可观察数据(Observable Data),可观察数据就是观察到数据的读取、写入,并进行拦截。

    Mobx提供了observable接口来定义可观察数据。定义的可观察数据,通常也是组件的状态。该方法接受一个参数,参数可以是原始数据类型、普通Object、Array、或者ES6的Map类型。返回一个observable类型的参数。

    1
    2
    Array.isArray(mobx.observable([1,2,3])) === false //true
    mobx.isObservale(mobx.observable([1,2,3])) === true //true

    注意,数组经过observable包装后,就不是Array类型了,而是Mobx定义的一个特殊observable类型。

    虽然数据类型不一样,但是使用方式基本和原来一致(原始数据类型除外)

    1
    2
    3
    4
    5
    6
    7
    const observableArr = mobx.observable([1,2,3]);
    const observableObj = mobx.observable({name: 'Jay'});
    const observableMap = mobx.observable(new Map([['name','Wang']]));

    console.log(observableArr[0]) // 1
    console.log(observableObj.name) // Jay
    console.log(observableMap.get('name')) // wang

    可观察数据类型的原理是,在读取数据时,通过getter来拦截,在写入数据时,通过setter来拦截

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Object.defineProperty(o,key,{
    get: function(){
    // 收集依赖的组件
    return value;
    },
    set: function(newValue){
    // 通知依赖的组件更新
    value = newValue
    },
    });

    在可观察数据被组件读取时,Mobx会进行拦截,并记录该组件和可观察数据的依赖关系。在可观察数据被写入时,Mobx也会进行拦截,并通知依赖它的组件重新渲染。

    observer

    observer接收一个React组件作为参数,并将其转变为响应式(Reactive)组件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 普通组件
    const Hello = mobxReact.observer(class Hello extends React.Component{
    render(){
    return <div>Hello,{user.name}!</div>
    }
    })
    // 函数组件
    const Hello = mobxReact.observer(()=>{
    <div>Hello,{user.name}!</div>
    })

    响应式组件,即当且仅当组件依赖的可观察数据发生改变时,组件才回自动响应,并重新渲染。

    action

    在Mobx中是可以直接修改可观察数据,来进行更新组件的,但是不建议这样做。如果在任何地方都修改可观察数据,将导致野蛮状态难以管理。

    所有对可观察数据的修改,都可以在action中进行。

    1
    const changeName = mobx.action(name => user.name = name)

    使用Mobx可以将组件状态定义在组件外部,这样,组件逻辑和组件视图很容易分离。兄弟组件之间的状态也很容易同步。另外,也不在需要手动使用shouldComponentUpdate进行性能优化了。

javaweb

web服务器 (tomcat)用来接收客户发来的请求和响应客户请求

  • 目录结构

  • bin 存放启动和停止等命令和且其他脚本文件。
    
    config 存放服务器的配置文件
    
    lib 存放服务器的jar包
    
    logs 存放服务器的日志文件
    
    webapps web应用的部署目录
    
    temp  存放tomcat的临时文件
    
    work    tomcat的工作目录
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    编辑器配置好tomcat运行环境

    添加好一个server实例

    servlet (处理请求和发起响应,为了实现动态页面而衍生出来的)

    servlet 生命周期

    - 加载类
    - 初始化
    - init
    - service
    - destory

    servlet与Tomcat之间的关系

    - tomcat是web应用服务器,是一个servlet/Jsp容器,负责把请求传递给Servlet,并将Servlet的响应传递给客户。
    - servlet是服务器上的一个组件,

    在web.xml中定义servlet与访问网址之间的匹配关系

    ```xml
    <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>test01.servlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
    </servlet-mapping>

可以在web.xml中配置load-on-startup=1 服务器启动时初始化servlet对象

servlet初始化参数

1
2
3
4
5
6
7
8
9
10
11
12
<servlet>
<servlet-name>Myservlet</servlet-name>
<servlet-class>test01.MyServlet</servlet-class>
<init-param>
<param-name>haha</param-name>
<param-value>这是Servlet中的初始参数</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

getInitParameterNames() 获取在servlet中的所有初始化参数的名字

重定向

1
response.sendRedirect("重定向的地址")

转发

1
request.getDispatcher("转发的地址").forWard(request,response)

JSP页面(java server pages)本质也是一个servlet

html中写jsp标签,jsp标签中写java代码

<% java代码%> <%= java变量%>

html,java代码块,jsp标签组成

JSP中的内置对象

  • out(jspWriter) :相当于respons.getWriter()获取的对象,用于在页面中显示信息。
  • config (servletConfig): servlet 中的 servletConfig对象。
  • page (Object) : 对应当前的servlet对象,实际上就是this
  • pageContext (PageContext) : 当前页面的上下文,也是一个域对象。
  • exception (Trowable): 错误页面中的异常对象
  • request (HttpServletRequest): HttpServletRequest对象
  • response (HttpServletResponse) : HttpServletResponse对象
  • application (ServletContext) : ServletContext对象
  • session(HttpSession): HttpSession对象

EL表达式 自动类型转换

​ EL是jsp内置的表达式语言,用以访问页面的上下文以及不同作用域中的对象 ,取得对象属性的值,或执行简单的运算或判断操作。

​ EL表达式用于代替JSP表达式(<%= %>)在页面中做输出操作

1
2
EL表达式语法
${ EL表达式(可完成取值,简单的运算,简单的判断)}

​ EL取值的四个域:
​ pageScope
​ requestScope
​ sessionScope
​ applicationScope

EL表达式与JSTL的比较

  • EL表达式为了简化jsp中传统的取值操作。 ${requst.pwd} <%= request.getAttribute(“pwd”)%>
  • JSTL是 (java server pages standard Tag library)
  • EL表达式多用于取值操作,而JSTL则可以方便我们对集合进行遍历,对数据进行判断等操作

JavaScript

avaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应

BOM

①Borwser Object Model 浏览器对象模型
②浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。BOM由多个对象组成,其中代表浏览器窗口的Window对象是BOM的顶层对象,其他对象都是该对象的子对象
③常用的对象(window的子对象)
document history location screen navigator frames

DOM

①Document Object Model 文档对象模型
②document对象: window对象的一个属性,代表当前HTML文档,包含了整个文档的树形结构。获 取document对象的本质方法是:window.document,而“window.”可以省略。

document.getElementById(“id值”)

document.getElementsByTagName(“标签名”)

document.getElementsByName(“name值”)

Ajax

XMLHttpRequest对象是AJAX中非常重要的对象,所有的AJAX操作都是基于该对象的。

Xhr对象的方法

  • ①open(method,url,async) open()用于设置请求的基本信息,接收三个参数
    • ①method
      请求的方法:get或post
      接收一个字符串
    • ②url
      请求的地址,接收一个字符串
    • ③Assync
      发送的请求是否为异步请求,接收一个布尔值。
      true 是异步请求
      false 不是异步请求(同步请求)
  • ②send(string)
    send()用于将请求发送给服务器,可以接收一个参数
    • ①string参数
      该参数只在发送post请求时需要。
      string参数用于设置请求体
  • ③setRequestHeader(header,value)
    用于设置请求头
    • ①header参数
      字符串类型,要设置的请求头的名字
    • ②value参数
      字符串类型,要设置的请求头的值

XMLHttpRequest对象的属性

readyState
①描述XMLHttpRequest的状态
②一共有五种状态分别对应了五个数字:
0 :请求尚未初始化,open()尚未被调用
1 :服务器连接已建立,send()尚未被调用
2 :请求已接收,服务器尚未响应
3 :请求已处理,正在接收服务器发送的响应
4 :请求已处理完毕,且响应已就绪。
2)status
①请求的响应码
200 响应成功
404 页面为找到
500 服务器内部错误
3)onreadystatechange
①该属性需要指向一个函数
②该函数会在readyState属性发生改变时被调用
4)responseText
①获得字符串形式的响应数据。
5)responseXML(用的比较少)
①获得 XML 形式的响应数据。

使用JQuery框架来发送异步请求

  • JQuery是当前比较主流的 JavaScript 库,封装了很多预定义的对象和实现函数,

  • JQuery的对象的本质就是dom对象的数组/集合

  • JQuery对象与dom对象的相互转换
    JS转JQuery: var jObj = $(dObj);
    JQuery转JS: var dObj = jObj[0] 或者 var dObj = jObj.get(0)

HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分中两次请求是否由一个客户端发出的。假如在我们进行网购时,买了一条裤子,又买了一个手机。由于http协议是无状态的,如果不通过其他手段,服务器是不能知道用户到底买了什么。而Cookie就是解决方案之一。

Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求。

创建cookie

​ Cookie mycookie = new Cookie(‘key’,’value’);

​ mycookie.setPath(‘设置cookie的路径’);

​ mycookie.setMaxAge(‘设置cookie的时间’);

​ request.addCookie(mycookie);

读取cookie

​ Cookie[] cookie = request.getCookie();

Session

​ 使用cookie是有局限的,如果cookie很多会增加数据传输量,浏览器也会对cookie的数量有限制,于是session出现。

​ Session的作用就是在服务器端保存一些用户的数据,然后传递给用户一个名字为JSESSIONID的Cookie,这个JESSIONID对应这个服务器中的一个Session对象,通过它就可以获取到保存用户信息的Session。

  1. Session的工作原理
    ①Session的创建时机是在request.getSession()方法第一次被调用时。
    ②Session被创建后,同时还会有一个名为JSESSIONID的Cookie被创建。
    ③这个Cookie的默认时效就是当前会话。
    ④简单来说,Session机制也是依赖于Cookie来实现的

  2. 使用

    HttpSession session = request.getSession();

  3. 时效性

    可以在web.xml中进行设置 30分钟

    1
    2
    3
    <session-config>
    <session-timeout>30</session-timeout>
    </session-config>

URL重写

​ 因为session还是需要cookie实现的,如果cookie禁用,则session无法使用,所以我们需要一些备用的手段,如RUL重写。

  1. URL重写其实就是将JSESSIONID的值以固定格式附着在URL地址后面,以实现保持JSESSIONID,进而保持会话状态。这个固定格式是:URL;jsessionid=xxxxxxxxx

  2. 实现方式

    String url = “targetServlet”;

    String encodeURL = response.encodeURL(url)

    response.sendRedirect(encodeURL)

主页面访问权限控制 (过滤器 字符转码)

  1. 对于WEB应用来说,过滤器是一个驻留在服务器中的WEB组件,他可以截取客户端和WEB资源之间的请求和响应信息。WEB资源可能包括Servlet、JSP、HTML页面等

  2. 当服务器收到特定的请求后,会先将请求交给过滤器,程序员可以在过滤器中对请求信息进行读取修改等操作,然后将请求信息再发送给目标资源。目标资源作出响应后,服务器会再次将响应转交给过滤器,在过滤器中同样可以对响应信息做一些操作,然后再将响应发送给服务器。

  3. 使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class myFilter implement Filter{
    @override
    public void destroy(){

    }
    @override
    public void doFilter(ServletRequest arg0,Servlet response arg1,FilterChain arg2) throws IOException,ServletException {

    }
    @override
    public void init(FilterConfig arg0) throws ServletException{

    }
    }

    在xml中配置

    1
    2
    3
    4
    5
    6
    7
    8
    <filter>
    <filter-name>loginFilter</filter-name>
    <filter-class>com.atguigu.servlet.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>loginFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

在线人数统计(监听器)

  1. Listener用于监听JavaWeb程序中的事件。
  2. 例如:ServletContext、HttpSession、ServletRequest的创建、修改和删除
  3. 监听器的类型分为
    ①生命周期
    ②数据绑定

xml

​ xml用来传输和存储数据,xml没有预定义标签,均为自定义标签。

  1. 配置文件
    JavaWeb中的web.xml
    C3P0中的c3p0-config.xml
  2. 数据交换格式
    Ajax
    WebService
  3. 数据存储
    保存关系型数据

xml组成

  1. XML文档组成
    ①XML声明
    version属性指定XML版本,固定值是1.0
    encoding指定的字符集,是告诉解析器使用什么字符集进行解码,而编码是由文本 编辑器决定的
    ②CDATA区
    当XML文档中需要写一些程序代码、SQL语句或其他不希望XML解析器进行解析 的内容时,就可以写在CDATA区中
    XML解析器会将CDATA区中的内容原封不动的输出
    CDATA区的定义格式:
  2. 语法规则
    ①XML声明要么不写,要写就写在第一行,并且前面没有任何其他字符
    ②只能有一个根标签
    ③标签必须正确结束
    ④标签不能交叉嵌
    ⑤严格区分大小写
    ⑥属性必须有值,且必须加引号
    ⑦标签不能以数字开头
    ⑧注释不能嵌套

xml解析

  1. XML解析是指通过解析器读取XML文档,解释语法,并将文档转化成对象

  2. 常用的解析方式
    DOM(Document Object Model)
    SAX(Simple API for XML)

  3. Dom4j解析示例

    1
    2
    3
    SAXReader saxreader = new SAXReader();
    Document document = saxreader.read("students.xml")
    Element root = document.getRootElement();

JSON

  1. AJAX一开始使用的时XML的数据格式,XML的数据格式非常简单清晰,容易编写,但是由于XML中包含了过多的标签,以及十分复杂的结构,解析起来也相对复杂,所以目前来讲,AJAX中已经几乎不使用XML来发送数据了。取而代之的是一项新的技术JSON。
  2. JSON是JavaScript Object Notation 的缩写,是JS提供的一种数据交换格式。
  3. JSON对象本质上就是一个JS对象,但是这个对象比较特殊,它可以直接转换为字符串,在不同语言中进行传递,通过工具又可以转换为其他语言中的对象。

JSON通过6种数据类型来表示

  1. 字符串
  • 例子:”字符串”
  • 注意:不能使用单引号
  1. 数字:
  • 例子:123.4
  1. 布尔值:
  • 例子:true、false
  1. null值:
  • 例子:null
  1. 对象
  • 例子:{“name”: ”sunwukong”, ”age”: 18}
    6.数组
  • 例子:[1,”str”,true]

在JS中操作JSON

  1. 创建JSON对象
  • var json = {“name1”: ”value1”,”name2”: ”value2” , “name3”: [1,”str”,true]};
  • var json = [{“name1”: ”value1”},{“name2”: ”value2”}];
  1. JSON对象转换为JSON字符串
  • JSON.stringify(JSON对象)
  1. JSON字符串转换为JSON对象
  • JSON.parse(JSON字符串)

在Java中操作JSON

  1. 在Java中可以从文件中读取JSON字符串,也可以是客户端发送的JSON字符串,所以第一个问题,我们先来看如何将一个JSON字符串转换成一个Java对象。

  2. 首先解析JSON字符串我们需要导入第三方的工具,目前主流的解析JSON的工具大概有三种json-lib、jackson、gson。三种解析工具相比较json-lib的使用复杂,且效率较差。而Jackson和gson解析效率较高。使用简单,这里我们以gson为例讲解。

  3. Gson是Google公司出品的解析JSON工具,使用简单,解析性能好。

  4. Gson中解析JSON的核心是Gson的类,解析操作都是通过该类实例进行。

  5. JSON字符串转换为对象

    1
    2
    3
    4
    5
    6
    String json = "{\"name\": \"张三\",\"age\": 18}";
    Gson gson = new Gson();
    // 转换为集合
    Map<String,Object> stuMap = gson.fromJson(json,Map.class);
    // 转换为类
    Student student = gson.fromJson(json,Student.class);

6.对象转json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Student stu = new Student("李四", 23);
Gson gson = new Gson();
//{"name": "李四","age": 23}
String json = gson.toJson(stu);
Map<String , Object> map = new HashMap<String, Object>();
map.put(“name”, “孙悟空”);
map.put(“age”, 30);
//{“age”: 30,“name”: “孙悟空”}
String json2 = gson.toJson(map);

List<Student> list = new ArrayList<Student>();
list.add(new Student(“八戒”, 18));
list.add(new Student(“沙僧”, 28));
list.add(new Student(“唐僧”, 38));
//[{“name”: “八戒”,“age”: 18},{“name”: “沙僧”,“age”: 28},
{“name”: “唐僧”,“age”: 38}]
String json3 = gson.toJson(list);
// 如果将一个数组格式的json字符串转换成java对象需要用到
//Gson提供的一个匿名内部类: TypeToken
TypeToken tk= new TypeToken<List<User>>(){};
List<User> list2 = gson.fromJson(json,tk.getType());
System.out.println(list2.get(0));

dao层

service层

web层

  • model 需要向页面加载的数据 一般为javaBean
  • view 页面模板 一般为jsp
  • controller 加载哪些数据然后跳转哪个页面 一般为servlet

js函数学习

  • var squares = Array(9).fill(null); //创建长度为9的数组

  • var squaresCope = squares.slice(); //返回一个新的数组,如果指定了start和end参数,则从start到end,否则会全部拷贝。

  • var newPlayer = Object.assign({},player,{score : 2}); //**Object.assign()** 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。第一个参数为目标对象,后面的都是源对象,源对象和目标对象中有相同的属性,源对象的属性会覆盖目标属性。

  • array.map(function(currentValue,index,arr),thisValue) 数组中的每个元素都会执行这个函数,thisValue可以省略。

  • 函数表达式会有一个name属性,当没有命名时会将分配变量的名字作为自己的隐式名。

  • bind()、call()、apply()方法用法,都是用来重定义this这个对象的。具体区别

  • es6 字符串拼接,可以配合反单引号完成拼接字符串的功能

    1、反单引号怎么打出来?
    将输入法调整为英文输入法,单击键盘上数字键1左边的按键。

    2、用法
    step1: 定义需要拼接进去的字符串变量
    step2: 将字符串变量用${}包起来,再写到需要拼接的地方

    3、示例代码:

    let a=’Karry Wang’;

    let str=I love ${a}, because he is handsome.;
    //注意:这行代码是用返单号引起来的

    alert(str);
    一定是用反单引号啊!不要写成单引号了!

  • opacity属性 (让 DIV 元素半透明)

    元素的不透明度级别描述了透明度级别,当不透明度为 1 时表示完全不透明,当不透明度为 0.5 时表示半透明,当不透明度为 0 时表示完全透明。

  • 定时器

    • setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。(循环定时器)
    • setTimeout() :在指定的毫秒数后调用函数或计算表达式。(延时定时器)
  • 数组添加删除

    • 添加在第一个:unshift(xxx)
    • 删除指定元素:splice(index,number,item)
  • &&|| 运算符使用短路逻辑(short-circuit logic),是否会执行第二个语句(操作数)取决于第一个操作数的结果。在需要访问某个对象的属性时,使用这个特性可以事先检测该对象是否为空:

1
var name = o && o.getName();
  • switchcase 都可以使用需要运算才能得到结果的表达式;在 switch 的表达式和 case 的表达式是使用 === 严格相等运算符进行比较的:

  • ES2015 引入了更加简洁的 forof 循环,可以用它来遍历可迭代对象,例如数组:

    1
    2
    3
    for (const currentValue of a) {
    // Do something with currentValue
    }
  • ECMAScript 5 增加了另一个遍历数组的方法,forEach()

    1
    2
    3
    ["dog", "cat", "hen"].forEach(function(currentValue, index, array) {
    // Do something with currentValue or array[index]
    });
  • 数组函数

    shift \ unshift \ push \ pop \ concat \join \ length \ splice \

  • js取非行间样式

    • getComputedStyle(obj,false)[‘attr’]方法
    • div.currentStyle[‘width’];方法
  • dom节点

    • childNodes \ nodeType
    • children //好用
  • String

    • search方法
  • 事件冒泡

    • event.cancelBubble=true
    • 鼠标位置 clinetX,clientY
    • 键盘按键 keyCode
    • 其他属性 boolean值 ctrlKey shiftKey altKey
  • 默认行为

    • documemnt.oncontextmenu=()=>{return false;}
    • otxt.onkeydown=()=>{return false}
    • 计算窗口的高度document.documentElement.clientHeight
    • 计算物体自己的高度 document.documentElement.clientWidth
  • 事件绑定

    • attachEvent(‘onclick’,函数)
    • addEventListener(‘click’,函数,false)
  • 事件捕获

    • setCapture() ie浏览器下
  • AJAX

    • 创建Ajax对象 var oAjax = new XMLHttpRequest();

    • 链接服务器 oAjax.open() | open(方法,文件名,异步传输)

    • 发送请求 oAjax.send()

    • 接受返回值 oAjax.onreadystatechange = function(){

      oAjax.readystate // 浏览器和服务器进行到哪一步了

    • };

    • 看看是否成功 oAjax.status==200

    • 查看返回的文本 oAjax.responseText

  • 原型

    • prototype | 用法 类.prototy.属性 (集体添加上属性)
  • 继承

    • A继承B的属性 在A的函数中添加B.call(this)
    • A继承B的方法 A.prototype=B.prototype;
  • Generator函数(函数名后有*号,用yeild表达式来表示)用来生成iterator表达式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function* myGenerator(){
    yeild 'hello';
    yeild 'generator';
    }
    let MG = myGenerator(); // 这里生成一个Generator函数
    MG.next();// 第一种方法
    for( var a of MG){
    console.log(a)
    }
  • promise函数(可以保存状态,pending,从pending变为fulfilled
    从pending变为rejected)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let p1 = new Promise(function(resolve,reject){
$.ajax({
url:'data/json.txt',
dataType: 'json',
success(arr){
resolve(arr);
},
error(err){
reject(err);
}
})
})
p1.then(function(arr){
alert('成功了'+arr);
},function(){
alert('失败了');
})
  • export和module.export(还是不太了解)

    1
    2
    3
    4
    5
    6
    exportsmodule.exports 的一个引用
    module.exports 初始值为一个空对象 {},所以 exports 初始值也是 {}
    require 引用模块后,返回的是 module.exports 而不是 exports!!!!!
    exports.xxx 相当于在导出对象上挂属性,该属性对调用模块直接可见
    exports = 相当于给 exports 对象重新赋值,调用模块不能访问 exports 对象及其属性
    如果此模块是一个类,就应该直接赋值 module.exports,这样调用者就是一个类构造器,可以直接 new 实例。
  • html 中rel属性

    描述
    alternate 文档的可选版本(例如打印页、翻译页或镜像)。
    stylesheet 文档的外部样式表。
    start 集合中的第一个文档。
    next 集合中的下一个文档。
    prev 集合中的前一个文档。
    contents 文档目录。
    index 文档索引。
    glossary 文档中所用字词的术语表或解释。
    copyright 包含版权信息的文档。
    chapter 文档的章。
    section 文档的节。
    subsection 文档的子段。
    appendix 文档附录。
    help 帮助文档。
    bookmark 相关文档。
    nofollow Google 使用 “nofollow”,用于指定 Google 搜索引擎不要跟踪链接。

js解构

​ 可以查看https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

React.Fragment(简写<></>)

​ 片段(fragments) 可以让你将子元素列表添加到一个分组中,并且不会在DOM中增加额外节点(还可以使用返回数组的方式来解决。);您可以像使用其他元素一样使用<></>,只是它不支持 键(keys) 或 属性(attributes)。

插槽(Portals)

1
ReactDOM.createPortal(child, container)

​ 第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 片段(fragment)。第二个参数(container)则是一个 DOM 元素。

对于 portal 的一个典型用例是当父组件有 overflow: hidden 或 z-index 样式,但你需要子组件能够在视觉上 “跳出(break out)” 其容器。例如,对话框、hovercards以及提示框。

js小技巧

  • &&|| 运算符使用短路逻辑(short-circuit logic),是否会执行第二个语句(操作数)取决于第一个操作数的结果。在需要访问某个对象的属性时,使用这个特性可以事先检测该对象是否为空:

    1
    var name = o && o.getName();
  • 或用于缓存值(当错误值无效时):

1
var name = cachedName || (cachedName = getName());
  • 类似地,JavaScript 也有一个用于条件表达式的三元操作符:
1
var allowed = (age > 18) ? "yes" : "no";

1、react初步了解

1、特点

  • 声明式 :我们只需要更新数据就可以了,不用亲自操作dom元素。
  • 组件化 :将页面分为一个个的组建,易于编写和维护。

2、高效的原因

  • 虚拟dom,不总是直接操作DOM。以前是一个一个修改DOM,虚拟DOM与DOM对象一一对应,更改虚拟DOM并不会直接更改DOM,而是等待都更改完成,批量更改。
  • DOM Diff 算法,最小化页面重绘。

3、引入库文件

开源库

​ react-dom.development.js(提供操作DOM对象的react扩展库)、react.development.js(react核心库)、babel.js(把ES6改为ES5或解析jsx语法为js语法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="test">

</div>

<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.js"></script>

<script type="text/babel">
//1、创建虚拟DOM元素对象
var vDom = <h1>Hello React!</h1>
//2、将虚拟DOM渲染到页面真是DOM对象中
ReactDOM.render(vDom,document.getElementById('test'))
</script>

2、了解jsx

1、不使用jsx创建虚拟DOM对象

1
var element = React.creatElement('h1',{id:'myTitle'},'hello')

如果要使用变量中定义的内容,要使用{ }将变量包起来。

再js中可以使用debugger来设置断点。

在React组件的构造函数中设置this.state来初始化state。

2、自定义组件

1、定义组件

方式一、工厂函数组件

function MyComponent(){

​ return

}

方式二、es6类组件

class MyComponent2 extends React.Component{

​ render(){

​ return

​ }

}

2、渲染组件标签

ReactDOM.render(,document.getElementById(‘example1’))

3、组件的三打属性

  • const {isNext} = this.state //es6写法,等同年与 const isNext = this.state.isNext
    
    1
    2
    3
    4

    - ```js
    const isNext = !this.state.isNext
    this.setState({isNext}) //es6写法,等同于isNext = isNext
①state

​ 是一个对象,如果用它则必须使用类组件的方式。在constructor()方法中定义。可以使用setState({xxx = xxx})方式来更新数据,用这种方式更新数据,所有的用到该数据的地方都会进行更新。

②props

​ 是一个对象,用来将数据从组件外传入到组件内部。

指定默认值

1
2
3
4
5
//指定属性默认值
Person.defaultProps = {
sex: '男',
age:18
}

props验证

​ React.PropTypes 在 React v15.5 版本后已经移到了 prop-types 库。

1
<script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
1
2
3
4
5
//对props中的属性值济宁类型限制和必要性限制
Person.propTypes = {
name:PropTypes.string.isRequired,
age:PropTypes.number
}
1
2
3
4
5
6
/*
* ...的作用
* 1、打包
* 2、解包
* ReactDOM.render(<Person {...p1}/>,document.getElementById('test'))
* */
③refs

作用: React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。

这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保

在任何时间总是拿到正确的实例。

1
2
3
<input ref = ‘content'></input>

const input = this.refs.content
1
{{opacity:opacity}}

外边的大括号代表进行书写js文件,里面的括号代表这是一个对象。

react ajax

react本身没有提供ajax相关的代码。

解决方法:

  • 1、jQuery:比较重,不建议使用

  • 2、axios:轻量级,建议使用

    • 封装XmlHttpRequest对象的ajax
    • promise风格
    • 可以用在浏览器端和node服务器端
  • 3、fetch:原生函数,但老版本浏览器不支持

    • 不再使用XmlHttpRequest对象提交的ajax请求
    • 为了兼容低版本的浏览器,可以引入兼容库fetch.js

兄弟组件之间传递信息

组件:pubsub-js

1
2
3
4
5
6
7
8
import PubSub from 'pubsub-js'

PubSub.publish('name',data)

PubSub.subscribe('name',(name,data)=>{
hanshu

})

如何编写路由效果

  1. 编写路由组件
  2. 在父路由组件中指定
    • 路由链接:
    • 路由:

Redux

image-20200624105238185

1.安装redex

​ npm install –save redux

2.API

  • creatStore()

3.对象

  • store
    • 作用:redux库最核心的管理对象
    • 内部属性
      • state 公共状态
      • reducer 改变状态的函数
    • 方法
      • getState()
      • dispatch(action)
      • subscribe(listener)
    • 编码
      • store.getState() //获取状态数据
      • store.dispatch({type:’INCREMENT’,number}) //进行状态数据更改
      • store.subscribe(render) //状态数据更改后要重新执行渲染

4.核心概念

  • action(用来表示执行行为的对象)

    • 属性
      • type:标识属性,值为字符串,唯一
      • xxx:数据属性,值类型任意
    • Action Creator(创建Action的函数)
  • reducer(根据老的state和action,产生新的state的纯函数)

    • function xxx(state=0,action){ //根据action的type判断执行那些操作}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//1.创建reducer
import {INCREMENT,DECREMENT} from "./action-type";

export function counter(state = 0,action) {
console.log('counter()',state,action)
switch (action.type) {
case INCREMENT:
return state + action.data
break
case DECREMENT:
return state - action.data
break
default:
return state
}
}
//2.创建store
import {createStore} from "redux";
import {counter} from "./reducers";
const store = createStore(counter)
//2.1传递和使用store
function render() {
ReactDOM.render(<App store={store}/>,document.getElementById('root'))
}
//2.2初始化渲染
render()
//2.3订阅监听(store中的状态变化了,就会自动调用)
store.subscribe(
render()
)

//3.actionsCreactor actions工厂创建
import {INCREMENT,DECREMENT} from "./action-type";
export const increment = (number)=>({type:INCREMENT,data:number})
export const decrement = (number)=>({type:INCREMENT,data:number})
//4.插件中使用
import React,{Component} from "react";
import {INCREMENT,DECREMENT} from "../action-type";
import * as actions from "../actions"
export default class App extends Component{
increment = ()=>{
//1.读取选择的值
const number = this.select.value*1
//2.调用store的方法更新状态
this.props.store.dispatch(actions.increment(number))
}

decrement = ()=>{
//1.读取选择的值
const number = this.select.value*1
//2.调用store的方法更新状态
this.props.store.dispatch(actions.decrement(number))
}

incrementIfOdd = ()=>{
//1.读取选择的值
const number = this.select.value*1
//2.获取count的值
const count = this.props.store.getState()
//3.更新count
if (count%2==1){
this.props.store.dispatch(actions.increment(number))
}
}

incrementAsync = ()=>{
//1.读取选择的值
const number = this.select.value*1
//2.加上count的值
const count = this.props.store.getState()
//3.更新count
setTimeout(()=>{
this.props.store.dispatch(actions.increment(number))
},1000)
}

render() {
const count = this.props.store.getState()
return(
<div>
<p>click {count} times</p>
<div>
<select ref={select=>this.select = select}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>&nbsp;
<button onClick={this.increment}>+</button>&nbsp;
<button onClick={this.decrement}>-</button>&nbsp;
<button onClick={this.incrementIfOdd}>increment if odd</button>&nbsp;
<button onClick={this.incrementAsync}>increment async</button>&nbsp;
</div>
</div>
)
}
}

使用react-redux简化(就是使用传参的方式传递state和改变state函数)

  • 引入 npm install --save react-redux
  • 在index中 用Provider包装组件
1
2
3
4
5
6
import {Provider} from 'react-redux'
ReactDOM.render(
<Provider store = {store}> //store不在给App组件,而是给Provider组件
<App/>
</Provider>
)
  • 在App组件中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {increment,decrement} from "../actions";
class App extents React.Component{//不是直接暴露出来
static propTypes = { // 判断参数
count:PropTypes.number.isRequired,
incrememt:PropTypes.func.isRequired,
decrement:PropTypes.func.isRequired
}
....
incrementIfOdd = ()=>{
//1.读取选择的值
const number = this.select.value*1
//2.获取count的值
const count = this.props.count//这里获取的是props中的count不是在store获取
//3.更新count
if (count%2==1){
this.props.incrememt(number)//这里直接使用参数中的函数,不是在使用store.dispatch(action)
}
}
....

}
export default connect(
state=>({count:state}),
{increment,decrement}
)(<App/>) //这里使用connect函数给App插件绑定参数,第一个括号是执行connect函数,参数为要绑定的参数,返回是一个函数.然后在把App插件作为参数传递过去,返回一个绑定好参数的插件.使用export导出去
  • react-redux分为component和container
    • component不包含redux内容的部分
    • container是包含redux内容的部分

redux异步编程

  • 下载redux插件(异步编程中间件)

    npm install --save redux-thunk

  • 在store.js中添加applyMiddleware和thunk

    1
    2
    3
    4
    5
    6
    import {createStore,applyMiddleware} from "redux";
    import {counter} from "./reducers";
    import thunk from 'redux-thunk'

    const store = createStore(counter,applyMiddleware(thunk)) //应用上异步中间件
    export default store
  • 在插件中异步函数使用this.props.incrementAsync()函数

1
2
3
4
5
incrementAsync = ()=>{
//1.读取选择的值
const number = this.select.value*1
this.props.incrementAsync(number)
}
  • 在container中app.js中(也就是绑定参数的函数的js文件)添加incrementAsync函数
1
2
3
4
5
6
7
8
import React from "react";
import {connect} from "react-redux";
import {decrement, increment,incrementAsync} from "../actions";
import Counter from "../components/counter";
export default connect(
state =>({count:state}),
{increment,decrement,incrementAsync}
)(Counter)
  • 在actions文件中添加函数(注意异步函数返回的是一个函数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
包含所有action creator
*/
import {INCREMENT,DECREMENT} from "./action-type";
import {number} from "prop-types";
//同步的action都是返回一个对象
//异步的action都是返回一个函数
//增加
export const increment = (number)=>({type:INCREMENT,data:number})
//减少
export const decrement = (number)=>({type:DECREMENT,data:number})
//异步增加
export const incrementAsync = (number)=>{
return dispatch=>{
//异步的代码
setTimeout(()=>{
dispatch(increment(number))
// 1s之后才去分发一个action
},1000)
}
}

线性结构:特点数据元素之间存在一对一的关系(数组、队列、链表、栈)

​ 两种不同的存储结构,顺序存储结构(顺序表)和链式存储结构(链表)

非线性结构:(二维数组、多维数组、广义表、树结构、图结构)

稀疏数组 (当二维数组中存在多个一样的值得时候使用)
  • 第一行几行几列有多少个不同的元素
  • 剩下的是不同元素所在的行和列以及值

image-20210310172143830

josephu(约瑟夫)问题(丢手帕问题)

单项环形链表

最小生成树(普利姆算法)

最短路径问题(图+弗洛伊德算法)

汉诺塔 分治算法

八皇后算法 回溯算法

java

java构造赋值,先父类后子类,先默认后构造的顺序。

父类与子类:

​ 子父类拥有相同的变量,规则:自己有用自己,自己无用父类。

     父类实现先于子类实现,显式调用父类构造器或者隐藏调用父类无参构造器

​ Serializable接口,相当于一个标志,告诉jvm可以将该类的对象进行序列化和反序列化。(可以使用transient修饰那些不需要序列化的属性),最好自己写一个serialVersionUID(static final long),不会序列化static关键字修饰的属性。如果父类没有实现Serializable接口,那么必须有无参构造函数。

​ Externalizable接口,需要重写writeExternal和readExternal方法,效率比Serializable高,可以决定哪些属性需要序列化(即使transient修饰的),但是面对大量对象,或者重复对象,则效率低。

​ package打包后的类可以不在同一个文件夹中,但是所在文件夹的名字必须与包名一致。

​ import关键字,使用*号时,只会导入该包内的类,并不会导入包。

抽象类:

​ 防止创建没有对象性质的对象(例如:动物),只应该有方法声明,不应该有方法主题。

​ 抽象类也是具有构造函数的,所有子类实现都必须先执行抽象类的构造函数。

​ 抽象类中可以存在0到多个抽象方法,也可存在0到多个非抽象方法

接口:

​ 接口是一种特殊的抽象类,也是引用数据类型(数组,类,接口),包含抽象方法( public abstract),(静态方法和默认方法(default不可省))jdk8以后,成员属性都是常量(public static final)

​ 默认方法,子类不需要重写。

​ 实现接口是为了实现某个功能,是为了进行拓展。

类中代码会在属性初始化之后,无参构造函数之前

static

​ static 关键字修饰的 可以继承 但是不可以重写

final

​ final 修饰成员变量必须赋值(直接赋值,代码块赋值,构造方法赋值),修饰局部变量可以声明和赋值分开。

​ final修饰的形参也是不能改变的

​ final 修饰引用类型,可以更改引用对象。

​ static final 修饰的就是一个常量 (直接赋值,静态代码块赋值)

​ final 修饰的方法不允许被重写

​ final 修饰的类不能被继承

多态

​ 成员属性看左边,成员方法看右边(方法里面用右边变量)

Hashcode编码

​ 用的Object.hash(Object… values) 底层 Arrays.hashCode(values)

实现clone方法

​ 实现Cloneable接口,才能重写Object类的clone方法

javaBean规范

​ 必须要有包

​ 属性私有化

​ get、set方法

​ 实现接口序列化 Serializable

​ public修饰类

​ 增加无参构造函数

String类

​ 底层char数组,String对象永远不变

​ 字符串池的存在,所以字符串字面量是共享的

​ 底层是char数组,所以可以进行char数组和字符串的互转

​ intern方法: (手动优化)如果字符串池中有则返回字符串池中得,否则向池中添加再返回

​ match方法:正则表达式

StringBuilder(异步,不安全)

​ append: 添加

​ insert: 插入位置的前面

​ delete: 删除包前不包后

正则表达式的作用

​ 判断句子是否符合你的规则 match

​ 按照你的规则进行文本切割 split

​ 在文本中替换你想要得格式 replaceAll

. 匹配任意一个字符,除了\n
[] 匹配[]中列举的类型
\d 匹配数字,即0-9
\D 匹配非数字
\s 匹配空白,tab 空格
\S 匹配非空白
\w 匹配单词字符,即a-z,A-Z,_,0-9
\W 匹配非单词字符

正则表达式的斜杠成双原则 \ \ 因为编辑器认为\后的字母应该被转义,但是又找不到应该转义成的字符,我们需要的是一个完整的\d,所以斜杠成双。

* 匹配前一个字符0或无数次,即可有可无
+ 匹配前一个字符1或无数次,即至少有一次
匹配前一个字符1或0次,即不会多于一次
{m} 匹配前一个字符m次
{m,} 匹配前一个字符至少m次
{m,n} 匹配前一个字符m到n次

时间类型

long类型 仅仅是返回值类型 System.currentTimeMillis(), 1970年到现在的毫秒数

Data类型 日期 桥梁 由于千年虫事件 基本上不使用 被用来进行long类型和Calendar类型的数据转换以及时间的展示

Calendar类型 日历 日期的运算 属于抽象类,使用它的子类(GregorianGalendar)进行实例化,或者使用Calendar中的getInstance()方法 子类gregorianCalendar

从字符串转换为时间类型 DateFormat 抽象类,子类simpleDateFormat

格式化 date–》string

解析 string—》date

集合类型

​ Collection 接口

add,remove,size,contains

addAll, 合并不会去重

removeAll, 去重交集

retainAll 得到交集

根据类型的equals和hashcode进行判断

List接口 ===默认为集合 (有序、重复)

List允许出现重复元素,线性方式的有序存储,通过索引来访问集合中的指定元素

*如果list是Integer泛型的话,如果使用remove方法,这里必须要理解的是:如果不需要自动装箱就能调用方法的话,就不会进行自动装箱。

ArrayList在操作指定下标的任意元素上面,速度比较快。(查找上和指定下标操作的操作上速度比较快)。

LinkedList底层是双向链表,所以在操作首尾元素的操作上速度比较快。

vector自从ArrayList出现以后,就不再使用了

迭代器

相当于把所有的集合元素按照他们指定的顺序排放在一个类似于线性表的集合中。

使用集合对象调用iterator方法,获取iterator对象,如果有泛型,iterator也可以使用相应的泛型。

泛型

为了将运行时异常转换为编译时异常(深层次)

泛型不存在继承关系

set接口

set接口中的元素无序,并且存入的元素不重复出现。

HashSet

​ 无序且不重复、重写hashcode和equals方法

LinkedHashSet

​ 有序

TreeSet(实现了set和sortset)

​ 具有自然排序功能的类

​ 可以自定义排序

​ 不重复,不能放null

​ 因为TreeSet这个类需要吧里面的元素进行统一类型来比较,所以会配套使用泛型

​ TreeSet对自定义数据类型进行排序的话,需要两个前提

​ 实现comparable接口

​ 有具体的排序方法

比较器

在java中有两个常用的接口,分别是Comparator接口和Comparable接口

Comparator接口

​ 临时 重写 compare方法 两个参数

​ 经常在Arrays.sort以及Collections.sort里面来使用

​ 不能在TreeSet中使用

​ 使用内名内部类

Comparable接口

​ 持久 重写 compareTo方法 一个参数

1
2
3
// 都返回0的话,就会输出一个元素
// 返回正数时,代表该属性值的升序-->本身属性-参数属性
// 返回负数时,代表该属性值的降序-->参数属性-本身属性

Map接口

等同于set的定义,建唯一不重复。键值对

​ 键 无序、无下标、不允许重复

​ 值 无序、无下标、允许重复

HashMap 不能保证顺序,键采用自定义类型时,就要重写hashCode和equals方法

LinkedHashMap 多了排序的功能

TreeSet 自然排序且键不重复,可以采用自定义比较。

HashMap与Hashtable的关系 ArrayList和vector的关系

Throwable

​ 编写错误不属于异常(需要try catch的才是编译型异常)

​ printStackTrace() 打印异常的详细信息。包含了异常的类型,异常的原因,异常出现的位置

​ getMessage() 获取异常的原因

​ toString() 获取异常的类型和异常描述信息

异常处理方式

​ try catch finally 不加catch的话会结束程序的执行

​ throw 后面跟异常对象 并且结束当前方法的执行

​ throw 后面如果接运行时环境,一旦改代码执行,那么程序会停止,如果后面是检查时异常,就会要求你处理异常,程序不会停止。

​ 如果throw后面跟的是一个编译时异常,jvm就会要求你必须处理此异常

​ throws 放在方法结构尾部,用来告诉方法的调用者,这个方法有异常。

​ Exception 和 继承Exception类的子类 属于编译期异常(除了RuntimeException 和 它的子类)

​ RuntimeException和继承 了RuntimeException的子类

​ 自定义异常就是继承Exception或RuntimeException

反射

​ 通过字节码对象获取,把类的各个组成部分(属性,构造函数和方法)给获取到

​ 能干什么?

​ 获取类的相关信息,动态调用方法,动态调用属性

Class类

1
2
3
4
5
6
7
8
9

getName forName newInstance

getField(String) getDeclaredField(String) getFields getDeclaredFields

getMethod(String name,Class... <?> parameterType) getDeclaredField getMethods getDeclaredFields

getConstructor(Class... <?> parameterType) getDeclaredField getConstructors getDeclaredFields

Field类

1
2
3
4
get(Object o); // 返回一个Object 获取该对象的相对应的属性
set(Object o, 值) // 修改该对象的值
// NoSuchFieldException 获取非公有属性 解决 getDeclaredField
// IllegalAccessException 非法访问 解决 使用之前赋予权限 setAccessible(true)

Method类

1
2
3
4
get(Object,Class...<?> ParameterType ) // ParameterType 是类型,不是具体的值
invoke(Object o , Object... Parameter) // Parameter为具体的值
// NoSuchFieldException 获取非公有属性 解决 getDeclaredMethod
// IllegalAccessException 非法访问 解决 使用之前赋予权限 setAccessible(true)

Constructor类

1
2
newInstance // 创建一个新对象

工厂设计模式

这个创建模式让我们在创建对象时不会暴露创建逻辑,而是通过使用一个共同的接口来完成对象的创建

简单工厂、工厂方法、抽象工厂

优点:

​ 调用者想创建一个对象,只需要知道其名称,

​ 拓展性强,想增加产品,只要扩展产品类

​ 屏蔽产品的具体实现,无需关心内部实现

​ 面向接口编程

IO流

File类 (不能读/写文件内容,只能操作文件或文件夹的属性)文件或目录路径的抽象表现形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
exist() // 是否存在
createNewFile() // 创建新文件 eg\创建文件的目录必须存在
isHidden()// 判断文件是否隐藏
isFile()// 判断是否为普通的文件
length() // 文件的长度
isDirectory()//是否为文件夹
mkdir()//创建一个文件夹
mkdirs()//创建层级文件夹
renameTo(File dest) // 更改文件的名字
delete() // 删除文件 eg、如果删除文件夹,文件夹下面不能有文件
listFiles() // 列出指定路径下的所有文件
getAbsolutePath() //获取绝对路径
getCanonicalPath() // 获取规范形式 建议使用
getName() // 只有文件名
getPath() // 路径名字
listFile(FileFilter filter)

流对象

字节流

1
2
3
4
5
6
7
8
9
InputStream  实现了Closeable接口,可以被关闭
FileInputStream
FilterInputStream // 相当于私人订制
BufferedInputStream
DataInputStream // 专门处理基本数据类型的流
PushbakInputStream
ObjectInputStream
OutputStream 实现了closeable,Flushable接口

InputStream

  • available() 返回长度

FileOutputStream

  • read() 已经读完的情况下在读是-1 返回的是游标的位置

字符流

1
2
3
4
5
6
7
8
Reader
BufferedReader 常用
InputStreamReader
FileReader
Writer
BufferedWriter 常用
OutputStreamWriter
FileWriter

BufferedReader

  • Read 文件末尾返回null

BufferedWriter

  • write
  • append
  • newline 另起一行

PrinterWriter

  • PrinterWriter(String str)

序列化和反序列化

ObjectOutputStream和ObjectInputStream

一个类要实现序列化,它本身和它的属性必须都实现序列化。对父类无要求

serialVersionUID 使用来标识类的,来判断是否是同一个类,不写的话会自动计算生成

不想属性进行序列化解决方法

  • 加上static(类资源不会进行序列化)
  • 加上transient修饰词(当类实现的是Externalizable接口时,可以通过重写序列化和反序列化的方法指定某些属性进行序列化和反序列化,这时transient关键字失效)

线程

一个线程可以创建和撤销另一个线程

线程基本上不拥有系统资源

线程之间交替工作,被称为多线程。

线程的组成

  • cpu时间片
  • 运行数据(栈内存、堆内存)
  • 线程的业务逻辑代码

同步(并发)多个线程按照一定的顺序逐个进行执行。

异步(并行)多个线程一起不按顺序的执行。

1、多线程的创建

Thread类 实现run方法,调用start方法(如果执行run方法,不会开启一个新的线程)

  • 多个线程分别完成自己的任务

Runnable接口 实现run方法,但是还需要Threand类的start方法

  • 多个线程共同完成一个任务
  • 线程池只能放入实现Runable或Callable类线程,不能放入Thread子类

指定多线程的名字 setName方法

多线程的状态管理(生命周期)

New状态:多线程被创建出来,还没有调用start方法之前,属于这种状态。

Ready状态:调用了start方法,此时处于多个线程在争夺cpu使用权。

Runnable状态:当某个多线程抢夺到了cpu的使用权,并且开始运行他的业务逻辑的时候

Block状态:当多线程由于外部原因导致它无法继续执行业务逻辑的时候,

  • a、锁阻塞
  • b、指定时长的等待
  • c、不指定时长的等待

Terminated状态:当多线程业务逻辑执行完毕,属于这种状态,一旦进入这种状态,线程对象就无法调用方法了。

线程的常用方法

  • 静态方法

    • currentThread() 获取当前的线程对象
    • sleep() 让当前线程休眠(注意 因为是静态方法,所以不是按对象执行,而是看当前执行方法的线程) 如 在 t1 t2 线程,在t2中调用t1.sleep() ,t2休眠而不是t1休眠。
    • activeCount() 获取当前线程组的活动线程数量。
    • yield() 暂停当前线程的运行,让其进入就绪状态和其他的就绪线程抢夺资源。
  • 线程相关信息的方法

    • getName()/setName() 线程的名字
    • getId 线程的id标识符
    • getPriority()/setPriority() 线程的优先级
    • getState()线程的状态
    • setDaemon(boolean on) 标记为守护线程或用户线程
  • 守护线程

    • 守护线程,我们也称为后台线程或者是用户线程。
    • 一旦你设置了某个线程为守护线程的话,那么该线程会等待其他线程都结束,它就会自动结束,所以是守护线程我们一般不会设置其有效时间,会让它一直有效,典型的守护线程就是垃圾回收线程
    • 设置一个线程为守护线程要在start方法调用之前来设置。
  • 线程判断的方法

    • isAlive()
    • isDaemon()
    • isInterupted()
  • 其他

    • join()等待该线程终止再开始其他线程 放在start之后调用才有效

线程安全

多个线程同时使用同一个共享资源所导致的。

解决方法 锁(synchronized)

  • 对资源进行加锁

互斥锁的使用方式

  • 隐式锁
    • 代码块上锁
    • 方法上锁
  • 显式锁
    • lock上锁(jdk1.5之后)

代码块加锁

​ synchronized关键字可以用于方法的某个区域中,

​ synchronized(同步锁){

​ 需要同步操作的代码

​ }

​ 同步锁的解释

​ 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁,同步锁的要求:

​ 1、所对象可以是任意类型,我们一般直接使用Object对象

​ 2、保证这些线程对象使用的是同一把锁。

​ 注意:

​ 1、在任意时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码,其余代码只能在外边等着(Blocked)

​ 2、对于非static方法,同步锁就是this。对于static方法,我们使用当前方法所在类的字节码对象。

​ ps:sleep不释放锁资源,wait释放锁资源。

​ 可以使用lock接口,ReentrantLock是lock的实现类

​ 方法

​ lock()

​ unlock()

多线程唤醒的三种方式

​ interrupt() sleep()

​ notify()

​ notifyAll()

线程通信

​ 让多个线程之间可以进行进行同一件事情,需要线程之间进行协调。

​ wait和notify函数必须在同步代码块后者同步函数中使用。

线程池

使用:

​ 1、使用线程池的工具类Executors里面所提供的静态方法newFixedThreadPool(int nThreads)来构建一个指定线程数量的线程池对象。

​ 2、创建一个Runnable的子类,然后在run方法中写明你的任务逻辑代码。

​ 3、通过创建出来的ExecutorServices对象中的submit方法来执行你创建的Runnable子类。

​ 4、如果你不再使用线程池了,可以用shutDown()关闭它。

新特性

​ 1、lambda表达式

​ 2、方法引用

​ 有现成的方法使用,就是用现成的方法。(相当于对lambda表达式的进一步优化)

​ testInterface2(System.out::println)

​ 3、函数式接口

​ 就是符合lambda表达式的接口,确保接口中有且只有一个抽象方法

​ 在接口上使用@FunctionalInterface注解,如果是函数式接口,则编译通过,否则不通过。

​ 可以作为参数和返回类型。

​ 四种新常用的函数式接口(1.8)

​ Supplier接口 提供一个数据

1
2
3
4
Supplier<T>:包含一个无参的方法,用来获取一个泛型参数指定类型的对象数据。
Tget():获得结果,不需要参数,它会按照某种实现逻辑(由 Lambda表达式实现返回一个数据
Supplier<T>接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会
生产什么类型的数据供我们使用

​ Consumer接口

1
2
3
4
Consumer<T>:也被称为消费型接口,该接口正好与 Supplier接口相反,它不是生产一个数据,而是消费一
个数据,其数据类型由泛型决定。
void accept(T t):对给定的参数执行此操作。
default Consumer<T> andthen( Consumer after):返回一个组合的 Consumer,依次执行此操作,然后执行 afterf操作。

​ Predicate接口

1
2
3
4
5
Predicate<T>:通常用于判断参数是否满足指定的条件
boolean test(Tt):对给定的参数进行判断(判断逻辑由 Lambda表达式实现),返回一个布尔值
default Predicates> negate():返回一个逻辑的否定,对应逻辑非
default Predicate<T>and( Predicate other):返回一个组合判断,对应短路与
default Predicate<T>or( Predicate other):返回一个组合判断,对应短路或

​ Function接口

1
2
3
4
Function<T,R>:接口通常用于对参数进行处理,转換(处理逻辑由 Lambda表达式实现),然后返回一个新的值
Apply(Tt):将此函数应用于给定的参数
default<V> Function andthen( Function after):返回一个组合函数,首先将该函数应用于输入,然后将 after
函数应用于结果

stream流

流可以理解为是一种用来处理数据容器的东西。可以和lambda表达式相结合一起进行操作。

流的生成

​ 1、Collection接口下的子类

​ list.stream() set.stream()

​ 2、Map接口下的子类

​ 根据需求来进行键、值或者Entry对象的转换为stream流

​ map.keySet().stream() map.values().stream() map.entrySet().stream()

​ 3、数组

​ 直接调用Stream类的静态方法of

​ Stream.of(strArray)

​ 4、结束流

​ count forEach

​ 5、Stream转换到Collection

​ R collect(Collector collector)

​ Collectors工具类

​ public static Collector toList() : 把元素收集到list集合中

​ public static Collector toSet() : 把元素收集到set集合中

​ public static Collector toMap(Function keyMapper,Function valueMapper) : 把元素收集到map集合中


东软

操作数栈的概念

jdbc的连接步骤(引入jar包,mysql connector/J , lombok @Data, )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1、选择数据库的种类  Class.forName("com.mysql.jdbc.Driver")
2、创建连接,数据库地址,用户名、地址 Connnetion conn = DriverManager.getConnnection("jdbc:mysql://192.168.80.131:3306/db1?useUnicode=true&characterEncoding=utf8","root","123456");
3、选择要操作的数据库
上一步已经写好了
4、写sql语句
con.createStatement(String sql) // 少数 无预编译
PrepareStatement pstmt = con.prepareStataement(String sql) // 多数 有预编译
5、执行sql语句
ResultSet rs = pstmt.executeQuery();
6、处理结果集
while(rs.next()){

}

泛型逆向推到必须要写

单继承多实现

抽象类中可以有构造方法,接口中不可以有构造方法。

抽象类中可以有抽象方法和非抽象方法,接口中可以有非抽象方法(jdk8及以后)

字符流字节流之间转换: inputStreamReader bufferedReader

远程调用 一个机器上的controller层调用另一台机器上的service层 通过url调用

跨语言无法传输字节流,可以使用json或xml格式

分布式:将程序分为一个个的模块项目。(简单来说就是合力做一件事)

消息中间件:类似于数组。英文全称“Message Queue”,简称MQ。

事务:事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤 消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。

事务的四大特性:ACID,原子性(Atomicity),一致性(correspondence),隔离性(Isolation),持久性(durability)。

​ (1)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
​ (2)一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
​ (3)隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆, 必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。
​ (4)持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

进程:正在运行的程序

线程:是操作系统能够进行运算调度的最小单位,是进程中的实际运作单位。

javaee是通讯框架

单例模式

私有化构造方法

​ 饥饿式:先构造一个static的对象

​ 懒汉式: 先设置一个为null的static的变量,等调用对象的时候再进行生成。 因为是单实例多线程的调用需要加锁。