使用IDEA基於springboot開發ssm框架(undertow代替tomcat以及其他功能)
阿新 • • 發佈:2018-12-09
在這裡,第二次使用springboot開發,看過我之前的文章可知。因為spirngboot是去除xml等繁瑣配置,大部分內容都已經幫你設定好,因此需要有一定的spring基礎才能學習,不然不明白原理會難以下手。
文件結構圖
1. pom.xml需要引入的依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId >
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding >UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--事務處理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId> spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--資料庫連線池-->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!--斷點上傳工具-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>-->
</dependency>
<!--undertow伺服器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--freemarker ftl-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!--打包時的名字-->
<finalName>webApp</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<!--打包時跳過單元測試類-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
2. application.yml中相關配置
spring:
datasource:
hikari:
username: root
password: ####
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
max-lifetime: 176500
maximum-pool-size: 15
connection-timeout: 30000
redis:
host: 192.168.110.130
port: 6379
password: ####
timeout: 500 #超時時間
pool:
maxWaitMillis: -1 #連線池最大阻塞等待時間(使用負值表示沒有限制)
maxIdle: 8 #最大空閒連線
server:
undertow:
buffer-size: 1024
direct-buffers: true
#DEBUG模式
logging:
level: debug
3. Main主函式入口相關配置
@Configuration
@Controller
@ComponentScan(basePackages = "com.example.demo") //掃描註解
@MapperScan("com.example.demo.dao") //掃描介面
@SpringBootApplication //開啟初始化配置,必須有
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
@EnableTransactionManagement //開啟事務
@EnableCaching //開啟快取
public class DemoApplication {
@Autowired
private UserService userService;
@RequestMapping("/index")
public String index(){
return "index";
}
/*@Bean
public StringHttpMessageConverter stringHttpMessageConverter(){
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("ISO-8859-1"));
return stringHttpMessageConverter;
}
spring boot預設使用utf-8的訊息轉發器,這裡可以進行覆蓋測試
*/
@RequestMapping("/upload")
public @ResponseBody String upload(@RequestParam("files")MultipartFile[] files) throws Exception{
String path = "E:\\upload\\";
for(int i = 0;i<files.length;i++){
if(!files[i].isEmpty()){
String filename = files[i].getOriginalFilename();
String new_filename = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));
File f = new File(path + new_filename);
// System.out.println(f.toString());
files[i].transferTo(f);//sd
}
}
return "up success";
}
@RequestMapping("/download")
public String download(HttpServletResponse response){
String filename = "test.pdf";
response.setHeader("content-type","application/octet-stream");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition","attachment;filename="+filename);
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
os = response.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(new File("E:\\upload\\"+filename)));
int i;
while((i = bis.read(buff)) != -1){
os.write(buff,0,buff.length);
os.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
os.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return "down success";
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4. 自定義Config相關配置
- Hikari配置
@Configuration
public class HikariConfig {
/*如果有其他需求可以在這裡配置*/
@Bean
@ConfigurationProperties(prefix = "spring.dataSource.hikari")
public DataSource dataSource(){
HikariDataSource hikariDataSource = new HikariDataSource();
// hikariDataSource.setConnectionTimeout(50000);優先順序沒有application.yml高
System.out.println("Hikari載入成功");
return hikariDataSource;
}
}
- 攔截器配置
//自定義攔截器,繼承WebMvcConfigurerAdapter並且重寫addInterceptors方法,然後新增攔截策略
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
System.out.println("CustomInterceptor載入成功");
registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/**");
}
}
- 檔案上傳配置
@Configuration
public class MultipartConfig {
@Bean
public MultipartResolver multipartResolver(){
CustomMultipartResolver resolver = new CustomMultipartResolver();
System.out.println("CustomMultipartResolver載入成功");
resolver.setMaxUploadSize(1024*1024*100);//5MB
return resolver;
}
}
- mybatis配置
@Configuration
public class MybatisConfig {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
System.out.println("SqlSessionFactoryBean載入成功");
return sqlSessionFactoryBean;
}
}
- redis配置
@Configuration
public class RedisConfig extends CachingConfigurerSupport{
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.pool.maxIdle}")
private int maxIdle;
@Value("${spring.redis.pool.maxWaitMillis}")
private int maxWaitMillis;
@Bean
public JedisPool jedisPool(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMinIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
JedisPool jedisPool = new JedisPool(jedisPoolConfig,host,port,timeout,password);
System.out.println("jedis配置完成");
return jedisPool;
}
}
- undertow配置
@Configuration
public class UndertowConfig {
@Bean
@ConfigurationProperties(prefix = "server.undertow")
public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory(){
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
System.out.println("undertow載入成功");
// factory.setPort(8088);
return factory;
}
}
5. 攔截器類
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("攔截在這兒");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
6. 檔案斷點上傳類
- 監聽條
@Component
public class FileUpLoadProgressListener implements ProgressListener {
private HttpSession session;
public void setSession(HttpSession session){
this.session = session;
ProgressEntity status = new ProgressEntity();
session.setAttribute("status",status);
}
@Override
public void update(long nowByte, long process, int count) {
ProgressEntity progressEntity = (ProgressEntity) session.getAttribute("status");
progressEntity.setUpByte(nowByte);
progressEntity.setUpSize(process);
progressEntity.setUpItems(count);
System.out.println("裝載檔案上傳內容。。。" + progressEntity);
}
}
- 繼承重寫
public class CustomMultipartResolver extends CommonsMultipartResolver{
@Autowired
private FileUpLoadProgressListener listener;
@Override
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
listener.setSession(request.getSession());
fileUpload.setProgressListener(listener);
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems,encoding);
} catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
}
catch (FileUploadBase.FileSizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex);
}
catch (FileUploadException ex) {
throw new MultipartException("Failed to parse multipart servlet request", ex);
}
}
}
7. 自定義全域性異常類
@ControllerAdvice
public class GlobalException {
@ExceptionHandler(Exception.class)
@ResponseBody
public Map<String,Object> exceptionHandler(Model model){
HashMap<String, Object> result = new HashMap<>();
result.put("code",500);
result.put("message","親,系統錯誤請稍後重試...");
//返回json格式
return result;
}
}
8. dao層配置
- mybatis
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user")
public List<User> selectAll();
}
- redis
@Repository
public class RedisClient {
@Autowired
private JedisPool jedisPool;
public void addJsonData(String key,String target){
jedisPool.getResource().set(key,target);
}
public boolean isExistKey(String key){
Boolean result = jedisPool.getResource().exists(key);
return result;
}
}
9. 實體類配置
- ProgressEntity
//涉及流,需要序列化
public class ProgressEntity implements Serializable{
private long upByte = 0L;
private long upSize = 0L;
private int upItems;
@Override
public String toString() {
return "ProgressEntity{" +
"upByte=" + upByte +
", upSize=" + upSize +
", upItems=" + upItems +
'}';
}
public long getUpByte() {
return upByte;
}
public void setUpByte(long upByte) {
this.upByte = upByte;
}
public long getUpSize() {
return upSize;
}
public void setUpSize(long upSize) {
this.upSize = upSize;
}
public int getUpItems() {
return upItems;
}
public void setUpItems(int upItems) {
this.upItems = upItems;
}
}
- User
public class User implements Serializable{
private int id;
private String userName;
private String address;
private Date date;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", address='" + address + '\'' +
", date=" + date +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
10. service層配置
@Service
//@Transactional //這個註解可以加在類和方法,方法上說明此方法使用事務
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RedisClient redisClient;
/*測試redis快取*/
@Transactional(propagation = Propagation.SUPPORTS)
@Cacheable(value = "getAllUsers") //在getAllUsers找快取
public List<User> getAllUsers(){
System.out.println("如果第二次沒有列印,說明快取存在");
return userMapper.selectAll();
}
@Transactional(propagation = Propagation.REQUIRED)
@CacheEvict(value = "getAllUsers")//CacheEvict去除快取,CachePut加入快取
public void flushAllUsers(){
}
@Transactional(propagation = Propagation.REQUIRED)
public void addJson(String key,String target){
redisClient.addJsonData(key,target);
}
}
11. 測試結果
- 訪問index
- 斷點上傳
- 下載