必学框架新版SpringBoot教程(下集)

举报
摸鱼打酱油 发表于 2022/04/01 22:29:44 2022/04/01
【摘要】 个人简介作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门。@[toc] SpringBoot+JDBC1.导入JDBC和mysql的依赖在Pom.xml导入以下依赖 <dependency> <groupId>mysql</groupId> <...

个人简介

作者是一个来自河源的大三在校生,以下笔记都是作者自学之路的一些浅薄经验,如有错误请指正,将来会不断的完善笔记,帮助更多的Java爱好者入门。
@[toc]

SpringBoot+JDBC

1.导入JDBC和mysql的依赖

在Pom.xml导入以下依赖

        <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>

2.在application的配置文件配置数据源(DataSource)

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/ssmrl?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=18420163207

3.测试数据源是否生效

在SpringBoot单元测试进行

@SpringBootTest
class DemoApplicationTests {
    @Autowired    //自动注入数据源,因为我们已经配置过了(application.properties),它会在IOC容器去找到数据源
    private  DataSource dataSource;

    @Test
    void contextLoads() {
        System.out.println(dataSource);
    }

}

运行结果如下:

image-20210113161631607

结论:我们从输出结果可以看到,SpringBoot默认的数据源是HikariDataSource,这个数据源是目前最快的数据源,比阿里巴巴的Druid还要快,但是DruidDatasource有监控功能,后面再说

SpringBoot原生JDBC

1.在SpringBoot单元测试类中:

@SpringBootTest
class DemoApplicationTests {
    @Autowired
    private  DataSource dataSource;

    @Test
    void contextLoads() throws SQLException {

        Connection connection = dataSource.getConnection();
        String sql="select empid,empName from emp";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()){
            System.out.println(resultSet.getInt(1)+"    "+resultSet.getString(2));
        }

    }

}

输出结果如下:

image-20210113162723306

SpringBoot+JdbcTemplate

JdbcTemplate是Spring对JDBC的封装,目的是让Jdbc更加容易使用

image-20210113164334271

说明我们的JdbcTemplate可以正常使用了

**里面的sql语句可以写预处理,也就是用“ ? ”占位 **

查询单个数据:

image-20210113165628283

查询多个数据:

image-20210113165815772


SpringBoot+Druid

因为我们在DataSourceAutoConfiguration类中看到如下代码:

@Import({Hikari.class, Tomcat.class, Dbcp2.class, OracleUcp.class, Generic.class, DataSourceJmxConfiguration.class})
    protected static class PooledDataSourceConfiguration {
        protected PooledDataSourceConfiguration() {
        }
    }

Hikari.class 导入了Hikari的数据源,SpringBoot默认自带了HikariDataSource,如何切换数据源呢?

我们只需要在配置文件加上一句代码:

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

添加Druid数据源的监控功能

public abstract class ResourceServlet extends HttpServlet {
    //Druid监控的帐号密码
    private static final Log LOG = LogFactory.getLog(ResourceServlet.class);
    public static final String SESSION_USER_KEY = "druid-user";
    public static final String PARAM_NAME_USERNAME = "loginUsername"; //配置帐号
    public static final String PARAM_NAME_PASSWORD = "loginPassword"; //配置密码

因为我们在配置文件指定了spring.datasource.type=com.alibaba.druid.pool.DruidDataSource,会自动使用SpringBoot的默认配置,我们不想这样可以自己写一个Druid配置类,然后在附加上去

@Configuration
public class myDruid {

    //指定前缀为:spring.datasource
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean  //添加到IOC容器中去
    public DataSource druidDatasource(){
        DruidDataSource druidDataSource=new DruidDataSource();
        return druidDataSource;
    }

    //添加Druid监控,这个ServletRegisterBean相当于web.xml的<servlet></servlet>
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        //指定servlet的类
        ServletRegistrationBean servletRegistrationBean=new ServletRegistrationBean(new StatViewServlet());
        //配置映射路径
        servletRegistrationBean.addUrlMappings("/druid/*");
        //配置帐号密码
        servletRegistrationBean.addInitParameter("loginUsername","admin");
        servletRegistrationBean.addInitParameter("loginPassword","123456");
        return servletRegistrationBean;
    }
}

这样就完成啦

image-20210113172829360

输入刚刚配置的帐号密码就可以进入

image-20210113172854913

SpringBoot+Mybatis

image-20210116152421022

image-20210116152434429

image-20210116152457152

image-20210116152513332

springBoot+Mybatis整合比较简单

@Mapper:作用在dao接口上,作用就是把这个接口转换成可以注入的实现类。(注意,此时只是转换成了实现类,并没有在IOC容器中,所以我们还要加上组件注解,如@Repository,不然会不起作用)

也可以在springBoot启动类加上:@MapperScan:扫描一个包上的Mapper接口,并将自动转换成实现类,这时候我们在加上一个组件注解,然后@AutoWired就可以了。

具体的SpringBoot+Mybatis原理还未掌握。。。


SpringBoot+Mybtis绑定异常解决

绑定异常有很多种,当我们Mapper和Mapper.xml都绑定起来了,但是还报错。

image-20210128114800015

解决方法:在POM.xml加上Mybatis的文件过滤:

         <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>

SpringBoot异步任务

使用场景:比如我们发送验证码,从前端发送请求到后端是要等待的(网络通信是有延迟的),比如我们发送成功一个验证码需要3s,如果不是异步操作,我们就处于“单线程“的状态,会在3s内都无法在页面进行任何操作,这样用户体验感会很差,如果我们是异步任务,就相当于“多线程”,会单独的开启一个线程去发送验证码,另外一个线程以供用户操作页面,这样用户的体验感会更好。

@Async:标注这个类或者方法是异步的,标注之后就相当于另外开启了一个线程去处理这个@Async方法

@EnableAsync:开启异步任务功能。(必须要有)

@SpringBootApplication
@EnableAsync  //开启异步任务功能。
public class DemoApplication {

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

}

Async的方法要放在另外的类上,不然会导致异步功能失效

错误示范:

image-20210117230956632

发现上面的写法,@Async不起作用。

正确写法:

image-20210117231249701

image-20210117231338074

这样就生效了,所以结论是,@Async异步任务需要单独放在其他类上。。。。。(很重要)

SpringBoot定时任务

主要是运用cron表达式,进行定时的操作

public class MySend {
    //每两秒执行一次。
    @Scheduled(cron = "0/2 * * * * ? ")
    public void send(){
         System.out.println("hello");
    }

}
@SpringBootApplication
@EnableScheduling //开启定时任务,定时任务是cron表达式
public class DemoApplication {

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

}

SpringBoot邮件任务

SpringBoot把原生java发送邮件的代码进行进一步的封装,使得原来十分繁琐的过程变得极其好用。

1.在Pom.xml导入对应的邮件启动器

<!--        springBoot邮件启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

2.开启qq邮箱的SMTP服务

image-20210118174756651

3.获取SMTP授权码

image-20210118174701564

4.配置application-dev.properties

#发送邮箱配置
spring.mail.host=smtp.qq.com
spring.mail.username=1550324080@qq.com #邮箱号
spring.mail.password=zgwjpsscpsidicce   #授权码(不是密码)
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

发送简单邮件

5.用测试类去测试一下

@SpringBootTest
class DemoApplicationTests {
    @Autowired
    JavaMailSenderImpl javaMailSender; //邮件发送必须要的类
    @Test
    void contextLoads(){
        //发送简单邮件用SimpleMailMessage类
        SimpleMailMessage simpleMailMessage=new SimpleMailMessage();
        simpleMailMessage.setFrom("1550324080@qq.com"); //从哪个邮箱发送
        simpleMailMessage.setTo("1550324080@qq.com");  //发送到哪个邮箱
        simpleMailMessage.setSentDate(new Date()); //日期
        simpleMailMessage.setText("hello");  //内容文本
        simpleMailMessage.setSubject("主题"); //题目
        javaMailSender.send(simpleMailMessage); //开启发送邮件。。需要时间去发送,这里我们可以用异步方法,提升体验感
    }
}

发现报错了。。。

image-20210118180513820

成功了!!!!

image-20210118181901117

这里有个要注意的点,就是刚刚为什么会报错。

当我们自动装配 JavaMailSenderImpl javaMailSender;会显示无法找到他对应的bean。。。导致刚刚报错

因为我们邮箱的配置必须要在application.properties里面配置,而不能在application-dev.properties配置

image-20210118182343270

发送复杂邮件

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    JavaMailSenderImpl javaMailSender;

    @Test
    void contextLoads() throws MessagingException, FileNotFoundException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage(); //创建复杂邮件
        //*****需要上传附件,就要在MimeMessageHelper的构造器加上true,不然会报错****
        MimeMessageHelper mimeMessageHelper=new MimeMessageHelper(mimeMessage,true); //创建MimeMessageHelper去封装MimeMessage
        mimeMessageHelper.setFrom("1550324080@qq.com");
        mimeMessageHelper.setTo("1550324080@qq.com");
        mimeMessageHelper.setSubject("主题");
        mimeMessageHelper.setText("<h3>h3字体</h3><br/><h5>h5字体</h5>");
//        FileSystemResource fileSystemResource = new FileSystemResource(new File("C:\\Users\\youzhengjie666\\Pictures\\1.PNG"));

       //上传附件
        mimeMessageHelper.addAttachment("tupian1",new File("C:\\Users\\youzhengjie666\\Pictures\\1.PNG"));

        javaMailSender.send(mimeMessage);


    }

}

SpringBoot+Shiro安全框架

1.先导入Shiro-spring的依赖

<!--        shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.2</version>
        </dependency>

2.创建一个类,去配置shiro

package com.boot.shiro;

import com.boot.realm.myRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Servlet;
import java.util.ArrayList;
import java.util.LinkedHashMap;

@Configuration
public class myShiro {

    //配置加密
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        return hashedCredentialsMatcher;
    }


    @Bean
    public Realm realm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher hashedCredentialsMatcher){
        myRealm myRealm=new myRealm();
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return myRealm;
    }


    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("realm") Realm realm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }


    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor();
        return lifecycleBeanPostProcessor;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean setshiroFilter(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        shiroFilterFactoryBean.setLoginUrl("/tologin");
        shiroFilterFactoryBean.setSuccessUrl("/tolist");
        shiroFilterFactoryBean.setUnauthorizedUrl("/tounauth");

        LinkedHashMap<String, String> filters = new LinkedHashMap<>();
        filters.put("/tologin","anon");
        filters.put("/login","anon");
        filters.put("/toadmin","roles[admin]");
        filters.put("/touser","roles[user]");
        filters.put("/**","authc");


        shiroFilterFactoryBean.setFilterChainDefinitionMap(filters);

        return shiroFilterFactoryBean;
    }


//    @Bean
//    public FilterRegistrationBean shiroFilter(){
//        FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean();
//        filterRegistrationBean.setFilter(new DelegatingFilterProxy());
//        ArrayList<Object> list = new ArrayList<>();
//        list.add("/**");
//        filterRegistrationBean.setUrlPatterns(list);
//
//        return filterRegistrationBean;
//    }

 


}

3.创建一个类,配置realm

package com.boot.realm;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.HashSet;
import java.util.Set;

public class myRealm extends AuthorizingRealm {


    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //模仿从后台查询数据库
        String us="123";
        String pd="202cb962ac59075b964b07152d234b70"; //原密码是:123  ,这是MD5加密而成的

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(us,pd,this.getName());

        return info;
    }

       @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取principal===>也就是我们传入的帐号
        String principal = (String) principalCollection.getPrimaryPrincipal();

        Set<String> roles=new HashSet<>();
        roles.add("admin");
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo(roles);

        return simpleAuthorizationInfo;
    }


}

4.配置controller层

@Controller
public class testController {

    @RequestMapping(path = "/tologin")
    public String tologin(){
        return "login";
    }


    @RequestMapping(path = "/login")
    public String login(String username,String password){

        Subject subject = SecurityUtils.getSubject();

        if(!subject.isAuthenticated()){
            UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);

            try {
                subject.login(usernamePasswordToken);
            }catch (Exception e){
                return "redirect:tologin";
            }

        }

        return "forward:tolist";
    }



    @RequestMapping(path = "/tolist")
    public String tolist(){
        return "list";
    }
    @RequestMapping(path = "/tounauth")
    public String tounauth(){
        return "unauth";
    }

    @RequestMapping(path = "/toadmin")
    public String toadmin(){
        return "role_admin";
    }

    @RequestMapping(path = "/touser")
    public String touser(){
        return "role_user";
    }

}

5.需要的html文件

image-20210122143848238

扩展MVC

扩展SpringMVC只需要去实现WebMvcConfigurer类就可以了,并且这个类是配置类

如果加了@EnableWebMVC注解,就相当于全面接管SpringMVC,也就是会把SpringBoot默认配置全部失效

@Configuration
public class myMvcConfig implements WebMvcConfigurer {

    //添加视图跳转
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

        //这个代码相当于==>
        //@RequestMapping("/test")
        //public String xxx{
        // return "role_admin";
        //}
        registry.addViewController("/test").setViewName("role_admin");

    }

 
}

页面国际化

image-20210127145329346

创建xxx.properties作为默认国际化配置文件,xxx_zh_CN.properties作为中文配置,xxx_en_US.properties作为英文配置,这个Resource Bundle 'login’是会自动生成的

进入login.properties

image-20210127145551970

左上角有个“+”号,就是用来添加国家化消息的

在application-dev.properties指定国家化消息的basename,因为我们自定义了xxx.properties的xxx是login,所以login就是我们的总的国家化配置文件,只需要绑定这个login就行了

image-20210127145922680

spring.messages.basename=i18n.login //i18n就是我们用来存放国家化配置文件的包名

login.html

<form th:action="@{/login}" th:method="post">
    <span th:text="#{username}"></span><input type="text" name="username">
    <br/>
    <span th:text="#{password}"></span>:<input type="password" name="password">
    <br/>
    <input type="submit" th:value="#{submit}">
</form>


<a th:href="@{/tologin(locale='zh_CN')}">中文</a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a th:href="@{/tologin(locale='en_US')}">English</a>

注意:thymeleaf的#{}就是用来取国家化消息的

此时我们想进行中英文切换。我们需要做如下配置:

1.在login.html中传locale

<a th:href="@{/tologin(locale='zh_CN')}">中文</a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a th:href="@{/tologin(locale='en_US')}">English</a>

2.配置自定义的localeResolver

public class myLocale implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        Locale aDefault = Locale.getDefault();//获取默认的Locale
        String locale = request.getParameter("locale"); //获取login.html传来的语言
        if(!StringUtils.isEmpty(locale)){
            //zh_CN 要变成====>Locale("zh","CN"),只有把"_"分割成zh和CN
            String language=locale.charAt(0)+""+locale.charAt(1);
            String country=locale.charAt(3)+""+locale.charAt(4);
            return new Locale(language, country);
        }

        return aDefault;
    }

    @Override
    public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {

    }
}

3.将这个自定义LocaleResolver交给Spring管理

注意:这个自定义地区解析器的Bean的id必须是“ localeResolver ”,不然会找不到这个Bean

@Configuration
public class myLocaleConfig {

    @Bean("localeResolver") 
    public myLocale localeResolver(){

        return new myLocale();
    }


}

然后就大功告成了

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。