Java笔记1

Mysql

目录结构

  1. 安装目录
    D:/Mysql
    在这里插入图片描述
  2. 数据目录
    C:/ProgramData/Mysql/Mysql Server 5.5/data
    在这里插入图片描述
    点击mysql文件夹,进入里面看看
    在这里插入图片描述

MySQL登录

  1. 登录本机

    mysql -uroot -p

  2. 登录其他机器

    mysql -h127.0.0.1 -uroot -p

MySQL表的设计

在这里插入图片描述

# 旅游路线种类表
CREATE TABLE tab_category(
	cid INT PRIMARY KEY AUTO_INCREMENT,
	cname VARCHAR(100) NOT NULL UNIQUE
)

#一对多
CREATE TABLE tab_route(
	rid INT PRIMARY KEY AUTO_INCREMENT,
	rname VARCHAR(100) NOT NULL UNIQUE,
	price DOUBLE,
	rdate DATE,
	cid INT,
	FOREIGN KEY cid REFERENCES tab_categroy(cid)
)
#多对多
CREATE TABLE tab_user(
	uid PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(100) UNIQUE NOT NULL,
	password VARCHAR(100) NOT NULL,
	birthday DATE,
	sex CHAR(1) DEFAULT '男',
	telephone VARCHAR(11),
	email VARCHAR(100)
)
CREATE TABLE tab_favorite(
	rid INT,
	uid INT,
	date DATETIME,
	PRIMARY KEY(rid,uid),
	FOREIGN KEY(rid) REFERENCES tab_route(cid),
	FOREIGN KEY(uid) REFERENCES tab_user(uid)
)

数据库范式

设计关系型数据库,需要遵循不同的范式要求,设计出合理的数据库,一般达到第三范式数据库设计就很合理了,越高范式数据库冗余越小

  1. 第一范式:每一列都是不可分割的原子项
    在这里插入图片描述
    但是只满足第一范式数据表仍然存在问题:
    在这里插入图片描述
  2. 第二范式:在满足第一范式基础上,非码属性必须完全依赖于候选码
    在这里插入图片描述
    在这里,第二范式所说的要在满足第一范式的基础上消除部分依赖,其实就是这里姓名、系名和系主任依赖学号就好了,没必要依赖(学号,课程名称)
    因此做下面的优化
    在这里插入图片描述
    得到最终表
    在这里插入图片描述
    但是,也只是解决了第一个问题(存在严重的数据冗余,系名和系主任重复),第二个和第三个问题没有解决
  3. 第三范式:在满足第二范式基础上,任何非主属性不依赖其他非主属性(消除传递函数依赖)
    在这里插入图片描述
    改进如下:
    在这里插入图片描述
    看看问题解决了吗?
    在这里插入图片描述

数据库的备份和还原

1.命令行
备份:

<!--mysqldump -uroot -proot 数据库名 > 保存路径-->
mysqldump -uroot -proot db1 > /home/hadoop/apps/mysql/mydatabase

还原:

<!--假设事先已经删除数据库-->
create database db1
use db1
source /home/hadoop/apps/mysql/mydatabase

子查询

① 子查询的结果是单行单列的,使用=、>、<来判断

<!--SELECT AVG(salary) FROM emp)这个子查询的值为5000-->
SELECT * FROM emp WHERE emp.salary =(SELECT AVG(salary) FROM emp))

② 子查询的结果是多行单列,使用in运算符来判断

<!--SELECT id FROM emp WHERE name='财务部' or name='销售部'这个子查询得到的值是2,3,4-->
SELECT * FROM emp WHERE emp.dept_id  in (SELECT id FROM emp WHERE name='财务部' or name='销售部' )

③ 子查询的结果是多行多列

<!--当然也可以说还有普通的内连接-->
select * from dept t1,(select * from emp where emp.join_date>'2011-1-1') t2 where t1.dept_id=t2.dept_id)

事务

  1. 概念:如果一个包含多个步骤的业务操作,被事务管理,那么这些操作作为一个整体要么都执行成功,提交事务,要么中途失败回滚到原点

  2. 操作:

    <!--开启事务-->
    start transaction
    
    <!--张三账户增加500,李四账户减少500,这里有中文字符,所以肯定会出错-->
    update account set balance=balance+500 where name='张三'
    出错了...
    update account set balance=balance-500 where name='李四'
    
    <!--如果失败,回滚事务-->
    rollback
    <!--如果没有问题,提交事务;如果没有提交事务,那么当前窗口可以查看到数据被修改了,但是如果关闭窗口,数据会被回滚-->
    <!--增删改语句默认都是自动提交事务,也就是说执行后永久保存-->
    commit
    
  3. 事务提交两种方式:
    ① 自动提交
    ② 手动提交

    <!--查看事务提交方式 0--手动提交 1--手动提交 -->
    select @@autocommit;
    <!--修改事务提交方式-->
    set @@autocommit=0;
    <!--设置为手动提交进行增删改后需要commit提交-->
    

    MySQL默认是自动提交,oracle默认是手动提交

  4. 事务四大特性
    ① 原子性:事务是最小单位,要么一起成功,要么一起失败
    ② 持久性:当事务提交或回滚,数据库持久保持数据
    ③ 隔离性:各个事务之间互相独立,互不影响(其实这个很难做到,所以才有事务的隔离级别)
    ④ 一致性:事务操作前和操作后,数据总量不变

  5. 事务的隔离级别
    当多个事务操作同一批数据,不可避免会相互影响,这时就需要不同的隔离级别
    ① read uncommited(读未提交):脏读、虚读、幻读

    这个事务安全级别最低,如果先执行A事务,然后切到B事务,那么允许A事务读取B事务还没有提交的数据,那么会造成脏读、虚读、幻读

    ② read commited(读已提交):虚读、幻读 (Oracle)

    如果先执行A事务,然后切换到B事务,那么可以保证A不会读到B事务中未提交的数据,但是仍然会有虚读、幻读

    ③ repeatable read(可重复读):幻读 (MySQL)

    如果执行A事务,那么A事务先对读出的数据加锁,只要等到A事务执行完毕提交了,才能切换到B事务,避免了虚读,但是仍然会有幻读,因为幻读涉及到修改数据

    ④ serializable(可串行化)

    A事务执行提交完毕才能执行B事务,解决所有问题

    <!--查询隔离级别-->
    select @@tx_isolation
    <!--设置隔离级别:set global transaction isolation level 隔离级别字符串-->
    set global transaction isolation level repeatable read
    

用户管理

  1. 用户管理

    <!--在安装MySQL初会创建mysql库,里面有user表记录用户信息-->
    use mysql;
    select * from user;
    

    在这里插入图片描述

    创建用户

    create user ‘用户名’@‘主机名’ identity by ‘密码’

    删除用户

    drop user ‘用户名’@‘主机名’

    修改用户密码

    update user set password=password(‘新密码’) where user=‘用户名’

    如果忘记了MySQL的root密码怎么办?
    cmd (右键以管理员的身份运行)
    在这里插入图片描述
    关闭MySQL服务

    net stop mysql
    

    使用无验证方式启动MySQL

    mysqld --skip-grant-tables
    

    重新打开一个cmd窗口,直接输入mysql回车
    修改密码

    use mysql;
    update user set password=password('123') where user='root';
    

    右键打开任务管理器,结束任务进程
    在这里插入图片描述
    启动mysql服务

    net start mysql
    

    使用新的mysql账户密码登录

  2. 授权
    查询权限

    --%表示可以登录任意主机
    show grants for 'lisi'@'%'
    

    在这里插入图片描述
    查看root用户的权限

    show grants for 'root'@'%'
    

    在这里插入图片描述
    授予权限

    --grant 权限名 on 数据库名.表名 to '用户名'@'主机名'
    grant select on db3.account to 'lisi'@'%';
    

    在这里插入图片描述
    撤销权限

    -- reovke 权限名 on 数据库名.表名 from '用户名'@'主机名'
    revoke select on db3.account from 'lisi'@'%';
    

JDBC

jdbc一些小知识

  1. DriverManager 驱动管理对象
    它的作用是注册驱动,获取数据库连接
    DriverManager有个方法:static void registerManager(Driver driver)
    通过查看源码可以发现

    static{
    	try{
    		//它会将导入Class.forName("com.mysql.jdbc.Driver")加载二进制生成对象
    		java.sql.DriverManager.registerManager(new Driver);
    	}catch(SQLException e){
    		throw new RuntimeException("Can't register driver");
    	}
    }
    

    但是在mysql5后可以不用写Class.forName(“com.mysql.jdbc.Driver”)
    因为mysql-conncetor-java.jar驱动文件会读取java.sql.Driver文件中的内容
    在这里插入图片描述
    在这里插入图片描述

    数据库连接池(C3P0)

    1. 数据库连接池的配置文件中的maxPoolSize问题
      在这里插入图片描述
    DataSource ds=new ComboPooledDataSource();
    for(int i=0;i<11;i++){
    	Connection conn=ds.getConnection();
    	System.out.println(i+":"+conn);
    }
    

    在这里插入图片描述
    连接设置最大10个,11个超出了

    DataSource ds=new ComboPooledDataSource();
    for(int i=0;i<11;i++){
    	Connection conn=ds.getConnection();
    	System.out.println(i+":"+conn);
    	//第五个归还连接
    	if(i==5){
    		conn.close();
    	}
    }
    

    结果没有报错
    在这里插入图片描述

JDBCTemplate

  1. JDBCTmeplate是spring框架为了进一步简化jdbc的开发而设计的

  2. 使用
    ① 导入jar包(lib目录下)
    在这里插入图片描述
    ② 创建JDBCTemplate对象

    JdbcTemplate template=new JdbcTemplate(DataSource ds);
    

③ 查询单个数据

JdbcTemplate template=new JdbcTemplate(DataSource);
String sql="select * from emp where id=?";
Map<String,Object> map=template.query(sql,1);

查询一组数据封装到map中

JdbcTemplate template=new JdbcTemplate(DataSource);
String sql="select * from emp";
List<Map<String,Object>> list=template.queryForList(sql);

查询一组数据封装到list集合,里面对象就是emp类型

JdbcTemplate template=new JdbcTemplate(DataSource);
String sql="select * from emp";
List<Emp> list=template.query(sql,new BeanPropertyRowMapper<Emp>(Emp.class));

查询一组记录的个数

JdbcTemplate template=new JdbcTemplate(DataSource);
String sql="select count(id) from emp";
Long count=template.queryForObject(sql,Long.class);

Tomcat

  1. Tomcat的安装
    Tomcat的安装非常简单,直接解压即可,删除直接把软件目录删除就可以了。
    解压完成后可以看到:
    在这里插入图片描述

  2. Tomcat启动
    在bin目录下直接双击startup.bat
    在这里插入图片描述
    在浏览器上输入http://127.0.0.1:8080即可访问
    启动过程中可能存在的问题:
    ① 双击startup.bat一闪而过
    java的环境变量没有配置好
    ② 启动报错
    错误信息需要在logs目录下查看
    在这里插入图片描述
    在这里插入图片描述
    解决方法一:直接删除占用8080端口的进程
    Windows下输入命令

    netstat ano

    在这里插入图片描述
    打开任务管理器,选择“进程”|“选择列”
    在这里插入图片描述
    勾选进程标识符
    在这里插入图片描述
    找到5488这个进程,然后杀死即可
    方法二:修改自身端口号,不要使用8080端口,使用别的
    打开conf目录
    在这里插入图片描述
    修改为任意端口
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这里两个redirectPort是一样的端口号

    一般将Tomcat端口号修改为80,80端口号是http默认端口号,使用它就可以不用输入端口号就可以访问,要改的话,是上面的第二张图的Connector

    1. 关闭Tomcat
      ① 正常关闭:双击bin目录下的shutdown.bat或者在命令行窗口Ctrl+C
      ② 强制关闭:关闭窗口

Tomcat部署项目

  1. 直接将项目文件放入webapps目录下即可

  2. 将项目打成war包
    在这里插入图片描述
    自动解压缩
    在这里插入图片描述
    自动生成相应目录
    在这里插入图片描述
    如果要删除项目,直接删除war包即可

  3. 不拷贝文件完成部署
    打开conf/server.xml,找到标签,在标签下写上

    <Context docBase="D:/hello" path="/hehe/" />
    

    重启Tomcat,访问http://localhost/hehe/hello.html

  4. 在conf/Catalina/localhost目录下
    在该目录下创建bbb.xml,在里面编辑

    <!--这里不需要写Path-->
    <Context docBase="D:/hello">
    

    保存后重启Tomcat,访问http://bbb/hello.html
    使用这种方式还有一个好处是热部署,当不需要该项目资源文件,直接将bbb.xml修改为bbb.xml.bak即可,重新刷新页面会发现404
    而server.xml修改后要重启服务器才能生效,而且server.xml是全局,修改后可能会影响其他项目

Tomcat项目目录结构

  1. 在webapps目录下,存放多个项目,每个项目的目录里存放静态资源和动态资源
    具体目录结构如下:

    webapps
    |--LogWeb (LogWeb项目)
    	|-- 静态资源文件(HTML、css、js等)
    	|-- WEB-INFO
    		|-- web.xml (web项目的核心配置文件)
    		|-- classes目录 (放置编译好的字节码文件)
    		|-- lib 放置依赖的jar包
    

将Tomcat集成到IDE中

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建完项目后发现都自动生成对应的javaee项目目录
在这里插入图片描述
启动项目,Tomcat 8.3.31已经帮你添加好了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
之后启动的话,点击Tomcat 8.3.31的启动按钮即可
在这里插入图片描述
在这里插入图片描述
如果在这里新增加了一个hello.html
在这里插入图片描述
没有重启Tomcat,直接报404错误
在这里插入图片描述
这是需要重启Tomcat才能访问,可以在刚刚的Run|Edit Configuration…里配置
在这里插入图片描述
在这里插入图片描述
配置后在WEB-INFO中添加hehe.html
在这里插入图片描述
这个就是热部署,非常方便
在这里插入图片描述

Servlet

Servlet入门

  1. 当浏览器请求,为了响应请求需要执行java类,但是这些java类不是自动运行的,它没有main方法,需要依赖Tomcat执行。但是并不是随便一个类都能够被Tomcat识别并执行,它需要遵守一定的规则(其实在java里就是实现某个接口),而这里的规则(接口)就是Servlet
  2. 具体实现
    ① 创建Servlet类
    在这里插入图片描述
    ② 配置WEB-INFO目录下的web.xml
    在这里插入图片描述
    在浏览器上输入http://loaclhost/demo1
    页面上没有任何输出,但是在控制台上输出了“Hello Servlet”,说明service()方法被调用了
    另外,虽然直接访问http://loaclhost/demo1不加项目名比较方便,但是后期项目多就不合适了,因此需要配置虚拟目录
    在这里插入图片描述
    这样访问就需要http://localhost/day13_tomcat/demo1

Servlet执行原理

在这里插入图片描述

Servlet的生命周期

在这里插入图片描述
servlet生命周期详解:
① init() 创建Servlet
Servlet是什么时候被创建的?
在这里插入图片描述
另外,由于Servlet的init()只执行一次,因此他是单例对象,那么就可能存在多线程访问的安全问题
在这里插入图片描述
解决方法:
在Servlet中尽量少定义成员变量,改为定义局部变量,万不得已要定义成员变量,就不要修改它,只是读取
在这里插入图片描述
② 提供服务:service()
每次访问都会执行一次
③ 销毁: destroy()
它的执行是在servlet被销毁之前,可以把他理解为是遗言,释放资源

Servlet注解配置

  1. 之前每次创建一个servlet就在web.xml中配置一次,很麻烦,如果后期servlet很多就很混乱了,因此,Servlet3.0支持注解配置
  2. 具体步骤
    ① 使用Servlet3.0版本
    在这里插入图片描述
    ② 创建Servlet类
    在这里插入图片描述
    ③ 为Servlet类添加注解
    在这里插入图片描述
    在这里插入图片描述
    因此可以简写为
    在这里插入图片描述
    @WebServlet里面也可以配置多个路径
    在这里插入图片描述
    @WebServlet里其他配置
    在这里插入图片描述

Tomcat与IDE的配置

  1. IDEA会为每个Tomcat部署的项目单独创建一份配置文件
    在这里插入图片描述
    找到这个目录
    在这里插入图片描述
    进入conf
    在这里插入图片描述
    进入Catalina,它是规定项目day13_serlvet怎么部署和虚拟目录等信息
    在这里插入图片描述
    这个就是之前介绍的热部署方式
    在这里插入图片描述
    这里面记录了项目打成war包的存放路径,打开看看
    在这里插入图片描述
    在这里插入图片描述
  2. 项目存储位置(实际上是同一个项目存在两个地方)
    ① 工作空间项目
    ② Tomcat部署项目
    它位于我们刚刚打开的项目位置下
    在这里插入图片描述
    点开day13_servlet看看(工作空间)
    在这里插入图片描述
    点开out看看,里面存放项目被打成war包
    在这里插入图片描述
    在这里插入图片描述
    在这里,如果我们在IntelIJ中给项目添加上aaa.html,会发现他自动部署到Tomcat部署目录下
    在这里插入图片描述
    所以说,Tomcat是去查找Tomcat部署项目目录,Tomcat部署项目目录又对于这工作空间目录下的web目录(里面的WEB-INFO里的classes目录是对于工作空间下src目录编译后的java文件)
  3. WEB-INFO工作目录中的文件不能被浏览器直接访问
  4. Tomcat中如何断点调试
    在这里插入图片描述
    在这里插入图片描述

Servlet的体系结构

在使用Servlet接口,必须实现给定的五个方法(init等),但是我们实际上只需要使用里面的Service()方法,那么可以使用它的子类

Servlet 	接口
	|
GenericServlet 		抽象类
	|
HttpServlet			抽象类

使用GenericServlet发现代码清爽了很多
在这里插入图片描述
如果发现需要init()方法也可以复写
但是,我们一般使用HttpServlet,它对我们的http协议进行封装
这里继承HttpServlet不需要重写service( )方法,查看源码可以发现
在这里插入图片描述
这样就创建HttpServlet类
在这里插入图片描述

HTTP

HTTP

  1. 超文本传输协议
    在这里插入图片描述
    特点:
    ① 基于TCP/IP的高级协议
    ② 默认端口80
    ③ 基于请求/响应模型:一次请求一次响应
    ④ 无状态:每次请求相互独立,不能相互通信
    HTTP版本:
    ① 1.0:请求一次,响应后服务器和浏览器就断开连接
    ② 1.1:请求,响应后等一会,如果再有数据传输来,就复用连接
  2. 请求消息数据格式
    ① 请求行
    ② 请求头
    ③ 空行
    ④ 请求体
    在这里插入图片描述
  3. 响应消息数据格式
    ① 响应行
    ② 响应头
    ③ 响应空行
    ④ 响应体
    在这里插入图片描述

Request

  1. Request和Response原理
    在这里插入图片描述

  2. Request继承体系
    在这里插入图片描述

  3. Requset功能
    ① 获取请求消息数据
    获取请求行信息
    GET /day14/demo1?name=zhangsan HTTP/1.1

    //获取请求方式
    String  getMethod()
    //获取虚拟目录:/day14
    String getContextPath()
    //获取Servlet路径:/demo1
    String getServletPath()
    //获取GET请求数据 name=zhangsan
    String getQueryString()
    //获取请求URI /day14/demo1
    String getRequestURI() //返回/day14/demo1
    StringBuffer getRequestURL() //返回http://localhost/day14/demo1
    //获取版本号 HTTP/1.1
    String getProtocol()
    //获取客户机的IP
    String getRemoteAddr()
    

    获取请求头

    //获取请求头
    String getHeader(String name)
    //获取所有请求头名称
    Enumeration<String> getHeaderNames()
    

    获取请求体

    //获取字符流
    BufferReader getReader()
    //获取字节流
    ServletInputStream getInputStream()
    

    ② 其他功能
    获取请求参数(通用方式)

    //根据参数获取参数值,比如name=zhangsan
    String getParameter(String name)
    //根据参数获取参数值数组,比如hobby=run&hobby=sing
    String[] getParameterValues(String name)
    //返回参数名称
    Enumeration<String> getParameterNames()
    //返回所有参数的键值对集合
    Map<String,String[]> getParameterMap()
    

    在这里插入图片描述
    请求转发:在服务器里做资源跳转
    两种方式:
    第一种:

    //请求demo1,但是内部却将请求转发到demo2,这里使用同一个连接,可以看到forward()里原封不动地传递request和response
    request.getRequestDispatcher("/demo2").forword(request,response)
    

    特点:
    浏览器地址栏不变
    只能转发属于Tomcat里的资源
    使用一次请求

    共享数据
    一次请求,从AServlet转发到BServlet,是在一个request域中,因此可以创建一个域来让AServlet存入数据,BServlet取出数据

    void setAttribute(String name)
    String getAttribute()
    void removeAttribute(String name)
    

    因为转发是一次请求,所以共享数据一般用于转发
    获取ServletContext对象

    ServletContext getServletContext()
    

中文乱码问题

  1. Tomcat 8已经解决了Get方式的中文乱码问题
  2. POST方式就需要解决
    在这里插入图片描述

Response

  1. 响应消息数据格式

    1. 响应行
      HTTP/2.0 200 OK
      响应状态码
      服务端告诉浏览器本次请求响应的状态
      1xx:服务端接收客户端信息发现客户端发到一半不发了,发来询问客户端怎么回事?
      2xx:成功
      3xx:重定向 302(重定向) 304(访问缓存)
      4xx:客户端错误 404(请求资源路径不在) 405(请求方式没有对于的doXXX方法)
      5xx:服务器内部错误
    2. 响应头
      常见响应头
      ① Content-Type:响应体什么格式,什么编码
      text/html;charset=utf-8
      ② Content-disposition:服务器告诉客户端以什么方式打开响应体
      in-line:在当前页面打开(默认)
      attachment;filename=xx:以附件的形式打开响应体,常用于文件下载
    3. 响应空行
    4. 响应体
      在这里插入图片描述
  2. Response对象

    1. 设置响应行
      setStatus(int status)
    2. 设置响应头
      setHeader(String name,String value)
    3. 设置响应体
      getWriter( )
      getOutputStream( )
  3. 重定向

    response.sendRedirect("/day15/demo1");
    //它的实现核心代码是:
    //response.setStatus(302)
    //response.setHeader("location","/day15/demo1")
    

    特点:
    ① 地址栏改变
    ② 可以访问服务器以外的资源
    ③ 两次请求,request不能共享数据

  4. 相对路径和绝对路径
    ① 相对路径:通过路径不能唯一确定资源
    以 . 开头的路径,比如:
    当前路径:./demo1
    上一级路径: …/demo1
    ② 绝对路径:通过路径能唯一确定资源
    以 / 开头的路径
    /day15/demo1

    如果是给浏览器使用个,那么路径需要加虚拟目录(推荐使用动态获取虚拟目录的方式);如果是给服务器内部跳转用,不用加虚拟目录

  5. Response中文乱码问题
    在这里插入图片描述

  6. 生成图片验证码

    //创建一张内存图片
    BufferedImage image=new BufferedImage(width,height,TYPE_INT_RGB);
    //创建画笔
    Graphics g=image.getGraphics();
    //画笔一系列操作
    ImageIO.write(image,"jpg",response.getOutputStream())
    

ServletContext对象

  1. 它代表整个web应用程序,通过它可以和外部容器(Tomcat)通信(交互数据)

  2. 获取

    //方式一:通过request来获取
    request.getServletContext()
    //方式二:通过HttpServlet获取
    this.getServletContext()
    
  3. 作用

    1. 获取MIME类型

      //可以根据传入的文件名(如a.jpg),获取文件类型,之所以可以这样是因为在Tomcat中
      //的conf/web.xml中定义了所以MIME类型
      String getMineType(String filename)
      
    2. 共享数据

      //因为ServletContext存在的生命周期最长(从服务器启动到关闭),所以这个的使用要很谨慎
      void setAttribute(String key,String name)
      String getAttribute(String key)
      void removeAttribute(String key)
      
    3. 获取资源路径
      在这里插入图片描述

  4. 文件下载

    protected void doPost(HttpServletRequest request,HttpServletResponse response){
    	String filename=response.getParameter("filename");
    	ServletContext context=this.getServletContext();
    	FileInputStream fis=new FileInputStream(context.getRealPath("/img"+filename));
    		
    	response.setHeader("Content-Type",context.getMinaType(filename))
    	response.setHeader("Content-Disposition","attachment;filename="+filename)
    	
    	OutputStream os=response.getOutputStream();
    	byte[] bytes=new byte[1024];
    	int len=-1;
    	while((len=fis.read(bytes))>0){
    		os.write(bytes,0,len);
    	}	
    	//os由response打开,会自动关闭
    	fis.close();
    }
    

    如果filename是包含中文,那么可能会有乱码,通过以下代码解决:

    //agent:response.getHeader("user-agent")取得
    public String getFileName(String agent,String filename) throw UnsupportedEncodingException{
    	if(agent.contains("MSIE")){
    		//IE浏览器
    		filename=URLEncoder.encode(filename,"utf-8");
    		filename=filename.replace("+","");
    	}else if(agent.contains("Firefox")){
    		//火狐浏览器
    		BASE64Encoder base64Encoder=new BASE64Encoder();
    		filename="?utf-8?B"+base64Encoder.encode(filename.getBytes("utf-8"))+"?=";
    	}else{
    		//其他浏览器
    		filename=URLEncoder.encode(filename,"utf-8");
    	}
    	return filename;
    }
    

Cookie

  1. 快速入门

    //创建cookie
    Cookie cookie=new Cookie(String name,String value)
    //服务端发送cookie
    response.addCookie(Cookie cookie)
    //服务端获取浏览器携带的cookie
    Cookie[] cookies=request.getCookies()
    
  2. 实现原理

  3. cookie细节

    1. cookie存储多长时间

      //存储10秒
      cookie.setMaxAge(10)
      //关闭浏览器清除cookie(默认,cookie存储在浏览器内存中)
      cookie.setMaxAge(-1)
      //服务器告知浏览器删除cookie
      cookie.setMaxAge(0)
      
    2. cookie能不能存中文
      Tomcat 8之前不支持中文,要将中文用URL编码;Tomcat 8后支持中文

    3. cookie共享问题
      默认情况下,在Tomcat中不同web项目是不能cookie共享
      如果要共享,可以设置

      //默认是设置为cookie.setPath("/项目名"),只能被该项目下共享
      cookie.setPath("/")
      

      此外,不同Tomcat中的web项目也可以设置共享

      //它需要一级域名相同,news.baidu.com中news是二级域名,.baidu,com是一级域名
      cookie.setDomain(".baidu.com")
      
    4. cookie的特点和作用
      特点:
      ① cookie存储在浏览器
      ② 不同浏览器对cookie大小有限制
      作用:
      ① cookie一般用于少量不敏感信息
      ② cookie可以用于在不登录情况下做些设置

JSP

JSP原理

在这里插入图片描述
那么如何查看jsp就是一个Servlet类呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看index_jsp.java
在这里插入图片描述

JSP脚本

  1. <% 代码 %>
    在service()里能写的java代码,都可以写在里面,通过查看index_jsp.java可以发现
    这个代码是写在这个里面的
    在这里插入图片描述
  2. <%! 代码 %>
    一般是定义成员变量、静态代码块,它生成的代码位于index_jsp.java的成员变量位置,这种代码使用的比较少,因为在servlet中最好不要定义成员变量
    在这里插入图片描述
  3. <%= 代码 %>
    定义的代码会输出到页面上

JSP内置对象

  1. 在jsp中可以直接获取无需创建的对象
    在这里插入图片描述

Session

  1. Session入门

    //获取Session
    HttpSession session=request.getSession();
    //使用Session对象
    Object getAttribute(String name)
    setAttribute(String name,Object object)
    removeAttribute(String name)
    
  2. Session 细节

    1. 客户端关闭,服务端不关闭后再次访问服务端,两次Session是否一样?
      默认是不一样的,但是可以设置
      在这里插入图片描述
      结果
      在这里插入图片描述

    2. 客户端没关闭,服务端关闭,再次重启服务器两次Session一样吗?
      不是同一个,但是要保证两个Session数据一致
      Session钝化:将Session对象序列号到磁盘上
      Session活化:将Session对象反序列化恢复

      IntelIJ完成不了本地session的钝化,要借助Tomcat完成
      打开项目的Tomcat部署项目,找到项目war包里的内容,复制一份放到桌面上
      在这里插入图片描述
      将这三个文件打成war包
      在这里插入图片描述
      然后将这个war包丢到Tomcat的webapps目录下
      在这里插入图片描述
      停掉IDE里的Tomcat,然后启动本地的Tomcat,就是双击startup.bat文件
      访问http://loaclhost/day16/sessiondemo1在session中存入数据,访问http://localhost/day16/sessiondemo2取出session中的数据并打印
      在这里插入图片描述
      说明本地Tomcat启动正常,并且运行良好
      现在我们把Tomcat正常关闭,看看session是不是会被正常序列号到硬盘上
      双击shutdown.bat,正常关闭Tomcat
      查看Tomcat的work目录,里面存放运行的临时文件
      在这里插入图片描述
      然后启动Tomcat,观察该目录下的SESSIONS.ser
      在这里插入图片描述
      再次访问http://localhost/day16/sessiondemo2,打印“Hello Session”,session的活化成功

      在IDE中只能完成session钝化,不能活化session
      打开IDE的目录
      在这里插入图片描述
      里面有一个work目录
      在这里插入图片描述
      访问http://loaclhost/day16/sessiondemo1
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      再次访问http://loaclhost/day16/sessiondemo2,打印“null”

      因为后期都是在Tomcat里部署项目,所以完全不用担心IDE无法活化session

    3. session什么时候被销毁?
      ① 服务器关闭
      ② session.invalidate( )
      ③ 默认失效时间是30分钟
      在Tomcat的web.xml中可以配置
      在这里插入图片描述

  3. Session特点

    1. Session用于存储一次会话的多次请求的数据,存储在服务端
    2. Session可以存储任意类型,任意大小的数据,只要内存放的下

JSP指令

  1. JSP指令是用于配置页面和导入资源文件

  2. 快速入门
    格式:<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 %>
    在这里插入图片描述
    分类:
    ① page :配置JSP页面

    //等同于response.setContentType():设置响应体的MIMA类型和字符集
    contentType="text/html;charsetset=UTF-8"
    //比较鸡肋的属性,写上吧
    language="java"
    //jsp被编译后是通过out输出到页面上的,out是有缓冲区的,可以设置,默认8KB
    buffer="16kb"
    //jsp页面上会写一些java代码,用于导包
    import="java.util.List"
    //errorPage是加在当前页面上的,页面可能会出错,出错就跳转到404.jpg页面
    //isErrorPage是加在404.jsp页面,默认是false
    //如果为true,那么可以使用内置对象exception
    //String error =exception.getMessage();
    //一般是将错误信息输出到日志上
    errorPage="404.jsp"
    isErrorPage="true"
    

    ② include:包含页面和导入资源文件
    在这里插入图片描述
    在这里插入图片描述
    ③ taglib:导入资源文件库
    一般是导入标签库,比如JSTL标签库
    在这里插入图片描述
    创建WEB-INF/lib,为lib目录添加Library
    在这里插入图片描述
    在这里插入图片描述
    引入标签库
    在这里插入图片描述

ELT表达式

  1. ELT表达式是为了简化和替换JSP页面上的java代码
  2. 快速入门:
    语法:
    ${ 表达式 }
    <!--忽略ELT表达式-->
    \${ 表达式 }
    
  3. 使用
    1. 获取值
      el表达式只能从域对象中获取值
      ${域名称.键名}

      //如果取不到值,在页面上没有任何显示
      ${pageScope.name}
      ${requestScope.name}
      ${sessionScope.name}
      ${applicationScope.name}
      //从最小的域开始查起,直到找到为止
      ${name}
      
    2. 获取对象

      //定义User对象
      public class User{
      	private String name;
      	private Date birthday;
      	public void setName(String name){
      		this.name=name;
      	}
      	public String getName(){
      		return name;
      	}
      	public String getbirStr(){
      		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
      		return sdf.format(birthday);
      	}
      }
      //在jsp页面上可以通过这种方式取得,它的本质是通过getXXX来取值的
      ${user.name}
      //既然可以通过getXXX来这么取,那么只要在User中符合getXXX就可以了,比如:getbirStr()
      ${user.birStr}
      //获取list集合,但是如果角标越界了,它不会报错,在页面上没有显示
      ${list[0]}
      //获取map值,name是key
      ${map["name"]}
      //字符串、数组、集合判断是否为空或null
      ${empty list}
      //如果不为空
      ${not empty list}
      

JSP内置对象

  1. pageContext
  2. request
  3. session
  4. application
  5. page
  6. out
  7. config
  8. response
  9. exception
    在这里插入图片描述

JSTL

  1. JSTL是用来简化java代码

  2. 快速入门
    导入包
    在这里插入图片描述

    //test:如果为true,显示标签的内容;为false,不显示标签内容
    //<c:if>标签没有else的情况,只能再写一份
    <c:if test="${not empty list}">
    	遍历集合
    </c:if>
    
    //相当于java中的switch
    <c:choose>
    	<c:when test="${season==1}">春天</c:when>
    	<c:when test="${season==2}">夏天</c:when>
    	<c:when test="${season==3}">秋天</c:when>
    	<c:when test="${season==4}">冬天</c:when>
    	<c:otherwise>数字输入有误</c:otherwise>
    </c:choose>
    
    /*
    相当于java中的for循环
    for(int i=0;i<10;i++){
    }
    begin:初始值
    end:结束值
    var:临时变量(i)
    step:步长
    varStatus:循环状态对象
    	index:容器中的索引从0开始
    	count:循环次数从1开始
    */
    <c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
    	${i} ${s.index} ${s.count}
    </c:forEach>
    /*
    相当于java代码中的
    foreach(String item:list){
    }
    items:容器对象
    var:临时变量
    varStatus:循环状态对象
    	index:容器中的索引从0开始
    	count:循环次数从1开始
    */
    <c:forEach items="${list}" var="str" varStatus="s">
    	${str} ${s.index} ${s.count}
    </c:forEach>
    

过滤器

  1. 快速入门
    在这里插入图片描述

    具体使用:
    在这里插入图片描述

  2. 过滤器细节

    1. 可以使用web.xml配置
      在这里插入图片描述
    2. 过滤器请求流程
      在这里插入图片描述
    3. 过滤器生命周期
    public class FilterDemo1 implements Filter{
    	//服务器启动后Tomcat创建,只会执行一次,用于加载资源
    	public void init(FilterConfig filterConfig) throw ServletException{
    		
    	}
    	//每次请求执行一次,可以执行多次
    	public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain){
    		System.out.println("拦截器被执行了...");
    		filterChain.doFilter(servletRequest,servletResponse);
    	}
    	//服务器正常关闭执行,用于释放资源
    	public void destroy(){
    		
    	}
    }
    
    1. 过滤器拦截配置
      1. 拦截路径配置
        ① 具体资源路径:/index.jsp
        ② 拦截目录:/user/*
        ③ 后缀名拦截:*.jsp
        ④ 拦截所有资源:/*
        实例:
        过滤器FilterDemo4
        在这里插入图片描述
        在这里插入图片描述

      2. 拦截方式配置
        ① dispatcherTpyes.REQUEST:浏览器直接请求资源被拦下(默认)
        ②dispatcherTpyes.FORWARDS:只有Servlet内部互相转发被拦下
        ③dispatcherTpyes.INCLUDE:包含访问资源
        ④dispatcherTpyes.ERROR:jsp页面发生错误跳转到错误页面被拦下
        ⑤dispatcherTpyes.ASYNC:异步发送被拦下

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

    2. 拦截器链先后顺序
      1. 注解配置:按照类名字符串比较,值小的先执行
        如:AFilter和BFilter,AFilter先执行
      2. web.xml文件配置,谁先定义谁执行
  3. 登录案例

    @WebFilter("/*")
    public class LoginFilter implements Filter{
    	
    	public void init(FilterConfig filterConfig) throw ServletException{
    		
    	}
    	public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain){
    		//直接使用ServletRequest,它是没有getRequestURI()的方法
    		HttpServletRequest request=(HttpServletRequest)req;
    		String uri=request.getRequestURI();
    		//在如果仅仅包含/login.jsp和/loginServlet,那么访问的页面就会乱,没有验证码,因为请求被拦截了,index.jsp页面所需要的资源加载不出来
    		if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") ||uri.contains("/js/") ||uri.contains("/fonts/") ||uri.contains("/checkCodeServlet/") ){
    			//用户就是想登录,放行
    			chain.doFilter(servletRequest.servletResponse)
    		}else{
    			//用户可能已经登录过了,或者是非法登录
    			Object user=request.getSession().getAttribute("user")
    			if(user!=null){
    				//已经登录过,放行
    				chain.doFilter(servletRequest.servletResponse)
    			}else{
    				request.setAttribute("login_msg","你尚未登录")
    				request.getRequestDispatcher("/login.jsp").forward(request,servletResponse)
    			}
    			
    		}
    	
    	
    	}
    	public void destroy(){
    		
    	}
    }
    
  4. 敏感词过滤

//拦截器,请求http://localhost/TestServlet?name="张三"&msg="你是傻逼"
public class LoginFilter implements Filter{
	//从src目录下加载敏感词汇表,并在init()中加载
	private List<String> list=new ArrayList<String>();
	public void init(FilterConfig config) throw ServletException{
		//获取敏感文件的目录,需要用到服务器真实路径
		ServletContext servletContext=config.getServletContext()
		servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt")
		BufferedReader br=new BufferedReader(new FileReader(readPath))
		String line=null;
		while((line=br.readLine())!=null ){
			list.add(line)
		}
		br.close()
	}
	
	
	public void doFilter(ServletRequest req,ServletResponse resp,FilterChain chain){
		//创建代理对象,增强getParameter方法
		ServletRequest proxy_req=(ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader,req.getClass().getInterface(),new InvocationHandler(){
			//当在TestServlet中实际调用request.getParameter()时,会回调到这边来
			public Object invoke(Object proxy,Mehtod method,Object[] args)throws Throwable{
				//是getParameter方法,需要增强,用代理对象来执行
				if(method.getName().equals("getParameter")){
					//代理做一些边边角角的东西,还是要实际的req对象执行
					String value=(String) method.invoke(req,args)
					if(value!=null){
						for(String str:list){
							if(value.contains(str)){
								value=value.replaceAll(str,"**")
							}
						}
					}
					return value;
				}
				//不是getParameter()方法,不关心,直接用实际的req去执行就好
				return method.invoke(req,args)
			}
		})
		chain.doFilter(req.resp)
	}
	
	
	public void destroy(){
		
	}
}
//请求的Servlet
public class LoginFilter implements Filter{
	public void init(FilterConfig config) throw ServletException{

	}
	
	
	public void doFilter(ServletRequest req,ServletResponse resp,FilterChain chain){
		String name=req.getParameter("name")
		String msg=req.getParameter("msg")
		//敏感词会被过滤
		System.out.println(name+":"+msg)
	}
	
	
	public void destroy(){
		
	}
}

监听器Listener

  1. JavaWeb三大组件之一:Servlet、Filter、Listener

  2. ServletContextListener:监听ServletContext对象的创建和销毁

  3. 监听器机制
    首先得有事件——ServletContext对象的创建和销毁
    然后事件发生在Tomcat(事件源)中
    由ContextLoaderListener这个监听器来监听

    public class ContextLoaderListener implements ServletContextListener{
    	//监听ContextServlet对象的创建
    	public void contextInitialized(ServletContextEvent event){
    		//获取ServletContext对象
    		ServletContext context=event.getServletContext()
    
    		//在这里介绍一个Listener的应用,读取web.xml并初始化
    		String value=context.getInitParameter("contextConfig")
    		/*
    		在web.xml中是有如下配置
    		<context-param>
    			<param-name>contextConfig</param-name>
    			<param-value>/WEB-INF/classes/application.xml</param-value>
    		</context-param>
    		其实在以后并不需要开发监听器,而是使用web.xml配置监听器
    		*/
    		
    	}
    	//监听ContextServlet对象的销毁
    	public void contextDestroyed(ServletContextEvent event){
    		
    	}
    }
    

    有了这个监听器后,就需要将它注册到Tomcat中,负责监听ServletContext对象的创建和销毁
    ① 注解配置:@WebListener
    ② web.xml配置:

    <listener>
    	<listener-class>cn.itcast.web.listener.ContextLoaderListener </listener-class>
    <listener>
    

Redies

Redies安装

  1. Redies下载后直接解压即可
    在这里插入图片描述
  2. 先双击redis-server.exe,启动redies服务端
    在这里插入图片描述
  3. 双击redies-cli.exe,启动客户端
    在这里插入图片描述

通过命令行使用Redies

  1. Redies数据存储结构
    Redies的使用无非就是数据存取,因此需要了解redies的数据结构
    redies存储key-value格式数据,value类型可以很丰富
    key:String
    value:String、map、list(有序但可重复)、set(无序但不可重复)、SortSet(有序且不可重复)

  2. Redies命令

    //设置key-value
    SET name zhangsan
    //取值
    GET name
    //删除键值
    DEL name
    
    //设置键存活时间为1秒
    EXPIRE name 1
    //移除设置存活时间,使key永久有效,移除成功返回1;key不存在或者没有设置时间返回0
    PERSIST name
    
    //查询符合条件(pattern)的key
    KEYS run*
    //移动name这条记录到数据库1中,成功返回1,失败返回0(比如数据库1中压根就没有name,name,那么移动失败)
    MOVE name 1
    
    //返回key对于值的类型
    TYPE name
    

通过java操作Redies

  1. 快速入门

    1. 导包:commons-pool.jar和jedis.jar
    2. jedis的使用和命令行的使用相同
    	Jedis jedis=new Jedis("localhost",6379);
        jedis.set("name","张三");
        jedis.close();
    
    1. jedis连接池
    		JedisPoolConfig config=new JedisPoolConfig();
            config.setMaxTotal(100);
            JedisPool pool=new JedisPool(config,"localhost");
            //获取资源
            Jedis jedis = pool.getResource();
            jedis.set("name","张三");
            jedis.close();
    

Maven

Maven了解

  1. Maven能帮你构建工程、管理jar包、编译代码、自动运行单元测试打包生成报表、甚至能帮你部署web项目生成站点
  2. maven核心功能
    ① 依赖管理:maven将jar包放到仓库中,编译运行时通过jar坐标查找
    ② 一键构建:之前我们是通过本地Tomcat完成项目编译到部署一系列操作,现在是用集成在maven的Tomcat插件完成
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

Maven的安装

  1. maven直接下载并解压即可(apache-maven-3.5.2.zip)
  2. 解压后如下
    在这里插入图片描述
    逐一看看每个目录
    ① bin
    在这里插入图片描述
    ② boot
    在这里插入图片描述
    ③ conf
    在这里插入图片描述
  3. 复制解压后的目录(C:/my_java/apache-maven-3.5.2)
  4. 配置环境变量:
    MAVEN_HOME:C:/my_java/apache-maven-3.5.2
    Path:%MAVEN_HOME%/bin
  5. 安装完成
    在这里插入图片描述

Maven仓库种类

  1. maven仓库种类和彼此关系
    ① 打开C:/my_java/apache-maven-3.5.2/conf/setting.xml
    在这里插入图片描述
    图解:
    在这里插入图片描述
    在这里插入图片描述

maven目录结构

在这里插入图片描述
maven帮我们把这套标准弄好了
在这里插入图片描述

Maven常用命令

进入项目所在位置
在这里插入图片描述
命令行进入项目所在目录
在这里插入图片描述

<!--clean是将我们项目中编译好的信息删除掉,这个是下一个人接手上个人项目时,需要重新编译上一个人
的代码,因为不同人的机器上的环境是不一样的-->
mvn clean

在这里插入图片描述

<!--将核心代码(src/main/java)的代码进行编译,输出到traget目录下-->
mvn compile

在这里插入图片描述
查看target目录
在这里插入图片描述
在这里插入图片描述

//将核心代码和测试代码编译后输出到target目录
mvn test

在这里插入图片描述

//将项目打包输出到target目录下
mvn package

在这里插入图片描述
那为什么会被打成war包输出到target目录呢?
后退一级查看pom.xml文件
在这里插入图片描述
在这里插入图片描述

//除了做mvn package所做的事情,还将maven-helleworld-0.0.1-SNAPSHOT.war包安装到本地仓库中
mvn install

在这里插入图片描述
但是打开本地仓库目录

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

Maven生命周期

在这里插入图片描述

Maven的概念模型图

在这里插入图片描述

IDA中集成maven

打开setting
在这里插入图片描述
在这里插入图片描述

使用Maven创建项目

不使用骨架创建
在这里插入图片描述
在这里插入图片描述
创建完成后
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用Maven创建项目(不使用骨架)

在这里插入图片描述
在这里插入图片描述
推荐以后使用尽量不使用骨架

使用骨架创建web工程

在这里插入图片描述
在这里插入图片描述
创建完成
在这里插入图片描述
在这里插入图片描述
在main目录下创建java目录
在这里插入图片描述
默认maven是不允许java目录创建jsp页面
在这里插入图片描述
选择File|Project Structure…
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个了解即可,java目录下一般不要创建jsp

下面在java目录下新建com.itheima.servlet这个包,包下创建MyServlet类
在这里插入图片描述
打开pom.xml
在这里插入图片描述
也可以通过网上下载jar包
在这里插入图片描述
但是常用的jar包还是尽量本地仓库有
然后回头看,没有报错
在这里插入图片描述
启动项目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
访问浏览器,报错
在这里插入图片描述
因为maven自身集成了Tomcat插件,虽然我们不知道他集成的插件在哪里,但是它一定要依赖本地Tomcat的jar包,因此我们直接打开本地Tomcat安装目录
在这里插入图片描述
在这里插入图片描述
maven提供了一种解决冲突依赖的方法:
在这里插入图片描述
在这里插入图片描述

Maven集成Tomcat 7插件

Maven本身集成的Tomcat是版本6,现在修改为版本7
打开pom.xml文件
在这里插入图片描述
这样就将Tomcat 7修改好了
那原来的Tomcat 6还在吗?
答案是肯定的,那在哪里呢?下面来验证下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
而且我们也可以发现,同时运行着Tomcat 6和Tomcat 7
在这里插入图片描述
此外,访问http://localhost:8080/maven_web/MyServlet和http://localhost:8888/maven_web/MyServlet都是可以访问的

如果每次都要输入Tomcat 7插件的配置,一大段,很麻烦,可以提炼为动态模板
选择File|Settings…
在这里插入图片描述
先添加一个模板组——custom
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
指定maven的jdk插件
在这里插入图片描述

使用maven工程存取mysql

创建一个没有骨架的工程
pom.xml中配置mysql驱动包
在这里插入图片描述
但是是不是所有的包都要设置属性呢?
在这里插入图片描述
别忘了导入junit包

Linux

Linux上安装JDK

卸载Linux上自带的OpenJDK
在centOS 6.7自带jdk是openjdk
在这里插入图片描述
但是这不是我们想要的,卸载前要找到openjdk的位置

// -q是查看,-a是所有
rpm -qa | grep java

在这里插入图片描述

//这里说个小细节,对java-1.7.0-openjdk-1.7.0.79-2.5.5.4.e16.i686选中并右键,自动复制到光标处
rpm -e --nodeps java-1.7.0-openjdk-1.7.0.79-2.5.5.4.e16.i686
rpm -e --nodeps java-1.6.0-openjdk-1.6.0.35-1.13.7.1.e26_6.i686

验证是否卸载成功
在这里插入图片描述
安装jdk

mkdir /usr/local/java

事先上传jdk到Linux上,使用FileZilla-3.7.3
在这里插入图片描述
在这里插入图片描述
上传成功
在这里插入图片描述

// 不同的Linux版本不同,jdk安装需要,但有可能一些Linux已经安装好了
yum install glibc.i686
tar -xvf jdk-7u71-linux-i586.tat.gz -C /usr/local/java
cd /etc/profile

修改profile文件

JAVA_HOME=/usr/local/java/jdk1.7.0_71
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib.tools.jar
export JAVA_HOME PATH CLASSPATH

修改完后要重新加载下
在这里插入图片描述

source /etc/profile

Linux安装mysql

rpm -qa | grep mysql

在这里插入图片描述

rpm -e --nodeps mysql-libs-5.1/73-5.e16_6.i686

安装mysql

mkdir /usr/local/mysql
//上传的mysql安装包默认在用户目录下
cd ~
tar -xvf MYSQL-5.6.22-1.e16.i686.rpm-bundle.tar -C /usr/local/mysql

在这里插入图片描述

rpm -ivh MYSQL-server-5.6.22-1.e16.i686.rpm

在这里插入图片描述
安装依赖

yum -y install libaio.so.1 libgcc_.so.1 libstdc++.so.6

在这里插入图片描述
提示需要升级
在这里插入图片描述

yum update libstdc++-4.4.7-4.el6x86_64

准备工作做完后,安装mysql

cd /user/local/mysql
rpm -ivh MYSQL-server-5.6.22-1.el6.i686.rpm
rpm -ivh MYSQL-client-5.6.22-1-el6.i686.rpm

安装完成后验证

mysql

报错:
在这里插入图片描述
因为mysql服务没有启动

service mysql status

在这里插入图片描述

service mysql start

在这里插入图片描述
启动成功,可以连接,但是要输入密码
在这里插入图片描述

mysql -uroot -p

那默认密码是什么呢?
在这里插入图片描述
按照指定密码登录
在这里插入图片描述
提示修改密码
在这里插入图片描述

set password=password('123456');

退出后重新登录
这里需要设置mysql开机自动启动

chkconfig --add mysql
chkconfig mysql on
chkconfig

但是这里有个问题,就是安装后的mysql不支持远程连接,比如在Windows上通过客户端连接mysql

在这里插入图片描述
所以需要开启mysql远程登录

mysql -uroot -p

grant all privileges on *.* to 'root'@'%' identified by '123456';
flush privileges;

设置完成后仍然无法连接,因为Linux默认只开放22端口(ssh)

/sbin/iptables -l INPUT-p tcp --dport 3306 -j ACCEPT
//将设置永久保存到防火墙设置中
/etc/rc.d/init.d/iptables save
/etc/init.d/iptables status

这样就可以连接了

Windows上搭建Nginx+Tomcat集群

通过在本地复制两份Tomcat文件来模拟两个Tomcat,通过修改配置文件来避免端口冲突,将一份web项目的war包文件分别发送到两个Tomcat中
现在通过http://localhost:8080/web和http://localhost:8081/web都可以访问到,但是我们不可能访问同一个页面请求两个不同的地址,这就需要Nginx了
nginx直接解压即可
在这里插入图片描述
访问http://localhost:80
在这里插入图片描述
现在需要通过NGINX映射两个Tomcat的访问地址
修改nginx下的conf/nginx.conf
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改配置文件,就是新增下面这两段内容
在这里插入图片描述
重新加载nginx配置文件
在这里插入图片描述
通过访问http://localhost/test(nginx已经绑定80端口),nginx会自动将请求转发到两个Tomcat上,刷新多次可以看到请求不同的Tomcat,但是这也存在一个问题:session的id不同,无法共享session
在这里插入图片描述
在这里插入图片描述
解决方法:
① 每次请求后只让它访问并在一个Tomcat中操作
在这里插入图片描述
反复刷新浏览器,只会访问Tomcat2,除非换个浏览器重新访问
② 使用redies服务器共享session(推荐)
③ 使用Tomcat广播机制共享session(不推荐)
修改两个Tomcat的server.xml文件
在这里插入图片描述
在两个Tomcat中的项目web.xml文件中同时加入
在这里插入图片描述
重新启动Tomcat
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Linux上搭建Nginx+Tomcat集群

分别创建/usr/local/tomcat1和/usr/local/tomcat2,并解压两份Tomcat到这里面来
然后修改其中一个端口号,记得修改防火墙放行
安装nginx

//nginx是由C编写,因此需要依赖gcc编译
yum install gcc-c++
//PCRE是一个Perl库,包括Perl兼容的正则表达式库,nginx的http模块需要正则表达式库来解析,pcre-devel是pcre的二次开发库
yum install -y pcre pcre-devel
//zlib提供多种解压缩方式,nginx需要利用zlib对http包进行gzip
yum install -y zlib zlib-devel
//OpenSSL是一个强大的安全套接字层密码库,包含主要的密码算法、常用密钥和证书封装管理功能以及SSL协议
//nginx不仅支持http协议,也支持https协议,因此需要openssl
yum install -y openssl openssl-devel

解压nginx压缩包到/usr/local/nigix
在这里插入图片描述

//configure命令是用来检测你的安装平台的目标特征的。
//它定义了系统的各个方面,包括nginx的被允许使用的连接处理的方法,比如它会检测你是不是有CC或GCC,并不是需要CC或GCC
//它是个shell脚本,执行结束时,它会创建一个Makefile文件。
./configure
//make是执行编译,它从Makefile中读取指令,然后编译,生成目标文件、最终的二进制文件。
make
//make install是用来安装的,它也从Makefile中读取指令,安装到指定的位置。
//其根据configure命令执行时的参数将Nginx部署到指定的安装目录,包括相关目录的建立和二进制文件、配置文件的复制。
make install

在这里插入图片描述
安装完毕后会有个sbin目录,进入里面

./nignx

在这里插入图片描述
查询是否安装成功

ps aux|grep nginx

在这里插入图片描述
修改nginx配置文件,重新加载nginx
修改防火墙规则,放出80端口
在浏览器上访问http://192.168.0.12
关闭nginx

./nginx -s stop

退出nginx

./nginx -s quit

修改了配置文件要重新加载nginx

./nginx -s reload
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值