在現(xiàn)代的Web應(yīng)用中,保護(hù)敏感接口不被未授權(quán)用戶訪問是非常重要的,尤其是在Spring Boot框架中。實(shí)現(xiàn)這一功能,通常通過攔截器、過濾器或Spring Security進(jìn)行身份驗(yàn)證和授權(quán)來完成。此舉不僅確保了用戶信息的安全性,也提升了系統(tǒng)的可靠性。
Spring Security是一個(gè)功能強(qiáng)大的安全框架,它提供了一整套的安全機(jī)制來控制用戶的身份驗(yàn)證和訪問權(quán)限。通過簡單的配置,可以針對特定的API接口設(shè)置權(quán)限,只允許已登錄用戶進(jìn)行訪問。使用Spring Security不僅方便,還能享受到其成熟的安全特性,如CSRF防護(hù)、會話管理等。
實(shí)現(xiàn)不登錄不允許訪問接口的步驟主要包括以下幾點(diǎn):
org.springframework.boot
spring-boot-starter-security
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/public/**").permitAll() // 允許公開訪問的接口
.anyRequest().authenticated() // 其他接口需要認(rèn)證
.and()
.httpBasic(); // 使用basic認(rèn)證
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("password")).roles("USER");
}
在實(shí)際開發(fā)中,可能會有更具體的訪問控制需求,Spring Security可以通過多種方式來滿足。例如,可以根據(jù)用戶的角色或權(quán)限對不同API進(jìn)行訪問控制。這意味著開發(fā)者可以在具體的業(yè)務(wù)邏輯中,根據(jù)用戶身份決定是否允許訪問特定資源。
除了Spring Security,也可以使用Servlet過濾器來實(shí)現(xiàn)接口的權(quán)限控制。用戶請求到達(dá)Servlet之前,過濾器可以對請求進(jìn)行檢查,判斷用戶是否登錄。如果未登錄,直接返回錯(cuò)誤響應(yīng);如果已登錄,繼續(xù)請求的處理。
@WebFilter(urlPatterns = "/api/protected/*")
public class AuthenticationFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String token = req.getHeader("Authorization");
if (token == null || !isValidToken(token)) {
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
chain.doFilter(request, response);
}
}
JWT(JSON Web Token)是一種無狀態(tài)的認(rèn)證機(jī)制,特別適用于現(xiàn)代Web應(yīng)用。通過JWT,后端可以生成一個(gè)token,前端在后續(xù)請求中攜帶該token,后端通過驗(yàn)證token的有效性來判斷用戶身份。這種方式不需要在服務(wù)器上存儲用戶的會話狀態(tài),極大地減輕了服務(wù)器的負(fù)擔(dān)。
public String generateToken(UserDetails userDetails) {
Map claims = new HashMap();
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 過期時(shí)間
.signWith(SignatureAlgorithm.HS256, "secret")
.compact();
}
為什么要使用Spring Security實(shí)現(xiàn)接口訪問控制? Spring Security為我們提供了成熟的API與功能,可通過最少的配置完成復(fù)雜的安全設(shè)置,確保系統(tǒng)安全高效。
在沒有Spring Security的情況下,怎么控制接口的訪問? 可以考慮使用Servlet過濾器進(jìn)行基本的身份驗(yàn)證,或是使用自定義的注解與AOP結(jié)合來實(shí)現(xiàn)訪問邏輯。
如果使用JWT會有什么優(yōu)勢? JWT是輕量級的認(rèn)證機(jī)制,沒有狀態(tài),無需在服務(wù)器保存會話信息,有助于分布式系統(tǒng)架構(gòu)的實(shí)現(xiàn)。
]]>在本篇文章中,我們將講解如何在Spring框架中實(shí)施事務(wù)管理。事務(wù)管理是確保數(shù)據(jù)一致性和完整性的關(guān)鍵要素,特別是在涉及到多個(gè)數(shù)據(jù)庫操作的場景中。我們將展示如何配置Spring事務(wù)管理,使用注解實(shí)現(xiàn)聲明式事務(wù),以及在程序中使用事務(wù)的技巧和注意事項(xiàng)。
為了順利完成接下來的操作,您需要具備以下環(huán)境和依賴:
確保您已安裝了上述的開發(fā)工具,并創(chuàng)建了一個(gè)簡單的Spring項(xiàng)目。
如果您使用Maven作為構(gòu)建工具,可以在pom.xml
文件中添加以下依賴:
org.springframework
spring-context
5.3.10
org.springframework
spring-tx
5.3.10
mysql
mysql-connector-java
8.0.26
接下來,在application.properties
文件中進(jìn)行數(shù)據(jù)源的配置:
spring.datasource.url=jdbc:mysql://localhost:3306/your_database?useSSL=false
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
在Spring配置類中啟用事務(wù)管理。在您的配置類上使用@EnableTransactionManagement注解:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
@Configuration
@EnableTransactionManagement
public class AppConfig {
// 其它Bean配置
@Bean
public JpaTransactionManager transactionManager() {
return new JpaTransactionManager();
}
// 如果用到JPA,記得配置Entity Manager
}
在服務(wù)類中使用@Transactional注解來定義事務(wù)。在這個(gè)示例中,我們創(chuàng)建一個(gè)服務(wù)類,該類的一個(gè)方法將執(zhí)行多個(gè)數(shù)據(jù)庫操作:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Transactional
public void createUserWithTransaction(User user) {
userRepository.save(user);
// 可能會拋出異常的操作
anotherOperation();
}
public void anotherOperation() {
// 其它邏輯
}
}
默認(rèn)情況下,如果方法拋出RuntimeException,事務(wù)將回滾。如果您想要自定義回滾行為,可以在@Transactional注解中使用參數(shù):
@Transactional(rollbackFor = Exception.class)
public void createUserWithTransaction(User user) {
// 邏輯
}
在操作的過程中,我們涉及到了一些關(guān)鍵概念,以下是對它們的解釋:
在Spring中,嵌套事務(wù)默認(rèn)是通過保存點(diǎn)來處理的。若外層事務(wù)回滾,則內(nèi)層事務(wù)亦會回滾??梢酝ㄟ^更改Propagation屬性來控制嵌套事務(wù)的行為:
@Transactional(propagation = Propagation.NESTED)
public void methodInNestedTransaction() {
// 邏輯
}
在異步執(zhí)行的場景中,事務(wù)不會自動傳播。因此,要在異步方法中手動處理事務(wù)。為了確保事務(wù)一致性,您可以使用CompletableFuture
結(jié)合手動事務(wù)管理。
使用連接池可以提升性能,在application.properties
中添加連接池配置,例如HikariCP:
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
綜上所述,本文通過分步指導(dǎo),展示了如何在Spring中實(shí)現(xiàn)事務(wù)管理。通過理解關(guān)鍵概念和常見問題,您可以更好地掌握Spring事務(wù)管理,提高應(yīng)用程序的可靠性與數(shù)據(jù)一致性。
]]>Spring Cloud Alibaba Sidecar 是一種輕量級的服務(wù)代理,它支持微服務(wù)架構(gòu)中的服務(wù)發(fā)現(xiàn)、負(fù)載均衡和熔斷保護(hù)等功能。借助 Sidecar,可以將非 Spring Cloud 應(yīng)用與 Spring Cloud 生態(tài)系統(tǒng)集成,從而實(shí)現(xiàn)服務(wù)治理。本文將提供一個(gè)詳細(xì)的操作步驟指南,幫助用戶快速上手使用 Sidecar 技術(shù)。
在開始之前,請確保以下技術(shù)環(huán)境準(zhǔn)備就緒:
使用 Spring Initializr 創(chuàng)建一個(gè)新的 Spring Boot 項(xiàng)目:
curl https://start.spring.io/starter.zip -o my-sidecar-app.zip -d dependencies=cloud-starter-alibaba-nacos-discovery,cloud-starter-alibaba-nacos-config,cloud-starter-alibaba-sidecar
解壓下載的文件并進(jìn)入項(xiàng)目目錄:
unzip my-sidecar-app.zip && cd my-sidecar-app
在項(xiàng)目的 pom.xml 中添加 Spring Cloud Alibaba Sidecar 相關(guān)依賴:
com.alibaba.cloud
spring-cloud-starter-alibaba-sidecar
同時(shí),定義其他所需的依賴:
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
要配置 Nacos 服務(wù)發(fā)現(xiàn),首先需要在 src/main/resources/application.yml 中添加以下配置:
spring:
application:
name: my-sidecar-app
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
確保您已經(jīng)啟動了 Nacos 服務(wù),默認(rèn)端口為 8848。
在 src/main/java/com/example/mysidecarapp 目錄下創(chuàng)建一個(gè)控制器文件 MyController.java:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/hello")
public String hello() {
return "Hello from Sidecar!";
}
}
在同一個(gè) application.yml 文件中,配置 Sidecar 的相關(guān)信息:
spring:
cloud:
sidecar:
application:
name: my-sidecar
services:
- url: http://localhost:8080
service-id: my-sidecar-app
使用以下命令運(yùn)行 Spring Boot 應(yīng)用程序:
mvn spring-boot:run
在瀏覽器中訪問 http://localhost:8080/hello,您應(yīng)該會看到 “Hello from Sidecar!” 的響應(yīng)。
如果您選擇使用 Docker 部署應(yīng)用,可以在項(xiàng)目根目錄創(chuàng)建一個(gè) Dockerfile:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
COPY target/my-sidecar-app.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
構(gòu)建 Docker 鏡像:
docker build -t my-sidecar-app .
運(yùn)行 Docker 容器:
docker run -p 8080:8080 my-sidecar-app
通過以上步驟,您已經(jīng)成功配置了一個(gè)簡單的 Spring Cloud Alibaba Sidecar 應(yīng)用,并了解了如何將其與 Nacos 集成。繼續(xù)探索更多的功能以滿足您的微服務(wù)需求。
]]>
Druid連接池是一款用于Java應(yīng)用程序的高性能數(shù)據(jù)庫連接池。它是阿里巴巴開源的一款連接池,具有監(jiān)控、擴(kuò)展和多種數(shù)據(jù)源支持等特點(diǎn)。使用Druid能夠有效地提升數(shù)據(jù)庫連接性能及應(yīng)用響應(yīng)能力。同時(shí),Druid還提供多種連接監(jiān)控功能,能幫助開發(fā)者快速定位性能瓶頸與高并發(fā)問題。
在Spring Boot項(xiàng)目中集成Druid連接池并不是特別復(fù)雜的過程,按照以下步驟可以輕松完成。
首先,在你的Spring Boot項(xiàng)目中引入Druid的依賴。可以在pom.xml中添加以下內(nèi)容。
com.alibaba
druid-spring-boot-starter
1.2.6
接下來,需要在application.properties或者application.yml中進(jìn)行一些配置。以下是基本的Druid配置示例:
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/yourdb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=rootpassword
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
spring.datasource.druid.max-wait=60000
spring.datasource.druid.filters=stat, log4j
為了更好地管理Druid連接池,我們可以創(chuàng)建一個(gè)配置類,這樣更符合Spring的管理規(guī)范。
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties("spring.datasource")
public DataSource dataSource() {
return DruidDataSourceBuilder.create().build();
}
}
Druid具有強(qiáng)大的監(jiān)控功能,可以在應(yīng)用中通過簡單的配置來打開監(jiān)控頁面。需要在application.properties中添加如下配置,并在你的Spring Boot項(xiàng)目中集成相應(yīng)的控制器。
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.web-stat-filter.enabled=true
配置完成后,可以通過簡單的單元測試或啟動主程序來驗(yàn)證Druid連接池的配置是否成功。在測試中,注意觀察控制臺輸出及Druid監(jiān)控頁面,確保連接池參數(shù)如最大連接數(shù)等配置的準(zhǔn)確性。
使用Druid連接池之后,你會發(fā)現(xiàn)整體數(shù)據(jù)庫操作的性能都有顯著的提升。這是因?yàn)镈ruid在連接的獲取與釋放上做了許多優(yōu)化。
在使用Druid的過程中,需特別注意連接的關(guān)閉。如果應(yīng)用中出現(xiàn)了大量的活躍連接,但未被及時(shí)關(guān)閉,可能會導(dǎo)致連接池資源耗盡。
到底為什么我們要選擇Druid連接池而不是其他連接池呢?
Druid連接池性能優(yōu)秀,特別是在高并發(fā)場景下,Druid的性能表現(xiàn)優(yōu)于大多數(shù)連接池;其次,其易用性和良好的文檔支持,使得新手和經(jīng)驗(yàn)豐富的開發(fā)者都能快速上手。
Druid和HikariCP兩者優(yōu)缺點(diǎn)各自是什么?
HikariCP通常以連接獲取速度快著稱,適合絕大多數(shù)場景,但在監(jiān)控和擴(kuò)展性上則稍顯不足。而Druid在監(jiān)控和擴(kuò)展性下功夫較多,因此在多數(shù)據(jù)源環(huán)境和需要復(fù)雜監(jiān)控的系統(tǒng)中更具優(yōu)勢。
使用Druid連接池后,我們應(yīng)該如何監(jiān)控其性能呢?
Druid本身提供了可視化的監(jiān)控頁面,可以通過在配置中開啟監(jiān)控功能,然后訪問相應(yīng)的URL進(jìn)行實(shí)時(shí)查看。此外,對于生產(chǎn)環(huán)境,也可以通過日志記錄連接池的狀態(tài)。
Druid連接池是否可以進(jìn)行擴(kuò)展與定制?
是的,Druid提供了多種配置項(xiàng)和擴(kuò)展接口,開發(fā)者可以根據(jù)實(shí)際項(xiàng)目需求進(jìn)行擴(kuò)展和定制。無論是自定義監(jiān)控參數(shù),還是擴(kuò)展數(shù)據(jù)源支持,Druid都能夠以較高的靈活性滿足不同場景的需要。
]]>在開發(fā)Spring Boot應(yīng)用時(shí),有時(shí)需要獲取當(dāng)前項(xiàng)目的絕對路徑,以便加載資源文件、配置文件或者進(jìn)行文件操作。Spring Boot提供了多種方法來實(shí)現(xiàn)這一目標(biāo)。本文將詳細(xì)介紹如何獲取項(xiàng)目的絕對路徑,并給出相應(yīng)的示例和注意事項(xiàng)。
可以通過Spring的ApplicationContext獲取當(dāng)前項(xiàng)目的路徑。如下所示:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class PathUtil {
@Autowired
private ApplicationContext applicationContext;
public String getProjectPath() {
return applicationContext.getApplicationName();
}
}
解釋:在這個(gè)示例中,通過@Autowired注入ApplicationContext,利用getApplicationName方法可以獲取應(yīng)用名稱。
可以利用Java系統(tǒng)屬性獲取當(dāng)前工作目錄:
public String getCurrentPath() {
return System.getProperty("user.dir");
}
解釋:這里的”user.dir”屬性返回當(dāng)前用戶的工作目錄,在Spring Boot項(xiàng)目中,它通常是項(xiàng)目的根目錄。
如果你是在Web環(huán)境中,可以通過ServletContext獲取絕對路徑:
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
@Component
public class WebPathUtil {
@Autowired
private ServletContext servletContext;
private String absolutePath;
@PostConstruct
public void init() {
absolutePath = servletContext.getRealPath("/");
}
public String getAbsolutePath() {
return absolutePath;
}
}
解釋:ServletContext的getRealPath(“/”)方法可以獲取當(dāng)前Web應(yīng)用的絕對路徑。
在終端中運(yùn)行以下命令啟動Spring Boot應(yīng)用:
mvn spring-boot:run
解釋:使用Maven的spring-boot:run命令可以啟動你的Spring Boot應(yīng)用。在應(yīng)用運(yùn)行后,上述方法可以用于獲取項(xiàng)目的絕對路徑。
File.separator
來處理文件分隔符,以確保兼容性。在構(gòu)建微服務(wù)架構(gòu)或處理多個(gè)后端服務(wù)間的交互時(shí),轉(zhuǎn)發(fā) POST 請求是一個(gè)常見的需求。本文將介紹如何使用 Spring Boot 實(shí)現(xiàn) POST 請求的轉(zhuǎn)發(fā),并提供詳細(xì)的操作步驟、命令示例及注意事項(xiàng)。
Spring Boot 是一個(gè)用于簡化 Spring 應(yīng)用程序開發(fā)的框架。通過 Spring Boot 提供的 RestTemplate 類以及 Controller 注解,我們能夠輕松地轉(zhuǎn)發(fā)請求。電信能力使得這些請求能夠在不同的微服務(wù)之間流動。
使用 Spring Initializr 創(chuàng)建一個(gè)新的 Spring Boot 項(xiàng)目,確保選擇了以下依賴項(xiàng):
mvn archetype:generate -DgroupId=com.example -DartifactId=postforward -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
在項(xiàng)目的 pom.xml 文件中添加 RestTemplate 依賴(如果未自動添加):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
在主應(yīng)用程序類中創(chuàng)建一個(gè) RestTemplate 的 bean,以便于后續(xù)進(jìn)行 HTTP 請求處理:
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
創(chuàng)建一個(gè)新的 Controller 類,用于處理請求轉(zhuǎn)發(fā)。以下是一個(gè)示例:
@RestController
@RequestMapping("/api")
public class ForwardController {
@Autowired
private RestTemplate restTemplate;
@PostMapping("/forward")
public ResponseEntity forwardRequest(@RequestBody String body) {
String url = "http://external-service/api/target";
ResponseEntity response = restTemplate.postForEntity(url, body, String.class);
return response;
}
}
使用以下命令啟動 Spring Boot 應(yīng)用程序:
mvn spring-boot:run
可以使用 Postman 或 curl 工具進(jìn)行測試,以下是 curl 的示例命令:
curl -X POST http://localhost:8080/api/forward -d "test data"