• Category Archives: 编程语言

在SpringBoot中使用SessionFactory的方法

首先项目中已经使用JPA的方式连接,然后加入hibernate依赖:

	<properties>
		<java.version>1.8</java.version>
		<hibernate.version>5.0.12.Final</hibernate.version>
	</properties>
		<!-- SpringBoot使用Hibernate的SessionFactory -->
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-core</artifactId>
		    <version>${hibernate.version}</version>
		</dependency>
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>${hibernate.version}</version>
		</dependency>

 

然后有以下几种方式,选择一种合适自己的。

方法一:

增加配置文件HibernateConfig.java:

package com.testSSH.config;

import javax.persistence.EntityManagerFactory;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HibernateConfig {
    
    @Bean
    public SessionFactory sessionFactory(@Qualifier("entityManagerFactory") EntityManagerFactory emf){
         return emf.unwrap(SessionFactory.class);
     }

}

如果要使用@Transactional则需要在application.properties中加上:

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

 

方法二:(推荐)

在SpringBoot的启动类中加上:

	@Bean
	public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf) {
	    return hemf.getSessionFactory();
	}

如果要使用@Transactional则需要在application.properties中加上:

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

 

 

方法三:

在SpringBoot的启动类中加上:

    @Bean
    public HibernateJpaSessionFactoryBean sessionFactory() {
        return new HibernateJpaSessionFactoryBean();
    }

如果要使用@Transactional则需要在application.properties中加上:

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext

 

 

使用方法:

@Autowired
private SessionFactory sessionFactory;

 

让SpringBoot2.0不使用hiraki数据库连接池而改用c3p0

SpringBoot2.0默认是用hiraki数据库连接池,听说这个是当今运行效率最高的,但由于某些原因我要使用c3p0数据库连接池,所以就给大家说一下我的配置过程,其实还是挺简单的:

在pom.xml中加上依赖:

		<!-- 不使用默认的hikari数据库连接池,使用c3p0的 -->
		<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
		<dependency>
		    <groupId>com.mchange</groupId>
		    <artifactId>c3p0</artifactId>
		    <version>0.9.5.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.mchange/mchange-commons-java -->
		<dependency>
		    <groupId>com.mchange</groupId>
		    <artifactId>mchange-commons-java</artifactId>
		    <version>0.2.15</version>
		</dependency>

然后注释掉原来application.properties中的默认数据库配置而改用c3p0的:

#mysql
#spring.datasource.url=jdbc\:mysql\://localhost\:3306/test?useSSL\=false&characterEncoding\=utf8
#spring.datasource.username=test
#spring.datasource.password=test
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.hikari.minimum-idle=10
#spring.datasource.hikari.maximum-pool-size=50

# c3p0
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/test?autoReconnect=true&amp;autoReconnectForPools=true&amp;useUnicode=true&amp;characterEncoding=utf-8
c3p0.user=test
c3p0.password=test
c3p0.driverClass=com.mysql.jdbc.Driver
#c3p0.minPoolSize=2
#c3p0.maxPoolSize=100
#c3p0.maxIdleTime=0
#c3p0.acquireIncrement=3
#c3p0.maxStatements=1000
#c3p0.initialPoolSize=3
#c3p0.idleConnectionTestPeriod=60
#c3p0.acquireRetryAttempts=30
#c3p0.acquireRetryDelay=1000
#c3p0.breakAfterAcquireFailure=false
#c3p0.testConnectionOnCheckout=false

最后补充配置类:

package com.isuidian.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;

@Configuration
public class DataSourceConfiguration {
 
    // c3p0 连接池
    @Bean(name = "dataSource")
    @Qualifier(value = "dataSource")
    @Primary
    @ConfigurationProperties(prefix = "c3p0")
    public DataSource dataSource(@Autowired Environment environment) {
        return DataSourceBuilder.create().type(com.mchange.v2.c3p0.ComboPooledDataSource.class).build();
    }
}

搞掂,部署运行,在springboot的启动信息中可以看到c3p0已经生效了。

SpringBoot2.0+Hibernate在Controller使用Session并发性能调优

从SpringBoot2.0开始,其DataSource就交给了Hikari负责。

对于高并发需求,根据数据库的性能,若然Controller执行时间过长,过多controller正在等待有限的sessionFactory资源,则会造成线程堵塞,引起雪崩。

需要在springboot的配置中假如如下设置:

spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=50
spring.datasource.hikari.idle-timeout=20000
spring.datasource.hikari.connection-timeout=20000

最主要是maximum-pool-size参数,在不设置的情况下默认是10,所以当用户卡在controller等待使用session资源时,做并发测试的时候就会出现卡死现象,引起雪崩。

如果controller中关于数据查询的部分的执行时间较长,maximum-pool-size一定要调大,但是这个值越大我猜测就越内存,一定要适当。

SpringBoot2.1.x+SpringCloud:Eureka(server+client)入门+高可用配置

eureka

一、Eureka服务器+Eureka服务提供者

1、首先到https://start.spring.io/中创建版本为2.1.x项目,在本地的IDEA导入后,首先在pom.xml中增加以下依赖(在pom.xml的<dependencies></dependencies>之间):

<!--Netflix Eureka依赖-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2、然后在pom.xml的<project></project>之间增加以下关于springcloud的版本管理:

<dependencyManagement>
	<dependencies>
		<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-dependencies</artifactId>
		<version>${spring-cloud.version}</version>
		<type>pom</type>
		<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

3、接着在在pom.xml的<properties></properties>中增加以下配置(注意:Greenwich对应的是springboot2.1.x版本,如果换成其他的会报错,就这个坑把我坑了一个下午):

<spring-cloud.version>Greenwich.SR3</spring-cloud.version>

4、还有在application.properties中增加如下配置:

1)eureka服务器是这样配置的:

server.port=8761

spring.application.name=eureka-server-1

#注册的域名(注意:可以使用localhost,但在高可用时,不同的eureka-server必须要使用不同的hostname,否则无法相互发现)
eureka.instance.hostname=eureka-server-1
#是否向注册中心注册自己(非高可用时为false,高可用时为true)
eureka.client.registerWithEureka=true
#是否从eureka上获取信息(非高可用时为false,高可用时为true)
eureka.client.fetchRegistry=true
#eureka通信地址(非高可用时写自己的eureka-server地址,高可用时填高可用的目标eureka-server地址)
eureka.client.serviceUrl.defaultZone=http\://eureka-server-2\:8762/eureka/

2)eureka服务提供者是这样配置的:

server.port=8771

spring.application.name=client1

eureka.instance.prefer-ip-address=true
#多个eureka-server时可用","号分隔
eureka.client.serviceUrl.defaultZone=http\://localhost\:8761/eureka/

5、最后在springboot的启动文件xxxApplication.java中增加对应的注解:

1)eureka服务器要使用@EnableEurekaServer注解:

package com.zero4j.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

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

}

2)eureka服务器要使用@EurekaClient1Application注解:

package com.zero4j.eurekaclient1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient   //也可以用EnableDiscoveryClient代替,前者兼容性更大,后者仅能兼容Eureka
public class EurekaClient1Application {

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

}

 

访问eureka-server对应的端口,将会显示以下是最终的运行结果:

123

 

二、Eureka服务消费者的相关配置

1、首先到https://start.spring.io/中创建版本为2.1.x项目,在本地的IDEA导入后,首先在pom.xml中增加以下依赖(在pom.xml的<dependencies></dependencies>之间):

<!--Netflix Eureka依赖-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

2、然后在pom.xml的<project></project>之间增加以下关于springcloud的版本管理:

<dependencyManagement>
	<dependencies>
		<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-dependencies</artifactId>
		<version>${spring-cloud.version}</version>
		<type>pom</type>
		<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

3、接着在在pom.xml的<properties></properties>中增加以下配置(注意:Greenwich对应的是springboot2.1.x版本,如果换成其他的会报错,就这个坑把我坑了一个下午):

<spring-cloud.version>Greenwich.SR3</spring-cloud.version>

4、还有在application.properties中增加如下配置:

#消费者端口
server.port=8081
spring.application.name=eureka-consumer-1
eureka.instance.hostname=localhost
eureka.client.service-url.defaultZone=http\://localhost\:8761/eureka/,http\://localhost\:8762/eureka/

5、创建RestTemplate模板配置

package com.zero4j.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
	
	/**
     * RestTemplate:提供了多种便捷访问远程Http服务的方法
     * 是一种简单便捷访问Restful服务模板类,提供用于访问Rest服务的客户端模板类
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    
}

6、消费者调用eureka服务示例

package com.zero4j.controller;

import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/")
public class TestControllerProvider {
	
	@Autowired
    private RestTemplate restTemplate;

	@GetMapping("/test")
    public String test() {
		
		//通过服务提供者名称调用
		//List<Dept> depts = restTemplate.getForObject("http://wzx-spring-cloud-provider/dept/findAll", List.class);
		//return depts;
		
		String test = restTemplate.getForObject("http://eureka-client-1/test", String.class);
		
		return test;
    }
	
}

7、服务提供者的java示例

package com.zero4j.controller;

import java.util.Random;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/")
public class TestControllerProvider {

	@GetMapping("/test")
    public String test() {
        return "服务提供者1:"+String.valueOf((new Random()).nextInt());
    }
	
}

配置SpringBoot的全局事务,解决在Controller中使用SessionFactory必须要使用注解@Transactional的问题

增加以下两个配置文件:

TransactionAdviceConfig.java

package com.zero4j.config;


import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

@Aspect
@Configuration
public class TransactionAdviceConfig {

	 //使dao使用session
	private static final String AOP_POINTCUT_EXPRESSION = " (execution(* com..dao..*.*(..))) ";
	//controller由过滤器中进行设置,这里设置会抽风
	/*private static final String AOP_POINTCUT_EXPRESSION2 = " (execution(* com..controller..*.*(..))) ";*/
	 
	 
    @Autowired
    private PlatformTransactionManager transactionManager;

    @Bean
    public TransactionInterceptor txAdvice() {

        DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
        txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
        txAttr_REQUIRED_READONLY.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        txAttr_REQUIRED_READONLY.setReadOnly(true);
        
        
        DefaultTransactionAttribute txAttr_READONLY = new DefaultTransactionAttribute();
        txAttr_READONLY.setReadOnly(true);
        
        

        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

        source.addTransactionalMethod("save*", txAttr_REQUIRED);
        source.addTransactionalMethod("add*", txAttr_REQUIRED);
        source.addTransactionalMethod("create*", txAttr_REQUIRED);
        source.addTransactionalMethod("insert*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("merge*", txAttr_REQUIRED);
        source.addTransactionalMethod("del*", txAttr_REQUIRED);
        source.addTransactionalMethod("remove*", txAttr_REQUIRED);
        source.addTransactionalMethod("put*", txAttr_REQUIRED);
        source.addTransactionalMethod("use*", txAttr_REQUIRED);
        source.addTransactionalMethod("exec*", txAttr_REQUIRED);
        source.addTransactionalMethod("set*", txAttr_REQUIRED);
        
        
        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);//特殊,service在save后会重新读取,如果设置成REQUIRED_READONLY,则save不会保存数据
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);
        
        /*
        source.addTransactionalMethod("save*", txAttr_REQUIRED);
        source.addTransactionalMethod("delete*", txAttr_REQUIRED);
        source.addTransactionalMethod("update*", txAttr_REQUIRED);
        source.addTransactionalMethod("exec*", txAttr_REQUIRED);
        source.addTransactionalMethod("set*", txAttr_REQUIRED);
        source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
        source.addTransactionalMethod("is*", txAttr_REQUIRED_READONLY);
        
        */
        source.addTransactionalMethod("*", txAttr_READONLY);
        return new TransactionInterceptor(transactionManager, source);
    }

    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression( AOP_POINTCUT_EXPRESSION );
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
    
   /* @Bean
    public Advisor txAdviceAdvisor2() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression( AOP_POINTCUT_EXPRESSION2 );
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }*/
}

FilterConfig.java

package com.zero4j.config;


import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.support.OpenSessionInViewFilter;

@Aspect
@Configuration
public class FilterConfig {

	//解决调用接口时session抽风的问题
	@Bean
	public FilterRegistrationBean<OpenSessionInViewFilter> testFilterRegistration() {	
		FilterRegistrationBean<OpenSessionInViewFilter> registration = new FilterRegistrationBean<>();
		registration.setFilter(new OpenSessionInViewFilter());
		registration.addUrlPatterns("/*");//配置过滤路径
		return registration;
	}
	
}

 

SpringBoot利用Redis对session进行共享

1、引入pom依赖包

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>

2、配置application.application

# spring session使用存储类型
spring.session.store-type=redis

#配置redis集群

spring.redis.cluster.nodes=192.168.1.55:7000,192.168.1.53:7003

3、启动类中增加@EnableRedisHttpSession

4、使用
request.getSession().setAttribute(“username”, “admin”);
String userName = (String) request.getSession().getAttribute(“username”);

SpringBoot2+JPA引入对Redis的支持

在pom.xml加入:

        <!-- 对Redis的支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

增加配置文件RedisConfig.java:

package com.zero4j.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.lang.reflect.Method;

/**
 * Redis 缓存配置类(通用)
 * @author linhongcun
 *
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * 缓存对象集合中,缓存是以 key-value 形式保存的。当不指定缓存的 key 时,SpringBoot 会使用 SimpleKeyGenerator 生成 key。
     * @return
     */
    @Bean
    public KeyGenerator wiselyKeyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };

    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
    	return RedisCacheManager.create(factory);
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        @SuppressWarnings({ "rawtypes", "unchecked" })
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

在application.properties中加入:

# Redis
spring.redis.host=127.0.0.1
spring.redis.port=6379

对Service类加入注解@CacheConfig和@Cacheable,如:

package com.zero4j.model.config;

import java.util.List;

import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

@Repository
@CacheConfig(cacheNames = "configRepository")
public interface ConfigRepository extends JpaRepository<Config, String> {

	@Query("SELECT config FROM Config config")
	@Cacheable(value = "findAll",keyGenerator="wiselyKeyGenerator")
	List<Config> findAll();
	
}

 

研究SpringBoot与非SpringBoot项目以及搭配MyBatis/JPA/Hibernate的并发性能浅度测试

测试环境服务器参数:

CPU:4核8G带宽200M
RDS:1核1G
操作系统:Linux
JDK版本:1.8
WEB容器:Tomcat 8
压测工具:JMeter 3.2

每个组合分别的test内容基本如下(根据搭配的数据库不同,有些方法命名稍有差异):

@Controller
@RequestMapping("")
public class RootController {
	
	@Autowired
    private UserService userService;
	
	@RequestMapping(value={"","/","/index"})
	String view(Map<String, Object> map){
    	
    	System.out.println("首页(default)");
    	
    	map.put("name", "SpringBoot");
		map.put("date", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    	
  		return "index.jsp";
  		
  	}
	
	@RequestMapping(value={"test1"})
	@ResponseBody
	String test() {

		String str = "(new Random()).nextInt() = "+(new Random()).nextInt();
		
		System.out.println(str);
		
		return str;
		
    }
	
	@RequestMapping(value="test2")
  	public void test2(HttpServletRequest request, HttpServletResponse response) {

		String str = "(new Random()).nextInt() = "+(new Random()).nextInt();
		
		System.out.println(str);
		
		ResponseStaticUtil.write(response, str);
  	}
	
	@RequestMapping(value={"get1"})
	@ResponseBody
	String get1() {

		User user = this.userService.get(1);
		String str = "user = "+user.getName()+" / (new Random()).nextInt() = "+(new Random()).nextInt();
		
		System.out.println(str);
		
		return str;
		
    }
	
  	@RequestMapping(value="get2")
  	public void get2(HttpServletRequest request, HttpServletResponse response) {
  		
  		User user = this.userService.get(1);
		String str = "user = "+user.getName()+" / (new Random()).nextInt() = "+(new Random()).nextInt();
		
		System.out.println(str);
  		
  		ResponseStaticUtil.write(response, str);
  	}
	
	@RequestMapping(value={"list1"})
	@ResponseBody
	String list() {

		List<User> users = this.userService.listAll();
		String str = "users.size()= "+users.size()+" / (new Random()).nextInt() = "+(new Random()).nextInt();
		System.out.println(str);
		
		return str;
		
    }
	
	@RequestMapping(value="list2")
  	public void list2(HttpServletRequest request, HttpServletResponse response) {

		List<User> users = this.userService.listAll();
		String str = "users.size()= "+users.size()+" / (new Random()).nextInt() = "+(new Random()).nextInt();
		System.out.println(str);
		
		ResponseStaticUtil.write(response, str);
		
    }
	
}

 

普通SpringMVC+Hibernate项目的各Controller压力测试结果:
123

SpringBoot+MyBatis项目的各Controller压力测试结果:
SpringBoot+Hibernate项目的各Controller压力测试结果

 

SpringBoot+JPA项目的各Controller压力测试结果:
123

SpringBoot+Hibernate项目的各Controller压力测试结果:
123

 

” SpringBoot+MyBatis / SpringBoot+JPA / SpringBoot+Hibernate ” 的get单个user对象压力测试对比:
" SpringBoot+MyBatis / SpringBoot+JPA / SpringBoot+Hibernate " 的get单个user对象压力测试对比

” SpringBoot+MyBatis / SpringBoot+JPA / SpringBoot+Hibernate ” 的获取user所有对象(只有3个数据)压力测试对比:
" SpringBoot+MyBatis / SpringBoot+JPA / SpringBoot+Hibernate " 的获取user所有对象(只有3个数据)压力测试对比

 

总结:

1、在写Controller方法时,普通SpringMVC框架在使用普通的response.write的方式时效率很高,但使用annotation的方式返回数据时效率十分低;反之,使用SpringBoot框架在使用annotation的方式返回数据时效率比传统的response.write方式的运行效率要高出一截。

2、在SpringBoot框架下搭配分别搭配MyBatis、JPA、Hibernate时,其运行效率的差异不大,JPA的方式稍弱一点点。

 

本文属于“cp锋”的原创,虽然内容不是十分精品,但还望尊重本人的研究成果,转发时请注明转载并带上本页面链接,感谢~

Spring boot设置文件上传大小限制

Spring Boot做文件上传时出现了报错

The field file exceeds its maximum permitted size of 1048576 bytes

显示文件的大小超出了允许的范围。查看了官方文档,原来Spring Boot工程嵌入的tomcat限制了请求的文件大小默认为1MB,单次请求的文件的总数不能大于10Mb.要更改这个默认值需要在配置文件(如application.properties)中加入两个配置.

springboot 1.4之前是这样的:

multipart.maxFileSize = 10485760       //单个文件的大小
multipart.maxRequestSize = 10485760     //单次请求的文件的总大小

springboot 1.4之后是这样的:

spring.http.multipart.maxFileSize = 10485760
spring.http.multipart.maxRequestSize = 10485760

springboot 2.0之后是这样的:

spring.servlet.multipart.max-file-size = 10485760
spring.servlet.multipart.max-request-size = 10485760

注意:很多其他网站是让你们用10Mb这样的形式去赋值的,但事实上这样会报错,这里的单位是以字节b为单位的,我们可以调成他原来的1048576 bytes的10倍,也就是10MB大概等于10485760

JAVA的各种HTTP/HTTPS模拟请求使用经验汇总

https:

try{
			

			
		StringBuffer reultBuffer = new StringBuffer();
			
		KeyStore keyStore  = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File("/home/certificate/apiclient_cert.p12"));
	        String passwordssss=mch_id;
	        keyStore.load(instream, passwordssss.toCharArray());	//证书密码
	        instream.close();
	        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, passwordssss.toCharArray()).build();	//证书密码(初始是商户ID)
	        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
	        
		HttpPost httpPost = new HttpPost("https://fraud.mch.weixin.qq.com/risk/getpublickey");
	        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
	        httpPost.setHeader("Content-Type", "text/xml; charset=UTF-8");
	        httpPost.setEntity(new StringEntity(str_lingqian.toString(),"UTF-8"));
	        
	        CloseableHttpResponse response      = null;
	        InputStream inputStream		        = null;
	        InputStreamReader inputStreamReader = null;
	        BufferedReader bufferedReader       = null;
	        try {
	        	response = httpclient.execute(httpPost);
	        	HttpEntity entity = response.getEntity();
				if (entity!=null){
					inputStream = entity.getContent();
					inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
					bufferedReader = new BufferedReader(inputStreamReader);
					String str = null;
					while ((str = bufferedReader.readLine()) != null) {
						reultBuffer.append(str);
						System.out.println(str);
					}
				}
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}finally{

				httpclient.close();
				response.close();
				bufferedReader.close();
				inputStreamReader.close();
				inputStream.close();
				inputStream = null;
			}
	     
	        Document document = DocumentHelper.parseText(reultBuffer.toString());
	        Element rootElm = document.getRootElement();
	        if(rootElm.elementText("return_code").toString().equals("SUCCESS") && rootElm.elementText("result_code").toString().equals("SUCCESS") ){
	        	pub_key = rootElm.elementText("pub_key").toString();
	        	System.out.println("pub_key = "+pub_key);
	        }else{	        	
	        	return status;
	        }
			
}catch(Exception e){
	e.printStackTrace();
}

 

close