1. 程式人生 > >關於IDEA中建立springboot+security+jpa

關於IDEA中建立springboot+security+jpa

首先本文章不會分析框架的底層程式碼只是幫助小白快速搭建專案,因為官方文件都寫的明明白白,其中spring Security安全框架可能有部分小白看不懂官方文件

廢話不多說了進入正題:因為springboot推薦使用Maven(依賴管理框架) 如何使用springboot呢? 在maven的專案目錄src/main/java下建立BootApplication類(可以改名)

BootApplication類 (該類是springboot的入口類用於啟動springboot):
@EnableTransactionManagement
//用於開啟事務註解
@SpringBootApplication
//Springboot的啟動入口類 @EnableWebSecurity //啟用web安全 //@Configuration //@Import({ // DispatcherServletAutoConfiguration.class, // EmbeddedServletContainerAutoConfiguration.class, // ErrorMvcAutoConfiguration.class, // HttpEncodingAutoConfiguration.class, // HttpMessageConvertersAutoConfiguration.class, // JacksonAutoConfiguration.class,
// JmxAutoConfiguration.class, // MultipartAutoConfiguration.class, // ServerPropertiesAutoConfiguration.class, // PropertyPlaceholderAutoConfiguration.class, // ThymeleafAutoConfiguration.class, // WebMvcAutoConfiguration.class, // WebSocketAutoConfiguration.class, // //})//用於自定義載入哪些類 public class
BootApplication extends SpringBootServletInitializer{ public static void main(String[] args) { SpringApplication.run(BootApplication.class, args); }}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com</groupId>
   <artifactId>boot</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>boot</name>
   <description>Demo project for Spring Boot</description>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.6.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>
<!--此包是themeleaf模板所需jar包-->
<dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
      <dependency>
      <groupId>org.thymeleaf.extras</groupId>
      <artifactId>thymeleaf-extras-springsecurity4</artifactId>
     </dependency>
<!--web應用所需的包-->
<dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </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>
<!--此包用於簡化程式碼可以使用註解自動生成get set等方法-->
<dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.16.10</version>
      </dependency>
<!--此包用於對資料庫操作基於hibernate-->
<dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
<!--阿里連線池所需包-->
<dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>druid</artifactId>
         <version>1.0.25</version>
      </dependency>
<!--spring安全框架包-->
<dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

現在只需要建一個Controller類即可

@RestController
public class Rest {
    @Autowired
private TestService testService;
@Secured("ROLE_user")
    @RequestMapping("/v1/{name}")//Rest Api風格
    //@PathVariable用於獲取Url上的引數
public List<User> boot(@PathVariable String name) {

        List<User> list=testService.findAll();
System.out.println(list.get(0).getUrole());
String data = "{\"name\":\"張三\"}";
        return list;
}

}
@RestController是springboot中的新增註解用於開發restful風格api介面 該註解相當於@Controller和@ResponseBody 合用返回的是json格式資料

因為springboot內建了tomcat所以只需要執行BootApplocation類  輸入 localhost:8080/v1/name 即可在瀏覽器中返回{“name”:“張三”}的資料 

是不是相當簡單,沒有ssh或ssm那麼多繁瑣的配置檔案,也不需要在web中配置mvc,spring

如果你想使用資料庫,springboot提供了jpa用於操作資料庫(至於什麼是jpa,簡單說jpa是貌似2006年5月提出的一種ORM持久化規範,它只是一種規範,而我們最常用的hibernate是對jpa的實現,也叫jpa產品) springboot的jpa是基於hibernate的但是他進行了進一步封裝,使開發人員更好的與資料庫進行互動,首先需要在pom.xml中加入依賴(上面的依賴已經假如,請看上邊的pom)  在springboot的配置檔案中加入

#配置資料庫
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=abc
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

  在建立bean  

//@Getter @Setter 是lok外掛中用於幫助自動建立getset方法還有許多註解等用 如果使用@Data
//@Min 是用於欄位驗證的註解
/*@Data   :註解在類上;提供類所有屬性的 getting 和 setting 方法,此外還提供了equals、canEqual、hashCode、toString 方法
  @Setter:註解在屬性上;為屬性提供 setting 方法
  @Getter:註解在屬性上;為屬性提供 getting 方法
  @Log4j :註解在類上;為類提供一個 屬性名為log 的 log4j 日誌物件
  @NoArgsConstructor:註解在類上;為類提供一個無參的構造方法
  @AllArgsConstructor:註解在類上;為類提供一個全參的構造方法
  @Transient表示屬性不與資料庫對映
  */
@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Getter @Setter private Integer uid;
@NotBlank(message = "使用者名稱不能為空")
    @Column(name = "username")
    @Getter @Setter private String username;
@NotBlank(message = "密碼不能為空")
    @Column(name = "password")
    @Getter @Setter private String password;
@NotNull(message = "年齡不能為空")//NotNull用於基本資料型別
@Min(value =18,message = "年齡必須大於等於18")
    @Column(name = "sage")
    @Getter @Setter private Integer sage;
/* @NotNull(message = "性別不能為空")*/
@Column(name = "ssex")
    @NotBlank(message = "性別不為空")//只能用於String
@Getter @Setter private String ssex;
@Column(name = "urole")
    @JsonIgnore  //在json序列化時忽略該屬性  因為在懶載入時候返回json資料時會出現錯誤重複載入
@ManyToMany(cascade = CascadeType.REFRESH,fetch = FetchType.LAZY)//optional設定外來鍵是否可以為空
@JoinTable(name ="u_r",joinColumns ={@JoinColumn(name = "uid")},inverseJoinColumns = {@JoinColumn(name = "rid")})
    @Getter @Setter private Set<Role> urole=new HashSet<Role>();
}

可能有注意到為什麼屬性沒有get set方法,因為我是用來lombok這個jar,它可以使用註解來自動生成get set用於簡化程式碼

,接著我們新建DaoImpl介面繼承JpaRepository(該類已經實現了簡單的crud操作我們無需實現Test介面)如果你想自己寫sql可以使用@Query註解在方法上按jpa規定的格式建立方法例如下面的findByUsername方法(沒有使用@Query是因為這個方法太簡單框架幫我們實現了)

public interface Test  extends JpaRepository<User,Long>{
    User findByUsername(String username);
}

在Server層我們直接呼叫Test介面即可

@Autowired
private Test test;
public List<User> findAll() {
     return test.findAll();
}

在controller中呼叫test即可實現全查

接下來看如何使用security

原來在ssh中使用security中首先匯入匯入security的包接著在web中配置代理過濾器

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

在配置security的配置檔案

<?xml version="1.0" encoding="UTF-8"?> 
<b:beans xmlns="http://www.springframework.org/schema/security"
   xmlns:b="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<!-- 配置不攔截登陸頁面 由於從3.1開始不再支援filters="none"-->
<http pattern="/index.jsp" security="none"></http>
<http pattern="/*.js" security="none"></http>
<!-- 開啟攔截連  use-expressions="false"用於關閉表示式的許可權控制-->
<http auto-config="true" use-expressions="true"  >
  <!--   配置自定義登入頁面 -->
  <form-login login-page="/index.jsp" authentication-failure-forward-url="/index.jsp" default-target-url="/success.jsp" />
 
<!--     配置攔截規則 -->
 <intercept-url pattern="/success.jsp" access="hasAnyRole('ROLE_USER','ROLE_admin')"/>
<!--  關閉跨域訪問 -->
 <csrf disabled="true"/>
<!--  配置session超時跳轉頁面  -->
 <session-management invalid-session-url="/index.jsp">
    <!--  最大允許1個使用者登入 -->
     <!-- <concurrency-control max-sessions="2" error-if-maximum-exceeded="true"/> -->
 </session-management>
<!--許可權不夠跳轉頁面  繼承AccessDeniedHandler自定義403頁面-->
 <access-denied-handler ref="accessDeniedServletHandler"/>
<!--  登出 -->
 <logout logout-url="/logout" logout-success-url="/index.jsp"  invalidate-session="true" delete-cookies="JSESSIONID"/>
</http>
<authentication-manager alias="authenticationManager">
    <authentication-provider ref="authenticationProvider">
     
 <!-- <user-service >
     配置多個使用者
  <user name="user" password="123456" authorities="ROLE_USER" />
  <user name="user1" password="123456" authorities="ROLE_ccc" />  
 </user-service> -->
 </authentication-provider>
 </authentication-manager>
 <!-- 註冊authenticationManager用於載入錯誤資訊 -->
<b:bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
 <b:property name="messageSource" ref="messageSource"></b:property>
</b:bean> <b:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <b:property name="hideUserNotFoundExceptions" value="false"></b:property>
    <b:property name="userDetailsService" ref="security"></b:property>
</b:bean> 
<!-- 修改spring security的預設國際化資原始檔 -->
<b:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<b:property name="basename" value="classpath:messages_zh_CN"></b:property>
</b:bean>
</b:beans>

看到上面的配置檔案是不是眼花 沒關係springboot與security高度整合 (web配置?不需要,xml?不需要)我們來零配置來使用security

首先我們在BootApplocation上用

@EnableWebSecurity 開啟Web

建立一個類繼承 WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
//開啟方法許可權註解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

   /* @Autowired
    private AuthenticationManager authenticationManager;*///如果想讓許可權註解生效必須加註入此bean
@Autowired
private MyAccessDeniedHandle myAccessDeniedHandle;
@Autowired
private MySecurity mySecurity;
@Override
public void configure(WebSecurity web) throws Exception {
        //配置靜態資源不攔截
web.ignoring().antMatchers("/static/**", "/**/*.jsp");
}

    @Override
protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/","/excep").permitAll()//配置不攔截Url
.anyRequest().authenticated()
                .and()//相當於結束標籤
.formLogin()
                .loginPage("/")
                .loginProcessingUrl("/action_security")//必須是post請求 如果為Get不生效
.usernameParameter("username")
                .passwordParameter("password")//配置登陸頁面
.successForwardUrl("/login")
                .failureUrl("/")
                .permitAll()//所有使用者都能訪問這個頁面
.and()
                .rememberMe()
                .userDetailsService(mySecurity)
                .tokenValiditySeconds(90000)
                .key("abc")
                .rememberMeParameter("rememberMe")
                .rememberMeCookieName("zxl")
                .and()
                .exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandle)//配置403許可權頁面 myAccessDeniedHandl自定義bean 如果不想自定義可以簡單的使用.accessDeniedPage()指定403頁面
.and()
                .logout()
                .invalidateHttpSession(false)
                .permitAll()
                .and()
                .csrf().disable();//關閉csrf 如果開啟後登出只能使用post請求用於防止別人偽造logout
}
    //使用BCrypt密碼加密
@Bean
public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
}
    /*  //異常訊息載入類
     @Bean
    public ReloadableResourceBundleMessageSource bundleMessageSource(){
        ReloadableResourceBundleMessageSource bundleMessageSource=new ReloadableResourceBundleMessageSource();
        bundleMessageSource.setBasename("classpath:messages_zh_CN");
        return bundleMessageSource;
    }
    @Bean
    //自定義的驗證類
    public DaoAuthenticationProvider daoAuthenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider=new DaoAuthenticationProvider();
       daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
       daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
       daoAuthenticationProvider.setUserDetailsService(mySecurity);
       return daoAuthenticationProvider;
    }
    //載入異常訊息
    @Bean
    public ProviderManager providerManager(){
        List<AuthenticationProvider> list=new ArrayList<>();
        list.add(daoAuthenticationProvider());
        ProviderManager providerManager=new ProviderManager(list);
        providerManager.setMessageSource(bundleMessageSource());
        return providerManager;
    }*/
@Bean
//自定義的驗證類
public DaoAuthenticationProvider daoAuthenticationProvider(){
        DaoAuthenticationProvider daoAuthenticationProvider=new DaoAuthenticationProvider();
daoAuthenticationProvider.setHideUserNotFoundExceptions(false);//用於捕捉使用者不存在異常
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
daoAuthenticationProvider.setUserDetailsService(mySecurity);
        return daoAuthenticationProvider;
}



}

該類相當於Security中xml配置檔案 如果想使用xml與其混合使用可以使用@Configuration註解來引用xml 

原來使用security的自定義國際化需要配置bean   現在無需配置只需要在maven的resources資料夾建立一個空的messages.properties 在建立一個messages_zh_CN.properties資料夾org/springframework/security/spring-security-core/4.2.3.RELEASE/spring-security-core-4.2.3.RELEASE.jar!/org/springframework/security/messages_zh_CN.properties

中複製到剛才的zh_CN資料夾中即可自定義異常訊息