服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 超详细讲解Java秒杀项目用户验证模块的实现

超详细讲解Java秒杀项目用户验证模块的实现

2022-10-08 15:26爱嘤斯塔 Java教程

这是一个主要使用java开发的秒杀系统,项目比较大,所以本篇只实现了用户验证模块,代码非常详尽,感兴趣的朋友快来看看

接着上期内容超详细讲解Java秒杀项目登陆模块的实现

一、用户验证

未登录的用户不能进入首页

根据上期内容,我未登录也能进入首页:

超详细讲解Java秒杀项目用户验证模块的实现

1、在方法内添加请求与反应

①、IUserService

package com.example.seckill.service;

import com.example.seckill.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.seckill.util.response.ResponseResult;
import com.example.seckill.vo.UserVo;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* <p>
* 用户信息表 服务类
* </p>
*
* @author lv
* @since 2022-03-15
*/
public interface IUserService extends IService<User> {

  ResponseResult<?> findByAccount(UserVo userVo, HttpServletRequest request, HttpServletResponse response);
}

②、UserServiceImpl

超详细讲解Java秒杀项目用户验证模块的实现

③、UserController

package com.example.seckill.controller;

import com.example.seckill.service.IUserService;
import com.example.seckill.util.response.ResponseResult;
import com.example.seckill.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

/**
* <p>
* 用户信息表 前端控制器
* </p>
*
* @author lv
* @since 2022-03-15
*/
@RestController
@RequestMapping("/user")
public class UserController {

  @Autowired
  private IUserService userService;

//    用户登录
  @RequestMapping("/login")
public ResponseResult<?> login(@Valid UserVo userVo, HttpServletRequest request, HttpServletResponse response){
//     调用service的登录验证
   return userService.findByAccount(userVo,request,response);
}
}

2、cookie操作的封装

package com.example.seckill.util;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

@Slf4j
public class CookieUtils {

  /**
   * @Description: 得到Cookie的值, 不编码
   */
  public static String getCookieValue(HttpServletRequest request, String cookieName) {
      return getCookieValue(request, cookieName, false);
  }

  /**
   * @Description: 得到Cookie的值
   */
  public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
      Cookie[] cookieList = request.getCookies();
      if (cookieList == null || cookieName == null) {
          return null;
      }
      String retValue = null;
      try {
          for (int i = 0; i < cookieList.length; i++) {
              if (cookieList[i].getName().equals(cookieName)) {
                  if (isDecoder) {
                      retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
                  } else {
                      retValue = cookieList[i].getValue();
                  }
                  break;
              }
          }
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      }
      return retValue;
  }

  /**
   * @Description: 得到Cookie的值
   */
  public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
      Cookie[] cookieList = request.getCookies();
      if (cookieList == null || cookieName == null) {
          return null;
      }
      String retValue = null;
      try {
          for (int i = 0; i < cookieList.length; i++) {
              if (cookieList[i].getName().equals(cookieName)) {
                  retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
                  break;
              }
          }
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      }
      return retValue;
  }

  /**
   * @Description: 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) {
      setCookie(request, response, cookieName, cookieValue, -1);
  }

  /**
   * @Description: 设置Cookie的值 在指定时间内生效,但不编码
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage) {
      setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
  }

  /**
   * @Description: 设置Cookie的值 不设置生效时间,但编码
   * 在服务器被创建,返回给客户端,并且保存客户端
   * 如果设置了SETMAXAGE(int seconds),会把cookie保存在客户端的硬盘中
   * 如果没有设置,会默认把cookie保存在浏览器的内存中
   * 一旦设置setPath():只能通过设置的路径才能获取到当前的cookie信息
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
                               String cookieValue, boolean isEncode) {
      setCookie(request, response, cookieName, cookieValue, -1, isEncode);
  }

  /**
   * @Description: 设置Cookie的值 在指定时间内生效, 编码参数
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
      doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
  }

  /**
   * @Description: 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
   */
  public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
                               String cookieValue, int cookieMaxage, String encodeString) {
      doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
  }

  /**
   * @Description: 删除Cookie带cookie域名
   */
  public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,
                                  String cookieName) {
      doSetCookie(request, response, cookieName, null, -1, false);
  }


  /**
   * @Description: 设置Cookie的值,并使其在指定时间内生效
   */
  private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
      try {
          if (cookieValue == null) {
              cookieValue = "";
          } else if (isEncode) {
              cookieValue = URLEncoder.encode(cookieValue, "utf-8");
          }
          Cookie cookie = new Cookie(cookieName, cookieValue);
          if (cookieMaxage > 0)
              cookie.setMaxAge(cookieMaxage);
          if (null != request) {// 设置域名的cookie
              String domainName = getDomainName(request);
              log.info("========== domainName: {} ==========", domainName);
              if (!"localhost".equals(domainName)) {
                  cookie.setDomain(domainName);
              }
          }
          cookie.setPath("/");
          response.addCookie(cookie);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  /**
   * @Description: 设置Cookie的值,并使其在指定时间内生效
   */
  private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
                                        String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
      try {
          if (cookieValue == null) {
              cookieValue = "";
          } else {
              cookieValue = URLEncoder.encode(cookieValue, encodeString);
          }
          Cookie cookie = new Cookie(cookieName, cookieValue);
          if (cookieMaxage > 0)
              cookie.setMaxAge(cookieMaxage);
          if (null != request) {// 设置域名的cookie
              String domainName = getDomainName(request);
              log.info("========== domainName: {} ==========", domainName);
              if (!"localhost".equals(domainName)) {
                  cookie.setDomain(domainName);
              }
          }
          cookie.setPath("/");
          response.addCookie(cookie);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }

  /**
   * @Description: 得到cookie的域名
   */
  private static final String getDomainName(HttpServletRequest request) {
      String domainName = null;

      String serverName = request.getRequestURL().toString();
      if (serverName == null || serverName.equals("")) {
          domainName = "";
      } else {
          serverName = serverName.toLowerCase();
          serverName = serverName.substring(7);
          final int end = serverName.indexOf("/");
          serverName = serverName.substring(0, end);
          if (serverName.indexOf(":") > 0) {
              String[] ary = serverName.split("\\:");
              serverName = ary[0];
          }

          final String[] domains = serverName.split("\\.");
          int len = domains.length;
          if (len > 3 && !isIp(serverName)) {
              // www.xxx.com.cn
              domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
          } else if (len <= 3 && len > 1) {
              // xxx.com or xxx.cn
              domainName = "." + domains[len - 2] + "." + domains[len - 1];
          } else {
              domainName = serverName;
          }
      }
      return domainName;
  }

  public static String trimSpaces(String IP) {//去掉IP字符串前后所有的空格
      while (IP.startsWith(" ")) {
          IP = IP.substring(1, IP.length()).trim();
      }
      while (IP.endsWith(" ")) {
          IP = IP.substring(0, IP.length() - 1).trim();
      }
      return IP;
  }

  public static boolean isIp(String IP) {//判断是否是一个IP
      boolean b = false;
      IP = trimSpaces(IP);
      if (IP.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")) {
          String s[] = IP.split("\\.");
          if (Integer.parseInt(s[0]) < 255)
              if (Integer.parseInt(s[1]) < 255)
                  if (Integer.parseInt(s[2]) < 255)
                      if (Integer.parseInt(s[3]) < 255)
                          b = true;
      }
      return b;
  }
}

3、UserServiceImpl

//          最初版本(session),但Session内数据是服务器共用的
//        所有不让名字重复
      String ticket=UUID.randomUUID().toString().replace("-","");
      request.getSession().setAttribute(ticket,user);
//        将生成的ticket给用户,用户如何验证?使用cookie
      CookieUtils.setCookie(request,response,"ticket",ticket);

点击登录时,查看应用程序,cookie内有值

超详细讲解Java秒杀项目用户验证模块的实现

4、跳转界面PathController

跳转方法:

//    跳所有二级页面
  @RequestMapping("/{dir}/{path}")
  public String toPath(@PathVariable("dir") String dir, @PathVariable("path") String path, HttpServletRequest request){
      String ticket= CookieUtils.getCookieValue(request,"ticket");
      if(ticket==null){
          throw new BusinessException(ResponseResultCode.TICKET_ERROR);
      }
//        去session中取到ticket对应的用户,判断是否有值
      Object obj=request.getSession().getAttribute(ticket);
      if(obj==null){
          throw new BusinessException(ResponseResultCode.TICKET_ERROR);

      }

      return dir+"/"+path;
  }

未登录时访问主界面失败:只有登录成功后才能访问

超详细讲解Java秒杀项目用户验证模块的实现

 

二、全局session

根据以上操作完后,session仍然有问题,,session只能在当前某一台服务器中,

需使用第三者完成数据共享,此处使用redis方式,将需要缓存的数据丢到缓存内

1、导入依赖

此处全局session是spring session中的一个,spring session就是spring中的一个文件

<!--commons-pool2-->
      <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-pool2</artifactId>
      </dependency>
      <!--spring-session将session借助于第三方存储(redis/mongodb等等),默认redis-->
      <dependency>
          <groupId>org.springframework.session</groupId>
          <artifactId>spring-session-data-redis</artifactId>
      </dependency>

2、配置yml文件redis

spring:
redis:
host: 47.100.191.44
password: xiaoli_redis
database: 0
port: 6379

超详细讲解Java秒杀项目用户验证模块的实现

3、开启虚拟机

现在开启虚拟机

 

三、自定义redis实现功能

完成全局session的作用

1、新建RedisConfig文件

用于操作redis

package com.example.seckill.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

  public RedisTemplate redisTemplate(RedisConnectionFactory factory){
//        新建一个
      RedisTemplate redisTemplate=new RedisTemplate();
      //设置一下使用连接工厂
      redisTemplate.setConnectionFactory(factory);
//        额外设置
//        将key序列化操作,转化为string
      redisTemplate.setKeySerializer(new StringRedisSerializer());
//        value被转化为json
      redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//          额外设置(hash 就是 map集合)
      redisTemplate.setHashKeySerializer(new StringRedisSerializer());
      redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
//        让设置生效
      redisTemplate.afterPropertiesSet();
      
      return redisTemplate;

  }

}

2、实现全局session

①、写个帮助类,用于调用

IRedisService接口:

package com.example.seckill.service;

import com.example.seckill.pojo.User;

public interface IRedisService {

  void putUserByTicket(String ticket, User user);

  User getUserByTicket(String ticket);

}

实现接口:

package com.example.seckill.service.impl;

import com.example.seckill.pojo.User;
import com.example.seckill.service.IRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class RedisServiceImpl implements IRedisService {

  @Autowired
  private RedisTemplate redisTemplate;

  @Override
  public void putUserByTicket(String ticket, User user) {
      redisTemplate.opsForValue().set("user:"+ticket,user,2L, TimeUnit.HOURS);
  }

  @Override
  public User getUserByTicket(String ticket) {
      Object obj=redisTemplate.opsForValue().get("user:"+ticket);
      if(obj==null || !(obj instanceof User)){
          return null;
      }
      return (User)obj;
  }
}

②、redisService到缓存中拿元素

  @Autowired
  private IRedisService redisService;

//    跳所有二级页面
  @RequestMapping("/{dir}/{path}")
  public String toPath(@PathVariable("dir") String dir, @PathVariable("path") String path, HttpServletRequest request){
//        获取用户的ticket
      String ticket= CookieUtils.getCookieValue(request,"ticket");
      if(ticket==null){
          throw new BusinessException(ResponseResultCode.TICKET_ERROR);
      }
//        去session中取到ticket对应的用户,判断是否有值
//        Object obj=request.getSession().getAttribute(ticket);
//        去缓存中拿元素
      User user=redisService.getUserByTicket(ticket);
      if(user==null){
          throw new BusinessException(ResponseResultCode.TICKET_ERROR);

      }
      return dir+"/"+path;
  }

③、放到缓存中

UserServiceImpl:

//          放到缓存中去
      redisService.putUserByTicket(ticket,user);
package com.example.seckill.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.seckill.exception.BusinessException;
import com.example.seckill.pojo.User;
import com.example.seckill.mapper.UserMapper;
import com.example.seckill.service.IRedisService;
import com.example.seckill.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.seckill.util.CookieUtils;
import com.example.seckill.util.MD5Utils;
import com.example.seckill.util.ValidatorUtils;
import com.example.seckill.util.response.ResponseResult;
import com.example.seckill.util.response.ResponseResultCode;
import com.example.seckill.vo.UserVo;
import com.sun.deploy.nativesandbox.comm.Request;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.Session;
import java.util.Date;
import java.util.UUID;

/**
* <p>
* 用户信息表 服务实现类
* </p>
*
* @author lv
* @since 2022-03-15
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

  @Autowired
  private IRedisService redisService;

  @Override
  public ResponseResult<?> findByAccount(UserVo userVo, HttpServletRequest request, HttpServletResponse response) {
//        先判断信息是否符合(账号是否是手机号码,密码是不是空)
//         if(!ValidatorUtils.isMobile(userVo.getMobile())){
//             throw new BusinessException(ResponseResultCode.USER_ACCOUNT_NOT_MOBLIE);
//         }
//         if(StringUtils.isBlank(userVo.getPassword())){
//             throw new BusinessException(ResponseResultCode.USER_PASSWORD_NOT_MATCH);
//         }
//         再去数据库查出对应的用户(mobile)
      User user=this.getOne(new QueryWrapper<User>().eq("id",userVo.getMobile()));
      if(user==null){
          throw new BusinessException(ResponseResultCode.USER_ACCOUNT_NOT_FIND);
      }
//        比较密码
//        二重加密(前端->后端,后端->数据库)
      String salt=user.getSalt();
//        将前台的加密密码和后端的盐再次进行加密
      String newPassword=MD5Utils.formPassToDbPass(userVo.getPassword(),salt);
      if(!newPassword.equals(user.getPassword())){
          throw new BusinessException(ResponseResultCode.USER_PASSWORD_NOT_MATCH);
      }
//        修改最后的登录时间
      this.update(new UpdateWrapper<User>().eq("id",userVo.getMobile()).set("last_login_date",new Date()).setSql("login_count=login_count+1"));
//          最初版本(session),但Session内数据是服务器共用的
//        所有不让名字重复
      String ticket=UUID.randomUUID().toString().replace("-","");
//       放到全局或者当服务器的session
//        request.getSession().setAttribute(ticket,user);
//          放到缓存中去
      redisService.putUserByTicket(ticket,user);
//        将生成的ticket给用户,用户如何验证?使用cookie
      CookieUtils.setCookie(request,response,"ticket",ticket);
      return ResponseResult.success();
  }
}

④、LocalDateTime无法构造实例

超详细讲解Java秒杀项目用户验证模块的实现

LocalDateTime是Java8推荐使用的时间类,我此处无法转化,需要去配置解析器,我就改变实体类中的LocalDateTime改为时间戳Timestamp

超详细讲解Java秒杀项目用户验证模块的实现

超详细讲解Java秒杀项目用户验证模块的实现

 

四、使用参数解析器

在controller类中方法内加上User实体类参数,查询出用户,自动将信息赋值

1、新建WebConfig文件

package com.example.seckill.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
//打开mvc的功能
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

  @Autowired
  private UserArgumentResolvers userArgumentResolvers;

  @Override
  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
      resolvers.add(userArgumentResolvers);
  }

//    使静态资源仍然可使用
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
      //静态资源访问映射  映射路径 -> 本地资源路径
      registry.addResourceHandler("/static/**")
              .addResourceLocations("classpath:/static/");
  }
}

2、定义参数解析器

UserArgumentResolvers :

package com.example.seckill.config;

import com.example.seckill.exception.BusinessException;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IRedisService;
import com.example.seckill.util.CookieUtils;
import com.example.seckill.util.response.ResponseResultCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;

@Component
public class UserArgumentResolvers implements HandlerMethodArgumentResolver {


  @Autowired
  private IRedisService redisService;

//    supportsParameter方法判断参数是否需要解析,决定了resolveArgument方法是否运行
  @Override
  public boolean supportsParameter(MethodParameter methodParameter) {
      return methodParameter.getParameterType() == User.class;
  }

//    解析参数
  @Override
  public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
//       参数解析User,因为很多地方需要做登录验证
      HttpServletRequest request=(HttpServletRequest) nativeWebRequest.getNativeRequest();
      //        获取用户的ticket
      String ticket= CookieUtils.getCookieValue(request,"ticket");
      if(ticket==null){
          throw new BusinessException(ResponseResultCode.TICKET_ERROR);
      }
//        去session中取到ticket对应的用户,判断是否有值
//        Object obj=request.getSession().getAttribute(ticket);
//        去缓存中拿元素
      User user=redisService.getUserByTicket(ticket);
      if(user==null){
          throw new BusinessException(ResponseResultCode.TICKET_ERROR);

      }
      return user;//经过了参数解析后,参数会变成你这个地方返回的值

  }
}

3、PathController

package com.example.seckill.controller;

import com.example.seckill.exception.BusinessException;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IRedisService;
import com.example.seckill.util.CookieUtils;
import com.example.seckill.util.response.ResponseResultCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
public class PathController {


//    登录跳首页
  @RequestMapping("/")
  public String toPath(){
      return "login";
  }

//    跳所有二级页面
  @RequestMapping("/{dir}/{path}")
  public String toPath(@PathVariable("dir") String dir, @PathVariable("path") String path, User user){
      return dir+"/"+path;
  }

}

4、访问主界面得到相关信息:

超详细讲解Java秒杀项目用户验证模块的实现

本期内容结束~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

到此这篇关于超详细讲解Java秒杀项目用户验证模块的实现的文章就介绍到这了,更多相关Java 用户验证内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_60389087/article/details/123533059

延伸 · 阅读

精彩推荐
  • Java教程HashSet和TreeSet使用方法的区别解析

    HashSet和TreeSet使用方法的区别解析

    这篇文章主要介绍了HashSet和TreeSet使用方法的区别解析,具有一定借鉴价值,需要的朋友可以参考下...

    霍少爷10542021-03-16
  • Java教程Java RMI机制讲解

    Java RMI机制讲解

    这篇文章主要介绍了Java RMI机制讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    ninahan9592021-09-29
  • Java教程基于自定义BufferedReader中的read和readLine方法

    基于自定义BufferedReader中的read和readLine方法

    下面小编就为大家分享一篇基于自定义BufferedReader中的read和readLine方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    fu1990@1268512021-03-06
  • Java教程老程序员教你一天时间完成Java迷宫小游戏

    老程序员教你一天时间完成Java迷宫小游戏

    最近经常在机房看同学在玩一个走迷宫的游戏,比较有趣,自己也用java写一个实现随机生成迷宫的算法,其实就是一个图的深度优先遍历算法....

    BJT12332021-11-15
  • Java教程java 枚举类中的valueOf用法说明

    java 枚举类中的valueOf用法说明

    这篇文章主要介绍了java 枚举类中的valueOf用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...

    lamdaxu4402021-12-29
  • Java教程java 中死锁问题的实例详解

    java 中死锁问题的实例详解

    这篇文章主要介绍了java 中死锁问题的实例详解的相关资料,希望通过本文大家能够理解掌握死锁的问题,需要的朋友可以参考下...

    CC小观8912021-01-05
  • Java教程java的三种随机数生成方式

    java的三种随机数生成方式

    主要介绍了java的三种随机数生成方式的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,,需要的朋友可以...

    cheng102e6482021-09-24
  • Java教程java入门概念个人理解之package与import浅析

    java入门概念个人理解之package与import浅析

    下面小编就为大家带来一篇java入门概念个人理解之package与import浅析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看...

    java教程网3672020-06-07