java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Boot 2.x构建Web服务

使用Spring Boot 2.x构建Web服务的详细代码

作者:卢鑫旺

这篇文章主要介绍了使用Spring Boot 2.x构建Web服务的详细代码,主要基于JWT的身份认证,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

架构:

库:

运行应用的步骤

关于项目配置

Web服务声明

应用程序的每个Web服务都将在controller层中声明。

示例

@RequestMapping("/api/v1/user")
@RestController
@Validated
public class UserController {

  private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
   private GeneralServices generalServices;

   @Autowired
   private UserService userService;

   /**
     * Web service to create new user
     *
     * @param httpServletRequest
    * @param user
     * @return
    */
   @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
   public ResponseEntity<Object> createUser(HttpServletRequest httpServletRequest,
                                             @Valid @RequestBody UserCreateModel user) {
       logger.debug("<--- Service to save new user request : received --->");
       ApiSuccessResponse apiResponse = userService.createUser(user, generalServices.getApiRequestedUserId(httpServletRequest));
        logger.debug("<--- Service to save new user response : given --->");
       return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);

    }

}

通过controller层,API请求将被带到服务层。所有业务逻辑都将在这里处理,然后它将使用JPA与数据库通信。

通用错误处理

每当异常发生时,它将从相应的类抛出,并在CommonExceptionHandlingController中处理。我们必须分别处理每种异常类型。这个功能是在ControllerAdvice注解的帮助下执行的。

示例

@ControllerAdvice
public class CommonExceptionHandlingController extends ResponseEntityExceptionHandler {

    private static final Logger logger = 
        LoggerFactory.getLogger(CommonExceptionHandlingController.class);
   @Override
    protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException httpRequestMethodNotSupportedException,
                                                                         HttpHeaders headers, HttpStatus status, WebRequest request) {
       return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ApiErrorResponse(Constants.WRONG_HTTP_METHOD,
                Constants.WRONG_HTTP_METHOD_ERROR_MESSAGE, Calendar.getInstance().getTimeInMillis()));
   }
   protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException methodArgumentNotValidException,
                                                                 HttpHeaders headers, HttpStatus status, WebRequest request) {
       return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ApiErrorResponse(Constants.MANDATORY_FIELDS_ARE_NOT_PRESENT_CODE,
               Constants.MANDATORY_FIELDS_ARE_NOT_PRESENT_ERROR_MESSAGE, Calendar.getInstance().getTimeInMillis()));

Spring Data(JPA)配置

Entity类

@Entity
@Table(name = "tbl_users")
public class Users implements Serializable {
   private static final long serialVersionUID = 1L;

  @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "id", columnDefinition = "bigint")
    private Long id;

  @OneToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "user_account_id", columnDefinition = "bigint", nullable = false)
   private UserAccounts userAccount;

Repository接口

public interface UserRepository extends JpaRepository<Users, Long> {

   /**
     * To find user object using username
     *
    * @param username
    * @return
     */
  Users findByUserAccountUsername(String username);

在application.properties中的JPA数据库配置

spring.jpa.show-sql=false
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.ddl-auto = update

spring.jpa.properties.hibernate.show_sql=false
spring.jpa.properties.hibernate.format_sql=false
spring.jpa.properties.hibernate.use_sql=true
spring.jpa.open-in-view=false
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider

数据库配置

application-dev.properties

此处写开发环境的配置信息

application-pro.properties

此处写生产环境的配置信息

spring.profiles.active=dev

application.properties

#DB config
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver

application-dev.properties

#DB config
spring.datasource.url=jdbc:sqlserver://localhost:1433;databaseName=sample_webservice_db_dev
spring.datasource.username=dbuser
spring.datasource.password=ENC(tZTfehMYyz4EO0F0uY8fZItE7K35RtkA)
#spring.datasource.username=dbuser
#spring.datasource.password=dbuserpassword

application-pro.properties

#DB config
spring.datasource.url=jdbc:sqlserver://192.168.1.119:1433;databaseName=sample_webservice_db
spring.datasource.username=proUser
spring.datasource.password=ENC(proUserPswd)

数据库密码加密

spring.datasource.password=ENC(tZTfehMYyz4EO0F0uY8fZItE7K35RtkA)
jasypt.encryptor.algorithm=PBEWithMD5AndDES
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.NoIvGenerator

SampleWebservice.java

@SpringBootApplication
@EnableEncryptableProperties
public class SampleWebservice extends SpringBootServletInitializer {
--------
--------

JWT身份验证配置

创建令牌的过程

UnAuthorisedAccessServiceImpl.java

@Override
   public ApiSuccessResponse userLoginService(String username, String password) {
      Tokens tokens = null;
       Users user = userService.findByUsername(username);
       if (user != null) {
           if (passwordEncryptingService.matches(password,
                   user.getUserAccount().getPassword())) {
               if (user.getUserAccount().getStatus() == Constants.ACTIVE_STATUS) {
                   String roleName = user.getUserAccount().getUserRole().getRoleName();
                   // Creating new tokens
                  try {
                       tokens = createTokens(user.getUserAccount().getId().toString(), roleName);
                  } catch (Exception exception) {
                        logger.error("Token creation failed : ", exception);
                      throw new UnknownException();
                   }

                   // Validating tokens
                  if (validationService.validateTokens(tokens)) {
                       tokens.setUserId(user.getUserAccount().getId());
                     return new ApiSuccessResponse(tokens);
                  } else {
                       throw new UnknownException();
                  }
              } else {
                 return new ApiSuccessResponse(new ApiResponseWithCode(Constants.USER_ACCOUNT_IS_INACTIVE_ERROR_CODE,
                           Constants.USER_ACCOUNT_IS_INACTIVE_ERROR_MESSAGE));
             }
          } else {
              return new ApiSuccessResponse(new ApiResponseWithCode(Constants.USERNAME_OR_PASSWORD_IS_INCORRECT_ERROR_CODE,
                       Constants.USERNAME_OR_PASSWORD_IS_INCORRECT_ERROR_MESSAGE));
           }
      } else {
           return new ApiSuccessResponse(new ApiResponseWithCode(Constants.USERNAME_OR_PASSWORD_IS_INCORRECT_ERROR_CODE,
                  Constants.USERNAME_OR_PASSWORD_IS_INCORRECT_ERROR_MESSAGE));
       }
    }
    @Override
   public ApiSuccessResponse createNewAccessTokenUsingRefreshToken(String refreshToken) {
        UserAccounts userAccount = null;
       AppConfigSettings configSettings = appConfigSettingsService.findByConfigKeyAndStatus(Constants.JWT_SECRET_KEY,
               Constants.ACTIVE_STATUS);
      // Validate Refresh token
       userAccount = jwtTokenHandler.validate(configSettings.getConfigValue(), refreshToken);
       if (userAccount != null) {
            // Creating new tokens if provided refresh token is valid
           try {
               tokens = createTokens(userAccount.getId().toString(), userAccount.getRole());
           } catch (Exception exception) {
              logger.error("Token creation failed : ", exception);
               throw new UnknownException();
          if (validationService.validateTokens(tokens)) {
               tokens.setUserId(userAccount.getId());
              return new ApiSuccessResponse(tokens);
           } else {
          }
       } else {
           return new ApiSuccessResponse(new ApiResponseWithCode(Constants.REFRESH_TOKEN_EXPIRED_ERROR_CODE,
                  Constants.REFRESH_TOKEN_EXPIRED_ERROR_MESSAGE));
      }
   }

过滤和验证令牌的过程

WebConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebConfig extends WebSecurityConfigurerAdapter {

   @Autowired
   private JwtAuthenticationProvider authenticationProvider;
    @Autowired
   private JwtAuthenticationEntryPoint entryPoint;
    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(Collections.singletonList(authenticationProvider));
   }
  public JwtAuthenticationTokenFilter authenticationTokenFilter() {
      JwtAuthenticationTokenFilter filter = new JwtAuthenticationTokenFilter();
        filter.setAuthenticationManager(authenticationManager());
      filter.setAuthenticationSuccessHandler(new JwtSuccessHandler());
        return filter;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http.csrf().disable()
               .exceptionHandling().authenticationEntryPoint(entryPoint).and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
             .addFilterBefore(new WebSecurityCorsFilter(), ChannelProcessingFilter.class)
               .addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class)
                .headers().cacheControl();
    }
}

JwtAuthenticationTokenFilter.java

public class JwtAuthenticationTokenFilter extends AbstractAuthenticationProcessingFilter {

   private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
   private GeneralServices generalServices;
  public JwtAuthenticationTokenFilter() {
       super("/api/**");
   }
    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,
                                                HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
                                                 -------
                                                 --------

应用用户密码加密

PasswordEncryptingService.java

public class PasswordEncryptingService {

    public String encode(CharSequence rawPassword) {
        return BCrypt.hashpw(rawPassword.toString(), BCrypt.gensalt(6));
    }

    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
    }

使用Slf4j配置日志

示例

UserServiceImpl.java

@Service("UserService")
@Scope("prototype")
public class UserServiceImpl implements UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

logger.error("Error");

logger.info("Info");

logger.warn("Warn");

基于Swagger的API文档

Pom.xml

  <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>${springfox.swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${springfox.swagger.version}</version>
        </dependency>

SwaggerAPIDocConfig.java

@Configuration
@EnableSwagger2
public class SwaggerAPIDocConfig {

    public static final Contact DEFAULT_CONTACT = new Contact("Demo", "http://www.demo.ae/",
            "info@demo.ae");
    public static final ApiInfo DEFAUL_API_INFO = new ApiInfo("Sample Application",
            "Sample Application description.",
            "1.0.0",
            "http://www.sampleapplication.ae/",
            DEFAULT_CONTACT, "Open licence",
            "http://www.sampleapplication.ae/#license",
            new ArrayList<VendorExtension>());
    private static final Set<String> DEFAULT_PRODICERS_AND_CONSUMERS =
            new HashSet<>(Arrays.asList("application/json", "application/xml"));
    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(DEFAUL_API_INFO)
                .produces(DEFAULT_PRODICERS_AND_CONSUMERS)
                .consumes(DEFAULT_PRODICERS_AND_CONSUMERS)
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                .paths(PathSelectors.any())
                .build();
    }
}

Postman脚本

到此这篇关于使用Spring Boot 2.x构建Web服务的详细代码的文章就介绍到这了,更多相关Spring Boot 2.x构建Web服务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文