CentOS 7 使用 yum 安装 RabbitMQ 3.6.6

1、安装erlang

到https://www.rabbitmq.com/releases/erlang/下载安装erlang的最大rpm版本,如果自行安装erlang会十分麻烦,我已经被坑过了

1.1、下载erlang

wget http://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos.x86_64.rpm

1.2、安装erlang

rpm -ivh erlang-19.0.4-1.el7.centos.x86_64.rpm

1.3、测试erlang

输入erl,出现如下画面即为安装正确:

Erlang/OTP 19 [erts-8.0.3] [source] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]
 
Eshell V8.0.3  (abort with ^G)
1>

2、安装RabbitMQ

注意不要再官网上安装最新的,安装最新的则需要安装更新版本的erlang,但是erlang能用rpm安装的最大版本只有19,所以我们在这里下载匹配的v3.6.6的RabbitMQ。

2.1、下载RabbitMQ

wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el7.noarch.rpm

2.2、安装RabbitMQ

rpm -ivh rabbitmq-server-3.6.6-1.el7.noarch.rpm

如果提示:#错误:依赖检测失败:socat 被 rabbitmq-server-3.6.6-1.el7.noarch 需要

则使用以下命令先安装socat:

yum install socat -y

2.3、启动RabbitMQ

systemctl start rabbitmq-server    #启动
systemctl status rabbitmq-server   #状态
systemctl stop rabbitmq-server     #关闭

2.4、配置网页插件

rabbitmq-plugins enable rabbitmq_management #启用插件

2.5、配置访问账号密码和权限

rabbitmqctl add_user mq mq123   #添加用户mq,密码mq123
rabbitmqctl set_permissions -p / mq ".*" ".*" ".*"  #添加权限
rabbitmqctl set_user_tags mq administrator  #修改用户角色
 
 
#其它操作
rabbitmqctl delete_user Username  #删除一个用户
rabbitmqctl change_password Username Newpassword  #修改用户密码
rabbitmqctl list_users  #查看当前用户列表

2.6、登录网页端

http://ip:15672

输入刚刚设置的账号和密码即可。

springboot2.1.1+hibernate5.0.12开启数据库二级缓存

首先加入依赖到pom.xml:

		<!-- hibernnate对二级缓存的支持 -->
		<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-ehcache</artifactId>
		    <version>5.0.12.Final</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
		<dependency>
		    <groupId>net.sf.ehcache</groupId>
		    <artifactId>ehcache</artifactId>
		    <version>2.10.6</version>
		</dependency>

然后在hibernate.xml配置文件中加入以下参数:

				<!-- hibernate5的二级缓存配置 -->
				<prop key="hibernate.cache.use_second_level_cache">true</prop>
				<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

接着创建二级缓存配置文件ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        diskPersistent="false"/>
</ehcache>

最后在需要开启缓存的pojo类中加入注解cache注解:

@Entity
@GenericGenerator(name="idGenerator", strategy="uuid")
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
public class Area {

	/**
	 * id:UUID生成法则
	 */
	@Id
	@GeneratedValue(generator="idGenerator")
	private String id;

配置完毕,启动项目,输出hibernate的sql执行语句,会发现第二次查询相同对象时不再执行查询语句。

使用jconsole远程监控tomcat的性能

1、修改tomcat的启动文件,在启动文件的CATALINA_OPTS(如果是daemon.sh启动则为JAVA_OPTS)变量中加上以下参数:

-Djava.rmi.server.hostname=[服务器IP] -Dcom.sun.management.jmxremote.port=[用于监控的端口] -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false

2、打开jconsole,输入服务器的IP和监控端口,账号密码为服务器的登录账号和密码,点连接即可。

Spring自定义注解(parameter)

1、新建注解接口VerifyAccount.java:

package com.zero4j.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented

public @interface VerifyAccount {

	String paramName() default "token";
	
	String permission() default "";
}

2、创建注解对应的切面类VerifyAccountAspect.java:

package com.zero4j.annotation;

import net.sf.json.JSONObject;

import org.aspectj.lang.annotation.Aspect;
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 org.springframework.web.multipart.support.MissingServletRequestPartException;

import com.zero4j.model.account.Account;
import com.zero4j.model.token.util.TokenStaticUtil;

@Aspect
@Component
public class VerifyAccountAspect implements HandlerMethodArgumentResolver{

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.hasParameterAnnotation(VerifyAccount.class);
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		
		String token = webRequest.getParameter("token");
		
		 JSONObject out = new JSONObject();
		
		if(token==null||token.equals("")){
			out.put("status", 401);
			out.put("message", "请先注册并登录后再进行此操作");
			out.put("debug", "缺少参数token或为空");
			//ResponseStaticUtil.write(response,out);
			System.out.println(out.toString());
			//return;
		}
		Account account = TokenStaticUtil.getAccount(token);
		if(account==null){
			out.put("status", 401);
			out.put("message", "请先注册并登录后再进行此操作");
			out.put("debug", "token对应的account为空");
			//ResponseStaticUtil.write(response,out);
			System.out.println(out.toString());
			throw new MissingServletRequestPartException("account");
			//return;
		}
		
		return account;
	}
	
}

注意要实现接口:HandlerMethodArgumentResolver

3、最后要在SpringMVC的配置java类中加入对应的代码:

package com.zero4j.config;

import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.zero4j.annotation.VerifyAccountAspect;

@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {


	@Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
		
		resolvers.add(new VerifyAccountAspect());
		
		WebMvcConfigurer.super.addArgumentResolvers(resolvers);
	}

}

注意这行:resolvers.add(new VerifyAccountAspect());

Spring自定义注解(method)

先定义一个注解接口 VerifyToken.java :

package com.zero4j.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented

public @interface VerifyToken {

	//权限参数
	String permission() default "";
	
}

再在同目录中定义一个切面类VerifyTokenAspect.java:

package com.zero4j.annotation;

import java.util.Enumeration;

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

import net.sf.json.JSONObject;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.zero4j.model.account.Account;
import com.zero4j.model.permission.util.PermissionStaticUtil;
import com.zero4j.model.token.util.TokenStaticUtil;
import com.zero4j.util.ResponseStaticUtil;

@Aspect
@Component
public class VerifyTokenAspect {

	@Pointcut("@annotation(com.zero4j.annotation.VerifyToken)")	//这是annotation对应类的所在位置,若目录不同,则填写完整路径,如:com.zero4j.annotation.VerifyToken
    private void pointcut(){
		
	}
	
	@Around("pointcut()&&@annotation(verifyToken)")
	public void around(ProceedingJoinPoint pjp, VerifyToken verifyToken) throws Throwable{
		
		//System.out.println("annotation执行前");
		
		//System.out.println("verifyToken.permission() = "+verifyToken.permission());
		
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        
        String token = request.getParameter("token");
        
        JSONObject out = new JSONObject();
		
		if(token==null||token.equals("")){
			out.put("status", 401);
			out.put("message", "请先注册并登录后再进行此操作");
			out.put("debug", "缺少参数token或为空");
			ResponseStaticUtil.write(response,out);
			//System.out.println(out.toString());
			return;
		}
		Account account = TokenStaticUtil.getAccount(token);
		if(account==null){
			out.put("status", 401);
			out.put("message", "请先注册并登录后再进行此操作");
			out.put("debug", "token对应的account为空");
			ResponseStaticUtil.write(response,out);
			//System.out.println(out.toString());
			return;
		}
		
		if(!(verifyToken.permission()==null||verifyToken.permission().equals(""))){
			if(PermissionStaticUtil.verify(account.getId(), verifyToken.permission())==false){
				out.put("status", 403);
				out.put("message", "你无权进行本操作");
				out.put("debug", "你没有"+verifyToken.permission()+"权限");
				ResponseStaticUtil.write(response,out);
				//System.out.println(out.toString());
				return;
			}
		}
		
		if(out.size()==0){
			pjp.proceed();
		}

	}

}

最后在需要切入的地方加上注解即可:

	@VerifyToken(permission="adminLog_read")
	@RequestMapping(value="", method=RequestMethod.GET)
	public void list(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(required=false) String token,
			@RequestParam(required=false) Integer offset,
			@RequestParam(required=false) Integer limit,
			@RequestParam(required=false) String startTime,
			@RequestParam(required=false) String endTime,
			@RequestParam(required=false) String accountNickname,
			@RequestParam(required=false) String accountMobile,
			@RequestParam(required=false) String description
		){
		
		........

		}

 

在J2EE中下载文件时使用中文名字的示例代码

    @RequestMapping(path = { "/downloadFromArchive" }, method={RequestMethod.GET})
    public ResponseEntity<byte[]> downloadFromArchive(HttpServletRequest request, HttpServletResponse response,
    			@RequestParam(required=false) String id
    		) throws IOException {
    	  
        HttpHeaders headers = new HttpHeaders();	//设置http协议头部
        
        if(id==null||id.equals("")){
        	return null;
        }
        
        Archive archive = this.archiveService.get(id);
        if(archive==null){
        	return null;
        }
        
        if(archive.getLink().indexOf(".")<0){
        	response.sendRedirect(archive.getLink());
        	return null;
        }
        String extension = archive.getLink().substring(archive.getLink().lastIndexOf("."));
        
        //System.out.println("archive.getTitle()"+archive.getTitle());
        //System.out.println("archive.getLink()"+archive.getLink());
        
        String fileName = archive.getTitle()+extension;
        //System.out.println("fileName = "+fileName);
        
        //获取文件在服务器上的绝对路径
		String filePath = archive.getLink();
		
		//假如路径为阿新制作的下载controller,则执行特殊的操作,filePath会根据阿新的逻辑去获取
		
			
		Pattern pattern = Pattern.compile(".*\\?archiveId=(.*?)&fileName=(.*)&randomName=(.*)");
		Matcher	matcher = pattern.matcher(archive.getLink());
		if(matcher.find()){
			System.out.println("正则匹配成功1");
			String archiveId = matcher.group(1);
			fileName = matcher.group(2);
			String randomName = matcher.group(3);
			filePath = "/uploads/archiveFile/"+archiveId+"/"+randomName;
			System.out.println("filePath" + filePath);
		}
		else{
			pattern = Pattern.compile(".*\\?archiveId=(.*?)&fileName=(.*)");
			matcher = pattern.matcher(archive.getLink());
			if(matcher.find()){
				System.out.println("正则匹配成功2");
				String archiveId = matcher.group(1);
				fileName = matcher.group(2);
				filePath = "/uploads/archiveFile/"+archiveId+"/"+fileName;
				System.out.println("filePath" + filePath);
			}else{}
		}
		
		
		
        File file = new File(this.servletContext.getRealPath("/") + filePath);
        
        if(!file.exists()){
        	System.out.println("目标下载文件不存在");
        	ResponseStaticUtil.write(response, "目标下载文件不存在");
    		return null;
        }
        //response.sendRedirect(filePath);
        
        
        //头部设置文件类型
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);  
        //headers.setContentDispositionFormData("attachment", upload.getName());
		if(request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0) {	//IE浏览器UTF-8
			System.out.println("IE浏览器");
			headers.setContentDispositionFormData("attachment", fileName);
		}/*else if(request.getHeader("User-Agent").contains("Firefox")){	//火狐浏览器
			fileName="=?utf-8?b?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?=";
		}*/else{	// 其他浏览器attachment;filename*=utf-8'zh_cn
			System.out.println("其他浏览器");
			response.setHeader("Content-Disposition", "attachment;fileName="+URLEncoder.encode(fileName,"utf-8")+"");// 重点
		}
        
        
		//返回文件字节数组
        /*try {
            return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
        } catch (IOException e) {
            e.printStackTrace();
            return null;    
        }*/
		InputStream in = new FileInputStream(file);  
        OutputStream out = response.getOutputStream();  
        byte[] b = new byte[1024];
        int length = 0;
        while((length = in.read(b)) != -1)  {  
            out.write(b,0,length);  
        }  
        in.close();  
        out.close();
        return null;
    }

有必要说一下,为什么没有使用FileUtils的readFileToByteArray方法,而是使用原始的out.write,因为前者在移动端中下载文件是不成功的(但奇怪的是在电脑端上却是正常的)。

创建一个基于SpringBoot2.1.x的JavaFX程序

1.创建SpringBoot项目

到 https://start.spring.io/ 创建一个SpringBoot2.1.x项目,解压后使用MyEclipse2015导入为maven项目~

2.引入JavaFX

对SpringBoot入口程序Application进行改造,继承javafx的application类,并引入接口CommandLineRunner, Consumer<Stage>,接着加入如下代码(高亮部分):

package com.dgzq;

import java.util.function.Consumer;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.stage.Stage;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DgzqApplication extends Application implements CommandLineRunner, Consumer<Stage>{

	public static void main(String[] args) {
		SpringApplication.run(DgzqApplication.class, args);
	}
	
	@Override
	public void run(String... args) throws Exception {
		
		Platform.runLater(new Runnable() {
		    @Override
		    public void run() {
		    	
		    	Stage stage = new Stage();
        		
		    	try {
					start(stage);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
        		
		    }
		});
		
	}

	@Override
	public void start(Stage primaryStage) throws Exception {
		accept(primaryStage);
	}

	@Override
	public void accept(Stage stage) {
		
		TabPane tabPane = new TabPane();	//增加标签面板
		tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
		
		Scene scene = new Scene(tabPane, 900, 690);
		stage.setScene(scene);
		stage.setTitle("测试界面");
		
		Tab tab1 = new Tab("标签页1");
		Tab tab2 = new Tab("标签页2");
		tabPane.getTabs().addAll(tab1,tab2);
		tabPane.getSelectionModel().select(tab1);	//设置默认选中
		
		stage.show();
	}

}

然后启动,出现如下界面则为成功:

ac571e727fe9d73b3500c54a3e2117c

 

3.增加预加载页面

在pom.xml加入如下依赖:

		<!-- SpringBoot2.x与JavaFX的集成 -->
		<!-- https://mvnrepository.com/artifact/de.roskenet/springboot-javafx-support -->
		<dependency>
		    <groupId>de.roskenet</groupId>
		    <artifactId>springboot-javafx-support</artifactId>
		    <version>2.1.6</version>
		</dependency>

 

新增一个启动入口文件如MainApplication.java用于展示欢迎界面,代码如下:

package com.dgzq;

import java.io.File;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import de.felixroske.jfxsupport.AbstractJavaFxApplicationSupport;
import de.felixroske.jfxsupport.SplashScreen;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.scene.paint.Color;

@SpringBootApplication
public class MainApplication extends AbstractJavaFxApplicationSupport {
	
	public static SplashScreen splashScreen;
	public static Stage splashStage;
	public static Scene splashScene;
	
    public static void main(String[] args) {
    	
    	//启动(若需要以fxml形式展示主界面,则第二个传参可以为"MainStageView.class"之类的)
    	launch(MainApplication.class, null, args);
        
    }

    @Override
    public void start(Stage stage) throws Exception {

    	MainApplication.splashScreen = new SplashScreen();
    	MainApplication.splashStage = new Stage(StageStyle.TRANSPARENT);
    	MainApplication.splashScene = new Scene(splashScreen.getParent(), Color.TRANSPARENT);
    	MainApplication.splashStage.setScene(splashScene);
    	MainApplication.splashStage.initStyle(StageStyle.TRANSPARENT);
    	MainApplication.splashStage.show();

    }
    
}

在预加载完成后还要再正式界面中隐藏掉本界面,因此要在原来的application类的stage.show()前面加入如下代码:

MainApplication.splashStage.hide();
MainApplication.splashStage.setScene(null);

然后注释掉原来的application启动类中的main方法:

/*public static void main(String[] args) {
	SpringApplication.run(DgzqApplication.class, args);
}*/

最后启动刚刚新建的MainApplication.java,便会出现中间界面:

d294a0cca4b571832aaa7b9c70f8363

好了,大功告成。如果还需要引入sqlite数据库,则可以继续往下操作。

4.引入hibernate并使用sqlite数据库

在MainApplication中的 下方加入如下代码,以提示sqlite是否存在:

    	File databaseFile = new File("sqlite3.db");
    	if(!databaseFile.exists()){
	    	Alert alert = new Alert(Alert.AlertType.INFORMATION);
			alert.setTitle("错误");
			alert.setHeaderText(null);
			alert.setContentText("找不到数据库文件:sqlite3.db(本次运行将自动创建全新的空白数据库)");
			alert.showAndWait();
    	}

再pom.xml中加入如下依赖:

	<!-- sqlite3驱动包 -->
        <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
		<dependency>
		    <groupId>org.xerial</groupId>
		    <artifactId>sqlite-jdbc</artifactId>
		    <version>3.28.0</version>
		</dependency>
		
		<!-- SpringBoot与hibernate的集成配置 -->
		<dependency>
		    <groupId>org.springframework.boot</groupId>
		    <artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<!-- SpringBoot使用Hibernate的SessionFactory -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-core</artifactId>
		    <version>5.0.12.Final</version>
		</dependency>
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>5.0.12.Final</version>
		</dependency>
		
		<!-- SpringBoot2.x与JavaFX的集成 -->
		<!-- https://mvnrepository.com/artifact/de.roskenet/springboot-javafx-support -->
		<dependency>
		    <groupId>de.roskenet</groupId>
		    <artifactId>springboot-javafx-support</artifactId>
		    <version>2.1.6</version>
		</dependency>

 

对原来的Application进行修改(加入高亮部分):

package com.dgzq;

import java.util.function.Consumer;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.stage.Stage;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean;

@SpringBootApplication
public class DgzqApplication extends Application implements CommandLineRunner, Consumer<Stage>{
	
	public static SessionFactory sessionFactory;
	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		DgzqApplication.sessionFactory = sessionFactory;
	}
	
	@Bean
    public HibernateJpaSessionFactoryBean sessionFactory() {
        return new HibernateJpaSessionFactoryBean();
    }

	/*public static void main(String[] args) {
		SpringApplication.run(DgzqApplication.class, args);
	}*/
	
	@Override
	public void run(String... args) throws Exception {
		
		Platform.runLater(new Runnable() {
		    @Override
		    public void run() {
		    	
		    	Stage stage = new Stage();
        		
		    	try {
					start(stage);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
        		
		    }
		});
		
	}

	@Override
	public void start(Stage primaryStage) throws Exception {
		accept(primaryStage);
	}

	@Override
	public void accept(Stage stage) {
		
		System.out.println("MainJavaFxApplication被实例化了");
		System.out.println("MainJavaFxApplication.sessionFactory = "+sessionFactory);
		
		TabPane tabPane = new TabPane();	//增加标签面板
		tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
		
		Scene scene = new Scene(tabPane, 900, 690);
		stage.setScene(scene);
		stage.setTitle("测试界面");
		
		Tab tab1 = new Tab("标签页1");
		Tab tab2 = new Tab("标签页2");
		tabPane.getTabs().addAll(tab1,tab2);
		tabPane.getSelectionModel().select(tab1);	//设置默认选中
		
		MainApplication.splashStage.hide();
		MainApplication.splashStage.setScene(null);
		
		stage.show();
	}

}

增加sqlite的方言类SQLiteDialect.java:

package com.fenji;

import java.sql.Types;

import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.VarArgsSQLFunction;
import org.hibernate.type.StandardBasicTypes;

public class SQLiteDialect extends Dialect {
    public SQLiteDialect() {
        super();
        registerColumnType(Types.BIT, "integer");
        registerColumnType(Types.TINYINT, "tinyint");
        registerColumnType(Types.SMALLINT, "smallint");
        registerColumnType(Types.INTEGER, "integer");
        registerColumnType(Types.BIGINT, "bigint");
        registerColumnType(Types.FLOAT, "float");
        registerColumnType(Types.REAL, "real");
        registerColumnType(Types.DOUBLE, "double");
        registerColumnType(Types.NUMERIC, "numeric");
        registerColumnType(Types.DECIMAL, "decimal");
        registerColumnType(Types.CHAR, "char");
        registerColumnType(Types.VARCHAR, "varchar");
        registerColumnType(Types.LONGVARCHAR, "longvarchar");
        registerColumnType(Types.DATE, "date");
        registerColumnType(Types.TIME, "time");
        registerColumnType(Types.TIMESTAMP, "timestamp");
        registerColumnType(Types.BINARY, "blob");
        registerColumnType(Types.VARBINARY, "blob");
        registerColumnType(Types.LONGVARBINARY, "blob");
        // registerColumnType(Types.NULL, "null");
        registerColumnType(Types.BLOB, "blob");
        registerColumnType(Types.CLOB, "clob");
        registerColumnType(Types.BOOLEAN, "integer");

        registerFunction("concat", new VarArgsSQLFunction(StandardBasicTypes.STRING, "", "||", ""));
        registerFunction("mod", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "?1 % ?2"));
        registerFunction("substr", new StandardSQLFunction("substr", StandardBasicTypes.STRING));
        registerFunction("substring", new StandardSQLFunction("substr", StandardBasicTypes.STRING));
    }

    public boolean supportsIdentityColumns() {
        return true;
    }

    public boolean hasDataTypeInIdentityColumn() {
        return false;
    }

    public String getIdentityColumnString() {
        return "integer";
    }

    public String getIdentitySelectString() {
        return "select last_insert_rowid()";
    }

    public boolean supportsLimit() {
        return true;
    }

    public String getLimitString(String query, boolean hasOffset) {
        return new StringBuffer(query.length() + 20).append(query).append(hasOffset ? " limit ? offset ?" : " limit ?")
                .toString();
    }

    public boolean supportsTemporaryTables() {
        return true;
    }

    public String getCreateTemporaryTableString() {
        return "create temporary table if not exists";
    }

    public boolean dropTemporaryTableAfterUse() {
        return false;
    }

    public boolean supportsCurrentTimestampSelection() {
        return true;
    }

    public boolean isCurrentTimestampSelectStringCallable() {
        return false;
    }

    public String getCurrentTimestampSelectString() {
        return "select current_timestamp";
    }

    public boolean supportsUnionAll() {
        return true;
    }

    public boolean hasAlterTable() {
        return false;
    }

    public boolean dropConstraints() {
        return false;
    }

    public String getAddColumnString() {
        return "add column";
    }

    public String getForUpdateString() {
        return "";
    }

    public boolean supportsOuterJoinForUpdate() {
        return false;
    }

    public String getDropForeignKeyString() {
        throw new UnsupportedOperationException("No drop foreign key syntax supported by SQLiteDialect");
    }

    public String getAddForeignKeyConstraintString(String constraintName, String[] foreignKey, String referencedTable,
            String[] primaryKey, boolean referencesPrimaryKey) {
        throw new UnsupportedOperationException("No add foreign key syntax supported by SQLiteDialect");
    }

    public String getAddPrimaryKeyConstraintString(String constraintName) {
        throw new UnsupportedOperationException("No add primary key syntax supported by SQLiteDialect");
    }

    public boolean supportsIfExistsBeforeTableName() {
        return true;
    }

    public boolean supportsCascadeDelete() {
        return false;
    }

    @Override
    public boolean bindLimitParametersInReverseOrder() {
        return true;
    }
}

增加配置文件application.properties用于配置数据库(注意高亮行,要指向刚刚创建的方言类SQLiteDialect.java):

spring.datasource.driver-class-name=org.sqlite.JDBC
spring.datasource.url=jdbc:sqlite:sqlite3.db

# Specify the DBMS
#spring.jpa.database=SQLite
# Show or not log for each sql query
spring.jpa.show-sql=true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto=update
# Naming strategy
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them to the entity manager
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.dialect=com.dgzq.SQLiteDialect
# table column upcase problem
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
# auto inject sessionFactory bean
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

好了,运行MainApplication看看效果:

639fccfb32a10d16ee5a29089e0094f

如图所示,输入sessionFactory不为空,则注入成功,后面大家自由发挥吧!

5.补充:记得指定maven打包时的启动入口

在pom.xml中加入如下高亮代码

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<mainClass>com.dgzq.MainApplication</mainClass>
				</configuration>
			</plugin>
		</plugins>
	</build>

大功告成!

使用MyEclipse进行Maven构建时出现501错误

经过分析,是由于自2020年1月15日起,中央存储库不再支持通过纯HTTP进行的不安全通信,并且要求对存储库的所有请求都通过HTTPS进行加密。

于是我们需要在构建过程中所依赖的maven对其settings.xml文件加入以下配置:

	<mirror>
		<id>central</id>
		<name>Maven Repository Switchboard</name>
		<url>https://repo1.maven.org/maven2/</url>
		<mirrorOf>central</mirrorOf>
	</mirror>

但是MyEclipse中如果使用自带的maven,则你会找不到settings.xml来进行配置,所以我从对应MyEclipse2015内置maven对应3.2.1版本源代码中找到了settings.xml文件,拷贝到C:\Users\Administrator\.m2并在mirrors中加入以上配置。

settings ←我配置好的文件在这里下载

接着根据下图只是将MyEclipse中的maven指定为刚刚设置的文件,然后执行 update project 即可~

7024d8405f8c484c4a7a2ee628e89e8

5240b2a4bda21aa8570dd13cb0f241a

 

最后要注意的是,如果使用JDK7或更低版本的话,是不支持TLS1.2的,而maven的中央仓库要求https协议为TLS1.2,此时可以考虑将JDK7升级到JDK8以上,或者将中央仓库改为阿里云的:

	<!--设置中央仓库的路径为国内阿里云路径-->
	<mirror>
		<id>nexus-aliyun</id>
		<mirrorOf>central</mirrorOf>
		<name>Nexus aliyun</name>
		<url>http://maven.aliyun.com/nexus/content/groups/public</url>
	</mirror>

如果是在MyEclipse以外的地方遇到TLS版本问题,则可以增加以下参数尝试:

-Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2

 

nginx要注意的并发配置

单核所能产生的线程数问题

nginx默认只使用cpu的一个核,单核支持的线程数是1024,意味着超过1024就会崩

需要在配置中加上:worker_processes 4 (数字“4”为您所需要使用的核数)

单个文件访问数量的问题

nginx默认只允许单个文件被4096个线程打开,意味着如果nginx的线程超过4096也会崩,哪怕设置CPU核数大于4个

需要在配置中加上:worker_rlimit_nofile 32768

123

close