java日常开发问题记录

283 阅读8分钟
  1. Java是面向对象的语言,一个程序的基本单位就是class,class是关键字。类名要求:类名必须以英文字母开头,后接字母,数字和下划线的组合,习惯以大写字母开头
public class SayHello {
    public static void main(String[] args) {
        System.out.println("所有的java文件都只有一个类,类名开头字母大写,其中名为main的方法为类的入口方法");
    }
}
  1. Java入口程序规定的方法必须是静态方法,方法名必须为main,括号内的参数必须是String数组。
  2. 不同的数据类型占用的字节数不一样。我们看一下Java基本数据类型占用的字节数:
    注:字符类型char表示一个字符。Java的char类型除了可表示标准的ASCII外,还可以表示一个Unicode字符
  3. 对于idea中gradle依赖下载缓慢的问题:idea中的maven和gradle使用本地的不用idea自带的,并在build.gradle文件中讲maven源设置为maven { url "maven.aliyun.com/repository/…" }
  4. 对于maven下载依赖慢易出错的问题,需在idea中配置本地maven,并在mirrors标签内增加如下代码:
<mirror>
  <id>alimaven</id>
  <name>aliyun maven</name>
  <url>http://maven.aliyun.com/nexus/content/groups/public</url>
  <mirrorOf>central</mirrorOf>        
</mirror>
  1. 在idea中添加注释模板:Editor -> File and Code Templates->includes中添加如下:
/**
 * @author  Mingxian Ma
 * @description //TODO
 * @date  ${DATE} ${TIME}
 */
  1. 对于maven、gradle等插件,需要使用本地时,不能对每个项目进行分别设置(在导入项目时会发生错误),所以要进行默认设置:

8. 在idea中安装grep console插件可以自定义控制台输出信息的颜色。

9. idea自动导入依赖包File-->Settings--->auto import:

10. springboot+idea热部署(自动刷新): blog.csdn.net/qq_42685050… 11. swagger和shiro整合

filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-resources", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");

java通用框架搭建

  1. SpringBoot项目在IntelliJ IDEA中实现热部署,设置完毕之后需要清除缓存重启idea:www.javazhiyin.com/32982.html
  2. java 日志框架中log4j2比较常用,需要添加依赖和设置配置文件log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="1800">
<!--    输出相关配置-->
    <appenders>
        <Console name="consolePrint" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
    </appenders>
<!--    日志级别配置-->
    <loggers>
        <!-- 将业务dao接口填写进去,并用控制台输出即可 -->
        <logger name="com.heeexy.example.dao" level="TRACE" additivity="false">
            <appender-ref ref="consolePrint"/>
        </logger>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="warn" additivity="false">
            <AppenderRef ref="consolePrint"/>
        </logger>
        <!--监控系统信息-->
        <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
        <Logger name="org.springframework" level="warn" additivity="false">
            <AppenderRef ref="consolePrint"/>
        </Logger>
        <root level="warn">
            <appender-ref ref="consolePrint" />
        </root>
    </loggers>
</Configuration>

pom.xml文件:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  1. 在spingboot中配置swagger2:
/**
 * @author Mingxian Ma
 * @description Swagger2配置文件
 * @date 2020/5/25 14:34
 */
@Configuration
@EnableSwagger2
public class Swagger2 {

    @Bean
    public Docket createRestApi() {
        ParameterBuilder ticketPar = new ParameterBuilder();
        List<Parameter> pars = new ArrayList<Parameter>();
        ticketPar.name("authorization").description("user authorization")
                .modelRef(new ModelRef("string")).parameterType("header")
                .required(false).build(); //header中的ticket参数非必填,传空也可以
        pars.add(ticketPar.build());    //根据每个方法名也知道当前方法在设置什么参数

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.heeexy.example.controller"))
                .paths(PathSelectors.any())
                .build()
                .globalOperationParameters(pars);
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("java通用框架api文档")
                .description("快速开发的java框架")
                .termsOfServiceUrl("https://juejin.cn/user/3632442151561534")
                .version("1.0")
                .build();
    }
}

15.在springboot中配置jwt实现token认证:

/**
 * @author Mingxian Ma
 * @description //TODO
 * @date 2020/5/25 18:22
 */
public class JwtUtil {
    private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);
    /**
     * 密钥
     */
    private static final String SECRET = "my_secret";

    /**
     * 过期时间
     **/
    private static final long EXPIRATION = 1800L;//单位为秒

    /**
     * 生成用户token,设置token超时时间
     */
    public static String createToken(JSONObject user) {
        //过期时间
        Date expireDate = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        String token = JWT.create()
                .withHeader(map)// 添加头部
                //可以将基本信息放到claims中
                .withClaim("userId", user.getInteger("userId"))//userId
                .withClaim("userName", user.getString("username"))//userName
                .withClaim("password", user.getString("password"))//userName
                .withExpiresAt(expireDate) //超时设置,设置过期的日期
                .withIssuedAt(new Date()) //签发时间
                .sign(Algorithm.HMAC256(SECRET)); //SECRET加密
        return token;
    }

    /**
     * 校验token并解析token
     */
    public static Map<String, Claim> verifyToken(String token) {
        DecodedJWT jwt = null;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
            jwt = verifier.verify(token);
        } catch (Exception e) {
            logger.error(e.getMessage());
            logger.error("token解码异常");
            //解码异常则抛出异常
            return null;
        }
        return jwt.getClaims();
    }
}
**
 * @author Mingxian Ma
 * @description //TODO
 * @date 2020/5/25 18:23
 */
@WebFilter(filterName = "JwtFilter", urlPatterns = "/*",initParams = {
        @WebInitParam(name = "loginUI", value = "/login/auth"),
        @WebInitParam(name = "swaggerUI", value = "/swagger")
})
public class JwtFilter implements Filter {
    private FilterConfig config;
    @Override
    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;
        String loginUI = config.getInitParameter("loginUI");
        String swaggerUI = config.getInitParameter("swaggerUI");
        String uri = request.getRequestURI();

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        //获取 header里的token
        final String token = request.getHeader("authorization");
        // 登录页面和wagger2界面放行
        if (uri.contains(loginUI) || uri.contains(swaggerUI)) {
            response.setStatus(HttpServletResponse.SC_OK);
            chain.doFilter(request, response);
        }

        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            chain.doFilter(request, response);
        }
        // Except OPTIONS, other request should be checked by JWT
        else {

            if (token == null) {
                response.getWriter().write(CommonUtil.errorJson(ErrorEnum.E_401).toString());
                return;
            }

            Map<String, Claim> userData = JwtUtil.verifyToken(token);
            if (userData == null) {
                response.getWriter().write(CommonUtil.errorJson(ErrorEnum.E_401).toString());
                return;
            }
            Integer userId = userData.get("userId").asInt();
            String userName = userData.get("userName").asString();
            String password = userData.get("password").asString();
            //拦截器 拿到用户信息,放到request中
            request.setAttribute("userId", userId);
            request.setAttribute("userName", userName);
            request.setAttribute("password", password);
            chain.doFilter(req, res);
        }
    }

    @Override
    public void destroy() {
    }
}
  1. 经典的getOutputStream() has already been called for this response错误,需要检查是否有同时调用javax.servlet.http.HttpServletResponse中方法(.setStatus、getWriter等)两次以上的情况。去除即可解决

需要在启动类中添加@ServletComponentScan注解

  1. 在idea中导入maven项目时,出现Unable to import maven project: See logs for details错误。重新查看idea自带maven的版本,下载对应的maven版本配置即可解决。
  2. Mybatis-Generator的使用反向生成java,并自动添加数据库注释。blog.csdn.net/kuyuyingzi/… 特别注意,需要在配置文件中:
<context id="wangyongzhi_mysql_tables" targetRuntime="MyBatis3">
    <plugin type="com.heeexy.example.generator.MyBatisPlugin" >
        <property name="hasLombok" value="true"/>
    </plugin>
    <!-- 防止生成的代码中有很多注释,加入下面的配置控制 -->
    <commentGenerator>
        <property name="suppressAllComments" value="true" />
        <property name="suppressDate" value="true" />
    </commentGenerator>
</context>
  1. idea常用插件:juejin.cn/post/684490…
  2. Could not find artifact ...:pom:0.0.1-SNAPSHOT and 'parent.relativePath':解决方法:多模块项目构建时,先将parent项目要先install一回,之后子项目才可以运行mvn compile命令,否则就会报如上异常。
  3. mysql驱动的不同写法:
    // MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  
    static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB";
    
    // MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";  
    static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB?useSSL=false&serverTimezone=UTC";
  1. mvc架构的实践与理解:controller层只做参数验证与接口转发,不作任何逻辑处理。所有的逻辑处理都在service实现层完成。

  2. 通俗一点,只要是实现了servlet接口的java程序,均称Servlet。Servlet是由sun公司命名的,Servlet = Server + Applet(Applet表示小应用程序),Servlet是在服务器端运行的小程序。

  3. List list=new ArrayList();为什么要声明为List 而不是ArrayList: 设计模式中有:“代码尽量依赖于抽象,不依赖于具体”,例如,代码List list = new ArrayList();下面通过list来操作集合。代码编写后发现集合使用的不准确,应该使用LinkedList,那么只要修改一行代码List list = new LinkedList();就可以,这行以后的代码不需要修改,因为List接口保证了调用的都是接口中的方法,而ArrayList与LinkedList都实现了List接口。而如果当时用ArrayList list = new ArrayList()这种形式的话,那么list访问到的就可能是ArrayList里独有的方法而非List接口中的方法。这样替换成LinkedList的时候就有可能需要修改很多的代码。向下转型:可以调用子类那些特有的方法,重新获得丢失的子类特有方法<泛型是常用>

  4. java常用包简介:java的核心类都放在Java包以及其子包下,Java扩展的许多类都放在Javax(extends)包以及其子包下。下面几个包是Java语言中的常用包:

1),java.lang:Java语言的核心类,如String,Math,System和Thread类等,使用这个包下的类无须使用import语句导入,系统(jdk)会自动导入这个包下的所有类。

2),java.util:这个包下包含了java的大量工具类、集合框架类和接口,例如Arrays,List,Set。

3),java.net:网络编程接口和类,以后要写和网络相关的应用就要用这个包。

4),java.io:流的接口和类,以后要写读写文件或者图片等这些就要用这个包。

5),java.text:java格式化相关类,以后我们要做软件国际化就要用这个包。

6),java.sql:jdbc相关接口和类 ,以后操作java连接数据库就要使用到这个包。

7),java.awt:抽象窗口工具集相关接口和类,搞一个类似于QQ一样的软件,界面就得使用这个包。

8),java.swing : 图形用户界面相关接口和类(可跨平台)。

  1. idea自动编译

26. springboot日志配置文件大致如下,放在src/main/resources:

日志级别:ERROR, WARN, INFO, DEBUG or TRACE

logging.level.com.dudu=DEBUG:com.dudu包下所有class以DEBUG级别输出
  1. 对象循环引用导致{"ref":"[0]"},是因为arrayList保存的是对象的引用,所以,每次更改和添加的都是都一个值,所以导致重复引用的问题。所以,每次add()的都必须是一个新对象。

当编辑器报String类等未定义时,就是因为项目中未加入jdk环境

持续更新……