• springboot入门


    入门

    版本:2.0.5

    项目初始化

    • 新建spring init项目
    • 可以:添加dev.yml和-prod.yml来区分开发和生成环境配置
    • 可以:修改配置文件为application.yml
    #可以配置启动文件
    spring:
      profiles:
        active: dev
    #可以修改端口号和启动路径
    server:
      port: 8080
      servlet:
        context-path: /girl
    

    选择不同配置文件启动:

    java -jar target/girl-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
    

    yml自定义属性

    先自定义

    girl:
      cupSize: F
      age: 18
    

    再读取:

    @Component
    @ConfigurationProperties(prefix = "girl")
    public class GirlProperties {
    
        private String cupSize;
    
        private Integer age;
    
        public String getCupSize() {
            return cupSize;
        }
    
        public void setCupSize(String cupSize) {
            this.cupSize = cupSize;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }
    

    controller

    springBoot推荐前后端分离,所以直接返回json

    • 注解:@RestController = @Controller + @ResponseBody

    springData

    1. 先引入
    <!--数据库-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    
    1. 再配置数据库

    yml文件

    #配置数据库
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/db_test
        username: root
        password: root
      jpa:
        database: MySQL
        show-sql: true
        generate-ddl: true
    

    pojo类

    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    @Entity
    public class Girl {
        @Id
        //设置自增,2.0之后要加后面的属性
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        private String cupSize;
    
        private int age;
    
        public Girl() {
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getCupSize() {
            return cupSize;
        }
    
        public void setCupSize(String cupSize) {
            this.cupSize = cupSize;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    

    dao层

    import org.springframework.data.jpa.repository.JpaRepository;
    
    /**
     * girl的操作类
     * Integer为主键ID的类型
     */
    public interface GirlRepository extends JpaRepository<Girl, Integer> {
        /**
         * 自定义扩展方法,按照年龄来查询
         * @param age
         * @return
         */
        public List<Girl> findByAge(Integer age);
    
    }
    

    service使用

    @Autowired
    private GirlRepository girlRepository;
    
    /**
     * 查询所有
     * @return
     */
    @GetMapping("/girls")
    public List<Girl> girlList() {
        return girlRepository.findAll();
    }
    
    /**
     * 新增一个女生
     * @param cupSize
     * @param age
     * @return
     */
    @PostMapping("/girls")
    public Girl girlAdd(@RequestParam("cupSize") String cupSize,
                        @RequestParam(value = "age",defaultValue = "18") int age) {
        Girl girl = new Girl();
        girl.setCupSize(cupSize);
        girl.setAge(age);
        return girlRepository.save(girl);
    }
    
    /**
     * 查询单个女生
     * @param id
     * @return
     */
    @GetMapping("/girls/{id}")
    public Girl girlFindOne(@PathVariable("id") Integer id) {
        return girlRepository.findById(id).get();
    }
    
    /**
     * 更新一个女生
     * @param id
     * @param cupSize
     * @param age
     * @return
     */
    @PutMapping("/girls/{id}")
    public Girl girlUpdate(@PathVariable("id") Integer id,
                           @RequestParam("cupSize") String cupSize,
                           @RequestParam(value = "age",defaultValue = "18") int age) {
        Girl girl = new Girl();
        girl.setId(id);
        girl.setCupSize(cupSize);
        girl.setAge(age);
    
        return girlRepository.save(girl);
    }
    
    /**
     * 根据ID删除一个女生
     * @param id
     */
    @DeleteMapping("/girls/{id}")
    public void girlDelete(@PathVariable("id") Integer id) {
        girlRepository.deleteById(id);
    }
    
    @GetMapping("/girls/age")
    public List<Girl> girlsByAge(Integer age) {
        return girlRepository.findByAge(age);
    }
    
    

    事务

    在service层方法添加 @Transactional注解即可

    静态资源

    在static下新建js和img和css即可。

    表单验证

    在domain里面添加注解

    @Min(value = 18,message = "年龄不能小于18岁")
    private int age;
    

    在controller里面添加

    /**
     * 新增一个女生
     * @param girl
     * @return
     */
    @PostMapping("/girls")
    public Girl girlAdd(@Valid Girl girl, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            System.out.println(bindingResult.getFieldError().getDefaultMessage());
            return null;
        }
        return girlRepository.save(girl);
    }
    

    AOP

    1. 先引入
    <!--开启aop-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    
    1. 然后在自定义的aspect上加注解

    aspect/HttpAspect.java

    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    
    @Component
    @Aspect
    public class HttpAspect {
        private final static Logger LOGGER = LoggerFactory.getLogger(HttpAspect.class);
    
        @Pointcut("execution(public * com.alvin.controller.GirlController.*(..))")
        public void log() {
        }
    
        @Before("log()")
        public void doBefore(JoinPoint joinPoint) {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            //url
            LOGGER.info("url={}", request.getRequestURL());
    
            //method
            LOGGER.info("method={}", request.getMethod());
    
            //ip
            LOGGER.info("ip={}", request.getRemoteAddr());
    
            //类方法
            LOGGER.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
    
            //参数
            LOGGER.info("args={}", joinPoint.getArgs());
        }
    
        @AfterReturning(returning = "object", pointcut = "log()")
        public void doAfterReturning(Object object) {
            LOGGER.info("response={}", object.toString());
        }
    }
    
    

    自定义全局异常

    先定义一个异常枚举

    enums/ResultEnum.java

    public enum ResultEnum {
        SUCCESS(0, "成功"),
        UNKOWN_ERROR(-1, "未知错误"),
    
        ;
    
        private Integer code;
        private String msg;
    
        ResultEnum(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public String getMsg() {
            return msg;
        }
    }
    

    先自定义一个异常类

    exception/GirlException.java

    public class GirlException extends RuntimeException {
        private int code;
    
        public GirlException(ResultEnum resultEnum) {
            super(resultEnum.getMsg());
            this.code = resultEnum.getCode();
        }
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    }
    

    再捕获异常

    handle/ExceptionHandle

    import com.alvin.domain.Result;
    import com.alvin.exception.GirlException;
    import com.alvin.utils.ResultUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @ControllerAdvice
    public class ExceptionHandle {
    
        private final static Logger LOGGER = LoggerFactory.getLogger(ExceptionHandle.class);
    
        @ExceptionHandler(value = Exception.class)
        @ResponseBody
        public Result handle(Exception e) {
            //判断是否是自定义的异常
            if (e instanceof GirlException) {
                GirlException girlException = (GirlException) e;
                return ResultUtil.error(girlException.getCode(), girlException.getMessage());
            } else {
                LOGGER.error("【系统异常】",e);
                return ResultUtil.error(100,e.getMessage());
            }
        }
    }
    

    单元测试

    在要测试的类上ctrl + shift + t 新建测试类

    普通测试

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class GirlServiceTest {
        @Autowired
        private GirlService girlService;
    
        @Test
        public void findById() throws Exception {
            Girl girl = girlService.findById(1);
            assertEquals(new Integer(20), girl.getAge());
        }
    }
    

    controller层测试

    模拟http请求

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    public class GirlControllerTest {
    
        @Autowired
        private MockMvc mvc;
    
        @Test
        public void girlFindOne() throws Exception {
            mvc.perform(MockMvcRequestBuilders.get("/girls/1"))
                    .andExpect(MockMvcResultMatchers.status().isOk()) //判断请求状态是否为200
                    .andExpect(MockMvcResultMatchers.content().string("abc")); //判断结果是否是abc
        }
    }
    

    项目打包

    # 进行单元测试并打包
    mvn clean package
    
    # 不进行单元测试并打包
    mvn clean package -Dmaven.test.skip=true
    

    linux部署

    直接启动

    nohup java -jar target/spring-boot-scheduler-1.0.0.jar &
    

    脚本启动和关闭:

    start.sh

     #!/bin/sh
    rm -f tpid
    nohup java -jar /data/app/myapp.jar --spring.profiles.active=stg > /dev/null 2>&1 &
    echo $! > tpid
    

    stop.sh

    tpid=`cat tpid | awk '{print $1}'`
    tpid=`ps -aef | grep $tpid | awk '{print $2}' |grep $tpid`
    if [ ${tpid} ]; then 
            kill -9 $tpid
    fi
    

    定时器

    先在springboot入口类添加注释:@EnableScheduling

    @SpringBootApplication
    @EnableScheduling
    public class GirlApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(GirlApplication.class, args);
        }
    }
    

    再在定时类上添加注解

    @Component
    public class printScheduler {
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @Scheduled(cron="0/5 * * * * ?")
        public void scheduleCheck() {
            logger.info("每5秒执行一次");
        }
    }
    

    整合其他框架

    freemarker

    引入

    <!--freemarker-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>
    

    controller层不要使用RESPController注解

    templates下面创建ftl格式的html文件(完整的html文件)

    用户列表:<br>
    <table border="1">
        <tr>
            <th>id</th>
            <th>username</th>
            <th>password</th>
            <th>name</th>
        </tr>
    		<#list userList as user>
    		<tr>
                <td>${user.id}</td>
                <td>${user.username}</td>
                <td>${user.password}</td>
                <td>${user.name}</td>
            </tr>
            </#list>
    </table>
    

    controller使用

    @RequestMapping("/findAllUser")
    public String findAllUser(Model model) {
        List<User> allUser = service.findAllUser();
        model.addAttribute("userList", allUser);
        System.out.println(allUser);
        return "hello";
    }
    

    mybatis

    pom引入

    <!--mybatis起步依赖-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.1.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    
    <!--配置xml资源-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    

    application.yml配置mybaits

    mybatis:
      type-aliases-package: com.alvin.demo.domain
      mapper-locations: classpath:mapper/*Mapper.xml
    

    项目入口加注解

    @MapperScan("com.alvin.demo.mapper")
    public class DemoApplication {
    

    直接使用即可

    如果要整合德鲁伊连接池,可以查看文章

    redis

    pom引入

    <!-- 配置使用redis启动器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    

    application.yml配置

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

    使用

    @Autowired
    private StringRedisTemplate redisTemplate;
    
    写入:
    redisTemplate.opsForValue().set("user", new ObjectMapper().writeValueAsString(user));
    
    读取User类:
    String userStr = redisTemplate.opsForValue().get("user");
    User user = new ObjectMapper().readValue(user, User.class);
    
    读取List<User>类
    String user = redisTemplate.opsForValue().get("userAll");
    ObjectMapper objectMapper = new ObjectMapper();
    JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, User.class);
    List<User> userList = objectMapper.readValue(user,javaType);
    

    使用redisCluster集群

    # 将配置修改为下面即可:
    spring.redis.cluster.nodes=192.168.25.153:7001,192.168.25.153:7002
    

    ElasticSearch

    pom引入

    <!--ElasticSearch-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    

    yml配置

    #elasticsearch
    spring:
      data:
        elasticsearch:
          cluster-name: my-elasticsearch
          cluster-nodes: 127.0.0.1:9300,127.0.0.1:9301,127.0.0.1:9302
    

    实体

    @Document(indexName = "blog4", type = "article")
    public class UserEntity {
        @Id
        @Field(type = FieldType.Long, store = true)
        private long id;
        @Field(type = FieldType.Text, store = true, analyzer = "ik_max_word")
        private String title;
        @Field(type = FieldType.Text, store = true, analyzer = "ik_max_word")
        private String content;
        ……
    

    使用

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    
    @Test
    public void createIndex() {
        elasticsearchTemplate.createIndex(UserEntity.class);
        elasticsearchTemplate.putMapping(UserEntity.class);
    }
    @Test
    public void testUserRepository() {
        UserEntity user = new UserEntity();
        user.setId(1);
        user.setTitle("zhangsan");
        user.setContent("123");
        userRepository.save(user);
    }
    

    如果报错(实例化失败),添加运行时参数

    -Des.set.netty.runtime.available.processors=false
    
  • 相关阅读:
    查看mysql数据库引擎
    crontab 从nano 转换为 vim
    Linux中,去掉终端显示的当前目录的绝对路径
    nginx 卸载后重新安装/etc/nginx配置文件没了,cannot open /etc/nginx/nginx.conf (No such file or directory)
    rabbitmq 配置
    OSError: mysql_config not found
    No module named 'ConfigParser'
    windows 安装tensorflow
    微服务架构设计
    centOS rabbitmq 安装
  • 原文地址:https://www.cnblogs.com/birdofparadise/p/10013160.html
Copyright © 2020-2023  润新知