网站首页 文章专栏 spring boot搭建本网站详细过程以及踩过的坑
spring boot搭建本网站详细过程以及踩过的坑

准备工作:

使用最新版本spring boot 2.0.3.RELEASE,IntelliJ IDEA 开发工具,jpa交互数据,thymeleaf模板引擎,一套标准的spring boot全家桶

一. 搭建项目

打开idea,新建项目

1.png

选择spring boot项目和jdk版本

3.png

更改项目属性,spring boot可以不需要tomcat以jar包运行,也可以放入tomcat以war包运行。这里我选择jar。

4.png

选择需要的依赖

5.png

删除不需要的.mvn,mvnw,mvnw.cmd三个包

6.png

项目初步完成。


二. 配置项目依赖和配置文件

1.完整的依赖如下:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

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

    <!--好用的插件-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
    </dependency>

    <!--qq互联用到的jar包-->
    <dependency>
        <groupId>qqConnect</groupId>
        <artifactId>qqConnect</artifactId>
        <version>1.1</version>
    </dependency>

    <!--json-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.3</version>
    </dependency>

    <!-- 热加载 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

2. spring boot配置文件

项目相比于传统的ssm项目优势之一就在于不需要配置繁琐的配置文件,基本只需要一个配置文件就行,项目搭建完成后会生成application.properties默认配置文件,觉得这种不好用,改为application.yml文件,.yml文件在写的时候层次感强,而且可以少写代码。

3. 在项目中配置多套环境的配置方法。

        因为现在一个项目有好多环境,开发环境,测试环境,准生产环境,生产环境,每个环境的参数不同,所以我们就可以把每个环境的参数配置到yml文件中,这样在想用哪个环境的时候只需要在主配置文件中将用的配置文件写上就行如下:

先新建两个.yml文件, application-dev.yml,application-prod.yml,分别可以写入不同的参数,在application.yml中只需要写以下指定哪一个配置文件。

spring:
  profiles:
    active: dev

完整的.yml文件如下:

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: 用户名
    password: 数据库密码
    url: jdbc:mysql://ip:3306/数据库名?characterEncoding=utf-8&useSSL=false
  jpa:
      show-sql: true
  jackson:
    default-property-inclusion: non_null
    date-format: yyyy-MM-dd HH:mm
    time-zone: GMT+8
  thymeleaf:
    prefix: classpath:templates/view/    #使用thymeleaf
    suffix: .html
    mode: HTML5
    encoding: UTF-8
    servlet:
      content-type: text/html
    cache: false
  application:
    name: 项目名
logging:
  level:
    com.yx: debug
server:
  servlet:
    context-path: /    #设置访问前不需加名称

4. 配置日志

日志我使用的是logback,可以简单配置,也可以复杂配置

简单配置:只需要在.yml里加上如下使用默认配置即可

logging:
  pattern:
    console: "%d - %msg%n"
  path: /var/log/tomcat/
  file: /var/log/tomcat/sell.log
  level:
    com.yx: debug

我使用的是自定义日志,编写logback-spring.xml文件

<?xml version="1.0" encoding="UTF-8" ?>

<configuration>

    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                %d - %msg%n
            </pattern>
        </layout>
    </appender>

    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %msg%n
            </pattern>
        </encoder>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--路径-->
            <fileNamePattern>/var/log/tomcat/xingchenge/info.%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>


    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>
                %msg%n
            </pattern>
        </encoder>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--路径-->
            <fileNamePattern>/var/log/tomcat/xingchenge/error.%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="consoleLog" />
        <appender-ref ref="fileInfoLog" />
        <appender-ref ref="fileErrorLog" />
    </root>

</configuration>

5. 构建项目包

在项目启动类同级新建controller,dataObject,service等包,在resources下的static下新建js,css,images等静态资源,在temlates下新建view目录,在view目录下便是 .html文件了。

项目完整路径如下:

7.png



三,编写测试页面

1. model层

@Entity
@Data
@DynamicUpdate
public class Test implements Serializable {

    @Id
    @GeneratedValue
    private Integer id; 
    private String name; 
    private Date addTime; 
}

如上为Test测试实体类,含有id,name,addTime三个属性。@Data为lombok插件,可以不用写get,set等方法。

2.repository层

public interface TestRepository extends JpaRepository<Test,Integer> {

    Page<Test> findAllByName(String name,Pageable pageable);

}

jpa其内在还是hibernate,只需继承JpaRepository,便可使用继承的查询等方法,好处在于简单的查询根本就不需要写sql或者hql,只需要根据命名规则就可以简单的条件查询加分页。但是对于复杂连表查询,也提供了hql和原生sql的方法。以下是查询命名规则:

KeywordSampleJPQL snippet
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is,EqualsfindByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age ⇐ ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNullfindByAgeIsNull… where x.age is null
IsNotNull,NotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1 (parameter bound with appended %)
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1 (parameter bound with prepended %)
ContainingfindByFirstnameContaining… where x.firstname like ?1 (parameter bound wrapped in %)
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection ages)… where x.age in ?1
NotInfindByAgeNotIn(Collectionage)… where x.age not in ?1
TRUEfindByActiveTrue()… where x.active = true
FALSEfindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

3. service层

public interface TestService {

    Page<Test> findAllByName(String name,Pageable pageable);

}
@Service
@Slf4j
public class TestServiceImpl implements TestService {

    @Autowired
    private TestRepository testRepository;
    
    @Override
    @Transactional            // 事物加此注解即可,这里其实不需要
    public Page<Test> findAllByName(String name,Pageable pageable) {
        return testRepository.findAllByName(name,pageable);
    }
}


 4. controller层

@RestController
@Slf4j
public class TestController {

    @Autowired
    private TestService testServer;

    @RequestMapping("/")
    public ModelAndView test(Map<String, Object> map) {
        try {
            log.info("=========进入测试controller=====");
            // 获取数据
            Page<Test> testPage = testServer.findAllByName("test",new PageRequest(0, 10));
            map.put("testList",testPage.getContent());
        } catch (Exception e){
            log.error("加载失败,{}",e);
        }
        return new ModelAndView("test",map);
    }
}

如上代码分页获取数据库10条test数据;

@RestController = @Controller + @ResponseBody

@Slf4j 配合lombok,直接使用 log日志对象,等同于 private  final Logger log= LoggerFactory.getLogger(XXX.class);

5.html层

在templates的view下新建test.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>测试页面</title>
</head>
<body>
    <div th:each="test,status:${testList}">
        <span th:text="${test.id}"></span>
        <span th:text="${test.name}"></span>
        <span th:text="${#dates.format(test.addTime , 'yyyy-MM-dd HH:mm')}"></span>
    </div>
</body>
</html>

至此,一个简单的demo就完成了,本网站便是在此基础上完成的。


四,配置自定义异常页面

在controller层新建controller如下:

@Controller
public class MainsiteErrorController implements ErrorController {

    @RequestMapping("/error")
    public String handleError(HttpServletRequest request){
        //获取statusCode:401,404,500
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if(statusCode == 404){
            return "404";
        }else if(statusCode == 403){
            return "403";
        }else{
            return "500";
        }

    }
    @Override
    public String getErrorPath() {
        return "error";
    }
}

在在templates的view下新建相应的404,403,500,error错误页即可。

 注意坑点 :return “404”;我之前写的是“/404”,在本地跑可以,访问路径错误时就到自定义的错误页了,但是在服务器上跑时却提示找不到404.html,经查找,把/去掉就可以了,以相对路径加载,虽说很小的问题,也卡了我有一回,mark下。


五,统一异常处理

新建自定义异常类并继承RunTimeException,重载构造函数,1:可传入自定义枚举类,2:传入code和message,这么做是为了业务上的方便。

@Getter
public class ServiceException extends RuntimeException{

    private Integer code;

    public ServiceException(ResultEnum resultEnum) {
        super(resultEnum.getMessage());

        this.code = resultEnum.getCode();
    }

    public ServiceException(Integer code, String message) {
        super(message);
        this.code = code;
    }
}

新建异常处理类

@ControllerAdvice
public class ServiceExceptionHandler {

    @ExceptionHandler(value = ServiceException.class)
    @ResponseBody
    public ResultVO handlerSellerException(ServiceException e) {
        return ResultVOUtil.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(value = ResponseBankException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public void handleResponseBankException() {

    }
}

这样在我们的其它层可返回自定义的异常,如下:

    @PostMapping("/create")
    public ResultVO<Map<String, String>> create(@Valid OrderForm orderForm,
                                                BindingResult bindingResult) {    
        if (bindingResult.hasErrors()) {
            log.error("【获取数据】参数不正确, orderForm={}", orderForm);
            throw new SellException(ResultEnum.PARAM_ERROR.getCode(),
                    bindingResult.getFieldError().getDefaultMessage());
        }
    }

可以返回我们想要的code,和message,配合自定义的enum枚举类,对于错误异常就有了明确的规定。





版权声明:本文由星尘阁原创出品,转载请注明出处!

本文链接:http://www.52xingchen.cn/detail/40




赞助本站,网站的发展离不开你们的支持!
来说两句吧
最新评论