2006-京淘Day08

1. 文件上传优化

1.1 url优化

说明: 如果需要通过网络虚拟路径访问服务器.则应该按照如下的配置实现.

  1. 本地磁盘路径: D:\JT-SOFT\images\2020\09\30\a.jpg
  2. 网络虚拟路径: http://image.jt.com\2020\09\30\a.jpg
  3. 1.2 编辑pro配置文件

  4. 1.3 完成属性的动态赋值

  5. package com.jt.service;

    import com.jt.vo.ImageVO;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.stereotype.Service;
    import org.springframework.web.multipart.MultipartFile;

    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.UUID;

    @Service
    @PropertySource("classpath:/properties/images.properties") //容器动态加载指定的配置文件
    public class FileServiceImpl implements FileService{

        //由于属性的值后期可能会发生变化,所以应该动态的获取属性数据. 利用pro配置文件
        @Value("${image.rootDirPath}")
        private String rootDirPath;             //   = "D:/JT-SOFT/images";
        @Value("${image.urlPath}")
        private String urlPath;                 // = "http://image.jt.com";

        //1.2 准备图片的集合  包含了所有的图片类型.
        private static Set<String> imageTypeSet;
        static {
            imageTypeSet = new HashSet<>();
            imageTypeSet.add(".jpg");
            imageTypeSet.add(".png");
            imageTypeSet.add(".gif");
        }


        /**
         * 完善的校验的过程
         * 1. 校验是否为图片
         * 2. 校验是否为恶意程序
         * 3. 防止文件数量太多,分目录存储.
         * 4. 防止文件重名
         * 5. 实现文件上传.
         * @param uploadFile
         * @return
         */
        @Override
        public ImageVO upload(MultipartFile uploadFile) {
            //0.防止有多余的空格 所以先做去空格的处理
            rootDirPath.trim();
            urlPath.trim();

            //1.校验图片类型  jpg|png|gif..JPG|PNG....
            //1.1 获取当前图片的名称 之后截取其中的类型.   abc.jpg
            String fileName = uploadFile.getOriginalFilename();
            int index = fileName.lastIndexOf(".");
            String fileType = fileName.substring(index);
            //将数据转化为小写
            fileType = fileType.toLowerCase();
            //1.3 判断图片类型是否正确.
            if(!imageTypeSet.contains(fileType)){
                //图片类型不匹配
                return ImageVO.fail();
            }

            //2.校验是否为恶意程序 根据宽度/高度进行判断
            try {
                //2.1 利用工具API对象 读取字节信息.获取图片对象类型
                BufferedImage bufferedImage = ImageIO.read(uploadFile.getInputStream());
                //2.2 校验是否有宽度和高度
                int width = bufferedImage.getWidth();
                int height = bufferedImage.getHeight();
                if(width==0 || height==0){
                    return ImageVO.fail();
                }

                //3.分目录存储  yyyy/MM/dd 分隔
                //3.1 将时间按照指定的格式要求 转化为字符串.
                String dateDir = new SimpleDateFormat("/yyyy/MM/dd/")
                                 .format(new Date());
                //3.2 拼接文件存储的目录对象
                String fileDirPath = rootDirPath + dateDir;
                File dirFile = new File(fileDirPath);
                //3.3 动态创建目录
                if(!dirFile.exists()){
                    dirFile.mkdirs();
                }

                //4.防止文件重名  uuid.jpg 动态拼接
                //4.1 动态生成uuid  实现文件名称拼接  名.后缀
                String uuid =
                        UUID.randomUUID().toString().replace("-", "");
                String realFileName = uuid + fileType;

                //5 实现文件上传
                //5.1 拼接文件真实路径 dir/文件名称.
                String realFilePath = fileDirPath + realFileName;
                //5.2 封装对象  实现上传
                File realFile = new File(realFilePath);
                uploadFile.transferTo(realFile);

                //实现文件上传成功!!! http://image.jt.com\2020\09\30\a.jpg
                String url = urlPath + dateDir + realFileName;
                return ImageVO.success(url,width,height);
            } catch (IOException e) {
                e.printStackTrace();
                return ImageVO.fail();
            }
        }
    }
     

  6. 2 反向代理机制说明

    2.1 为什么需要反向代理

    需求:当完成文件上传时,业务返回页面的是虚拟地址路径
    url地址: http://image.jt.com/2020/09/30/a.jpg
    真实图片地址: file:///D:/JT-SOFT/image/2020/09/30/d534bed912c748b0ac979ee40222490a.jpg
    问题: 如何让用户通过url访问 找到真实的磁盘地址的图片.

  7. 2.2 反向代理机制

    2.2.1 反向代理介绍

    反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,也无须在用户端作任何设定。反向代理服务器通常可用来作为Web加速,即使用反向代理作为Web服务器的前置机来降低网络和服务器的负载,提高访问效率。
    概括:
    1.位于用户(客户端)-服务器之间.
    2.用户访问反向代理服务器,以为是真实的服务器信息.
    3.用户根本不清楚真实的服务器信息到底是谁.
    4.一般反向代理机制保护了真实的服务器信息,所以也称之为服务器端代理.

  8. 2.3 正向代理机制

    2.3.1 需求引入

    1.宽带: 电信运营商 账号/密码 只能被一台机器使用.
    2.路由器: 在家庭的内部创建了局域网 使得局域网中的设备可以通过路由器的功能与外界通信.

    2.3.2 正向代理介绍

    正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。
    总结:
    1.正向代理位于客户与服务器之间
    2.客户端在发起请求之前 确定了目标服务器的地址.
    3.服务器不清楚到底是哪台客户端访问的我,以为只是路由器访问的.
    4.正向代理保护了客户的信息,所以也称之为 客户端代理

  9.  

     

     

    .4 Nginx

    2.4.1 Nginx介绍

    Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
    其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
    **Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,**在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

    特点:
    1.内存少 不超过2M tomcat服务器大约占用600M
    2.并发能力强 3-5万次/秒 tomcat服务器大约 150-220之间

  10.  

     

    2.4.2 Nginx安装使用
  11.  

     

     

     

     

    注意事项:
    1. 不要将nginx放到C盘及系统目录中 注意中文路径和空格.
    2. nginx服务器启动的速度特别快, 窗口会闪退 只启动一次即可
    3. nginx启动会占用80端口.
    4. nginx命令的运行必须在nginx.exe所在的目录中执行.
  12.  

     

    2.4.2 Nginx命令

    1).启动命令 start nginx
    2).重启命令 nginx -s reload
    3).停止命令 nginx -s stop

    2.4.3 Nginx服务器启动项说明

  13.  

     

     

     

     

  14. 2.4.4 关于nginx反向代理说明


http {
    # 一个反向代理就是一个server
    server {
        #监听 80端口
        listen       80;
        #监听的域名  域名不能重复.
        server_name  localhost;
        #执行的反向代理的动作   / 拦截所有的路径
        location / {
            # root关键字  代理的是一个目录
            root   html;
            #默认跳转页面
            index  index.html index.htm;
        }    
    }

}

 

2.5 Nginx实现图片回显

2.5.1 NGINX配置

# 图片服务器代理   image.jt.com:80
    server {
        listen 80;
        server_name image.jt.com;

        location / {
            # 转向目录
            root D:/JT-SOFT/images;
        }
    }
 

2.5.2 修改hosts文件

1.HOSTS文件的说明:

2.HOSTS文件的位置

3).以超级管理员身份运行

# 京淘配置  
#左侧写IP地址   右侧写域名  中间使用空格分隔
127.0.0.1   image.jt.com
127.0.0.1   manage.jt.com

#实现 nginx的
#192.168.126.129   image.jt.com
#192.168.126.129   manage.jt.com
127.0.0.1   www.jt.com
#Bug 有时在使用该软件时可能会出现丢失字母的现象.
127.0.0.1   sso.jt.com

3.nginx实现tomcat集群部署

3.1 项目部署

 

3.2 服务器反向代理

    #配置京淘后台管理服务器
    # manage.jt.com  localhost:8091服务器
    server {
        listen 80;
        server_name manage.jt.com;

        location / {

            #映射服务器
            proxy_pass  http://localhost:8091;
        }
    }

修改nignx服务器之后,重启nginx

 

3.3 动态获取当前服务器端口号

@RestController
public class PortController {

    //从spring服务器中动态的获取端口号
    @Value("${server.port}")
    private Integer port;

    @RequestMapping("/getPort")
    public String getPort(){

        return "当前服务器访问的端口号:"+port;
    }
}
 

3.4 项目打包

之后从项目的target目录中动态获取jar包文件 准备集群部署.

3.4 项目发布命令

注意事项: 当前的命令执行 会占用dos命令窗口 打印控制台信息. 当dos命令窗口关闭 服务器停止.
退出dos命令窗口: ctrl + c

java:     java     -jar   8081.war 
 

3.4 nginx负载均衡实现

3.4.1 轮询机制

说明: 按照配置文件的顺序 依次访问服务器.

#配置京淘后台管理服务器
    # manage.jt.com  localhost:8091服务器
    server {
        listen 80;
        server_name manage.jt.com;

        location / {

            #映射服务器
            #proxy_pass  http://localhost:8091;
            proxy_pass   http://jtWindows;    
        }
    }

    # 配置tomcat服务器集群  1.轮询策略
    upstream jtWindows {

        #server代表服务器地址
        server 127.0.0.1:8081;
        server 127.0.0.1:8082;    
    }
 

3.4.2 权重机制

说明: 按照权重的设置,让性能更优的服务器多处理请求.

# 配置tomcat服务器集群  1.轮询策略  2.权重策略
    upstream jtWindows {

        #server代表服务器地址
        server 127.0.0.1:8081 weight=8;
        server 127.0.0.1:8082 weight=2;    
    }
 

3.4.3 IPHASH策略(了解)

由于某些数据与服务器进行了绑定,则后来必须要求用户访问指定的服务器时,使用IPHASH策略

 

# 配置tomcat服务器集群  1.轮询策略  2.权重策略  3.iphash策略
    upstream jtWindows {

        #server代表服务器地址
        ip_hash;
        server 127.0.0.1:8081 weight=8;
        server 127.0.0.1:8082 weight=2;    
    }
 

作业

1.安装VMware虚拟机程序

2.检查网卡设置
如果没有网卡 则换一个vmwar版本安装…

 

3. 启动Linux系统

问题描述:
进入BIOS系统中 开启虚拟化设置即可. 主板系统 开机 F1/F2…

 

 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <artifactId>jt-sso</artifactId>
    <!--默认的打包方式就是jar 不写也没有关系-->
    <packaging>jar</packaging>
    <parent>
        <artifactId>jt</artifactId>
        <groupId>com.jt</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!--
        添加依赖信息
    -->

    <dependencies>
        <dependency>
            <!--依赖实质依赖的是jar包文件-->
            <groupId>com.jt</groupId>
            <artifactId>jt-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>

    <!--3.添加插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 

server:
  port: 8093
  servlet:
    context-path: /
spring:
  datasource:
    #引入druid数据源
    #type: com.alibaba.druid.pool.DruidDataSource
   #driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root

  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
#mybatis-plush配置
mybatis-plus:
  type-aliases-package: com.jt.pojo
  mapper-locations: classpath:/mybatis/mappers/*.xml
  configuration:
    map-underscore-to-camel-case: true

logging:
  level: 
    com.jt.mapper: debug

#关于Dubbo配置
dubbo:
  scan:
    basePackages: com.jt    #指定dubbo的包路径 扫描dubbo注解
  application:              #应用名称
    name: provider-user     #一个接口对应一个服务名称 一个接口可以有多个实现
  registry: #注册中心 用户获取数据从从机中获取 主机只负责监控整个集群 实现数据同步
    address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
  protocol:  #指定协议
    name: dubbo  #使用dubbo协议(tcp-ip)  web-controller直接调用sso-Service
    port: 20880  #每一个服务都有自己特定的端口 不能重复.

 

package com.jt;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.jt.mapper")
public class SpringBootRun {

    public static void main(String[] args) {

        SpringApplication.run(SpringBootRun.class, args);
    }
}

 

package com.jt.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.User;

public interface UserMapper extends BaseMapper<User> {

}

 

package com.jt.service;

import com.jt.pojo.User;

import java.util.List;

public interface UserService {
    List<User> findUserAll();

    boolean checkUser(String param, Integer type);
}

 

package com.jt.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import com.jt.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import redis.clients.jedis.JedisCluster;

import java.util.UUID;

@Service(timeout = 3000)
public class DubboUserServiceImpl implements DubboUserService{

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private JedisCluster jedisCluster;


    /**
     * 注意事项:
     * 1.暂时使用电话号码代替邮箱
     * 2.密码进行md5加密
     * 3.入库操作注意事务控制
     * @param user
     */
    @Override

    public void saveUser(User user) {

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

    /**
     * 1.获取用户信息校验数据库中是否又记录
     * 2.有 开始执行单点击登陆流程
     * 3.没有 直接返回空即可
     *
     *
     * @param user
     * @return
     */
    @Override
    public String doLogin(User user) {//username/password
        //1.将明文加密
        String md5Pass=
                DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        user.setPassword(md5Pass);
        QueryWrapper<User> queryWrapper=new QueryWrapper<>(user);
        //根据对象中不为null的属性当做where条件
        User userDB=userMapper.selectOne(queryWrapper);
        if (userDB==null){
            //用户名或者密码错误
            return null;
        }else {//用户名和密码正确 实现单点击登陆操作
            String ticket= UUID.randomUUID().toString();
            //如果将数据保存到第三方 一般需要脱敏处理
            userDB.setPassword("123456你信不?");

            String userJSON= ObjectMapperUtil.toJSON(userDB);
            jedisCluster.setex(ticket, 7*24*60*60, userJSON);
            return ticket;
        }

    }
}

 

package com.jt.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService{

    private static Map<Integer,String> columnMap=new HashMap();
    static {
        columnMap.put(1,"username");
        columnMap.put(2,"phone");
        columnMap.put(3,"email");
    }

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<User> findUserAll() {
        return userMapper.selectList(null);
    }

    /**
     * 判断依据:根据用户名查询 如果结果>0用户已存在
     * @param param
     * @param type
     * @return
     */
    @Override
    public boolean checkUser(String param, Integer type) {

        /**
         * 1.需要将type类型转化为 具体字段信息
         * 1=username 2=phone 3=email
         */
        String column=columnMap.get(type);
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq(column,param);
        Integer count=userMapper.selectCount(queryWrapper);
        return count>0?true:false;
    }
}

 

package com.jt.controller;

import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.util.CookieUtil;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisCluster;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private JedisCluster jedisCluster;


    /**
     * 完成测试按钮
     * 1.url地址:findUserAll
     * 2.参数信息:null
     * 3.返回值结果:List<User>
     *
     */

    @RequestMapping("/findUserAll")
    public List<User> findUserAll(){

        return userService.findUserAll();
    }


    /**
     * 业务说明:
     * jt-web服务器获取jt-sso数据 JSONP跨域请求
     * url地址:http://sso.jt.com/user/check/{param}/{type}
     * 返回值:SysResult对象
     * 真实的返回值:callback(SysResult的JSON)
     */

    @RequestMapping("/check/{param}/{type}")
    public JSONPObject checkUser(@PathVariable String param,
                                 @PathVariable Integer type,
                                 String callback){

        //true表示数据存在   false表示数据可以使用
        boolean flag=userService.checkUser(param,type);
        SysResult.success(flag);
        return new JSONPObject(callback, SysResult.success(flag));
    }

    /**
     * 业务实现:
     * 1.用户通过cookie信息查询用户数据。通过ticket获取redis中的业务数据
     * 2.url请求:http://sso.jt.com/user/query/+_ticket
     * 3.参数: 参数在url中,利用restFul获取
     * 4.返回值要求:SysResult对象(userJSON)
     */

    @RequestMapping("/query/{ticket}")
    public JSONPObject findUserByTicket(@PathVariable String ticket,
                                        HttpServletResponse response,
                                        String callback){

        String userJSON=jedisCluster.get(ticket);
        /**
         * 1.lur算法清空数据
         * 2.有可能cookie信息有误
         *
         */
        if (StringUtils.isEmpty(userJSON)){

            //2.应该删除cookie信息
//            Cookie cookie=new Cookie("JT_TICKET", "");
//            cookie.setMaxAge(0);
//            cookie.setDomain("jt.com");
//            cookie.setPath("/");
//            response.addCookie(cookie);
            CookieUtil.deleteCookie(response, "JT_TICKET", "jt.com");
            return new JSONPObject(callback,SysResult.fail());
        }
        return new JSONPObject(callback,SysResult.success(userJSON));
    }


}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值