1. 程式人生 > >使用IDEA基於springboot開發ssm框架(undertow代替tomcat以及其他功能)

使用IDEA基於springboot開發ssm框架(undertow代替tomcat以及其他功能)

在這裡,第二次使用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
    訪問index
  • 斷點上傳
    斷點上傳
  • 下載
    下載