Introdução ao serviço de descanso
O RESTful Service é um modelo arquitetônico que se tornou mais popular nos últimos anos. Seu serviço da Web leve reproduz o Nativo Get, Put, Post e Excluir do Protocolo HTTP. Comparado com SOAP e XML-RPC complexos, os serviços da Web do modo REST são obviamente mais concisos e mais e mais serviços da Web estão começando a adotar o design e a implementação do estilo REST. Por exemplo, a Amazon.com fornece serviços da Web que estão próximos ao estilo de descanso para pesquisas de livros; Os serviços da Web fornecidos pelo Yahoo também são estilo de descanso. O descanso nem sempre é a escolha certa. Tornou -se popular como um método de projetar serviços da Web que se baseia menos no middleware proprietário, como um servidor de aplicativos, do que nos métodos baseados em SOAP e WSDL. Em certo sentido, enfatizando os primeiros padrões da Internet, como URI e HTTP, o REST é uma regressão para a abordagem da Web antes da era de grandes servidores de aplicativos.
Exemplo, como mostrado na figura a seguir:
A chave para usar o REST é como abstrair recursos. Quanto mais preciso a abstração, melhor a aplicação do descanso.
Princípios -chave do serviço REST:
1. Dê a todos os objetos um ID
2. Conecte objetos juntos
3. Use métodos padrão
4. Múltiplas representações de recursos
5. Comunicação sem estado
Este artigo apresenta como criar uma estrutura de serviço de descanso simples com base na inicialização da primavera e como implementar a autenticação do serviço REST através de anotações personalizadas
Construir uma estrutura
pom.xml
Primeiro, introduza dependências relacionadas, use o MongoDB para bancos de dados e use redis para cache
NOTA: Não há tomcat usado aqui, mas a ressaca
<Depencency> <PuerpId> org.springframework.boot </groupid> <TRATIFACTID> Spring-boot-starter </stutifactId> </dependency> <pendence> <puperid> org.springframework.boot </groupid> <TRATifactId> spring-boot-starter-testerwork. <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <GrupId> org.springframework.boot </roupiD> <TRATIFACTID> Spring-boot-Starter-undertow </stutifactId> </dependency> <!-Redis Support-> <PependEncy> <ProceRID> org.springframework.boot </grupo> <TifactId> spring-BOTTERSTER <!-suporte MongoDB-> <Depency> <PuerpId> org.springframework.boot </frugiD> <TRAFACTID> Spring-boot-starter-data-mongodb </artifactId> </pendence>
Introduzir Spring-Boot-Starter-Web Support Services Web
A introdução de Data-Redis-Redis e Spring-Boot-Starter-Data-MongoDB pode facilmente usar o MongoDB e Redis
Arquivo de configuração
Função de perfis
Para facilitar a distinção entre o ambiente de desenvolvimento e o ambiente on -line, a função dos perfis pode ser usada para adicioná -la no aplicativo.properties
spring.profiles.active=dev
Em seguida, adicione o Application-dev.Properties como o arquivo de configuração do DEV.
Configuração do Mondb
Basta configurar o endereço do banco de dados
spring.data.mongodb.uri = mongodb: // ip: porta/database? readPreference = primárioPreferred
Redis Configuration
spring.redis.database = 0 # Endereço do servidor Redis spring.redis.host = IP # Redis Server Connection Porta spring.redis.port = 6379 # Redis Server Connection Senha (padrão está vazio) spring.redis.password = # Número máximo de conexões na conexão no pool de conexão (usando valores negativos significa sem limite). spring.redis.pool.max-wait = -1 # conexão inativa máxima em conexão pool spring.redis.pool.max-idle = 8 # conexão inativa mínima no conexão pool spring.redis.pool.min-idle = 0 # Timeout de conexão (ms) spring.redis.timeout = 0
Acesso de dados
MONGDB
O acesso ao MONGDB é muito simples. Você pode definir diretamente a interface estende o Mongorepository. Além disso, pode suportar a sintaxe JPA, por exemplo:
@ComPonentPublic Interface UserRepository estende o MongoRepository <Usuário, Integer> {public User FindByuserName (String UserName);}Ao usá -lo, basta adicionar a anotação @Autowired.
@ComPonentPublic Class AuthService estende o BasEservice {@AUTOWIRED UserRepository UserRepository; }Acesso Redis
Use StringReDistemplate para acessar Redis diretamente
@ComPonenPublic Class BaseService {@Autowired Mongotemplate Mongotemplate; @AUTOWIRED StringRedRedSplate StringRedReDISTEMPLATE; }Dados de armazenamento:
.StringRedEnSplate.OpsforValue (). set (token_key, user.getId ()+"", token_max_age, timeunit.seconds);
Excluir dados:
stringReDistemplate.Delete (getFormattoken (AccessToken, plataforma));
Serviços da Web
Defina uma classe de controlador, adicione RestController e use o requestmapping para definir a rota URL
@RestControllerPublic Classe AuthController estende Basecontroller {@RequestMapping (Value = {"/"}, Produces = "Application/json; Charset = utf-8", Method = {requestmethod.get, requestmeth.post}) @Responsonsoperbods public string () {Return {Return ". }}Agora comece, você deve poder ver o Hello World! Isso é
Autenticação de serviço
Mecanismo simples de acesso
Forneça uma interface de login. Depois que a autenticação for bem -sucedida, um AcessToken é gerado. Ao acessar a interface no futuro, o AccessToken é trazido com ela. O servidor usa o AccessToken para determinar se é um usuário legal.
Por conveniência, você pode salvar o AccessToken em Redis e definir o período de validade.
String token = criptografia de unsctionutils.sha256hex (string.format ("%s%s", user.getUserName (), system.currenttimemillis ())); String token_key = getFormattoken (token, plataforma); this.stringredistemplate.opsforValue (). set (token_key, user.getid ()+"", token_max_age, timeunit.seconds);Autenticação de identidade interceptadora
Para facilitar a autenticação de identidade unificada, um interceptador pode ser criado com base no mecanismo interceptador da primavera para executar autenticação unificada.
classe pública AuthCheckIntercept implementa HandlerInterceptor {}Para fazer o interceptador entrar em vigor, mais um passo é necessário para adicionar configuração:
@ConfigurationPublic Class SessionConfiguration estende o webmvcConfigureRAdApter {@AUTOWIRED AuthCheckIntercept AuthCheckInterceptor; @Override public void addinterceptores (Registro de InterceptorRegistry) {super.addinterceptores (Registry); // Adicione o interceptador Registry.addintercept (AuthCheckInterceptor) .AddPathPatterns ("/**"); }}Anotações de autenticação personalizadas
Para refinar a autenticação de permissão, por exemplo, algumas interfaces só podem ser acessadas por pessoas com permissões específicas e podem ser facilmente resolvidas por meio de anotações personalizadas. Na anotação personalizada, basta adicionar funções.
/*** Anotação de verificação de permissão*/@Target (ElementType.Method) @retention (retentionPolicy.Runtime) @DocumentEdPublic @Interface AuthCheck {/*** Lista de função* @return*/string [] ROLS () default {};}Lógica de inspeção:
Desde que a interface seja adicionada com a anotação authcheck, deve ser um usuário conectado
Se as funções forem especificadas, além de fazer login, o usuário também deve ter a função correspondente.
String [] ignoreurls = new String [] {"/User/.*", "/cat/.*", "/pp/.*", "/error"}; public boolean Prehandle (httpServletRequest httpServletRequest, httpServletResponse httpServletResponse, manipulador de objetos) lança exceção {// 0 Verifique os parâmetros públicos se (! } // 1. Ignore a verificação url string url = httpServletRequest.getRequesturi (). ToString (); for (string ignoreurl: ignoreurls) {if (url.matches (ignoreurl)) {return true; }} // 2. Handlermethod de anotação de verificação de consulta Handlermethod = (handlermethod) manipulador; Método método = handlermethod.getMethod (); // consulta anotação authcheck authcheck = métod.getannotation (authcheck.class); if (authcheck == null) {// sem anotação, sem retorno true; } // 3. Se houver anotação, verifique o AccessToken primeiro se (! CheckParams ("AccessToken", httpServletRequest, httpServletResponse)) {return false; } // Verifique se o token expira o número inteiro userID = authService.getUserIdFromToken (httpServletRequest.getParameter ("AccessToken"), httpServletRequest.getParameter ("plataform"); if (userID == null) {Logger.debug ("AccessToken") Timeout "); output (Responsultult.builder.error (" AccessToken expirou "). build (), httpServletResponse); retorna false;} // 4. Usuário do Usuário = AuthService.getUser (UserID); Resultado do serviço Encapsulamento
Adicione um construtor para facilitar a geração de resultados finais
public classe ResponseResult {public Static Class Builder {Responsultion ResponsultSult; Mapa <string, object> datamap = maps.newhashmap (); public Builder () {this.ResponseResult = new ResponseResult (); } Builder público (Estado da String) {this.ResponseResult = new ResponseResult (estado); } public static construtor newBuilder () {return New Builder (); } public static Builder Success () {return New Builder ("Sucesso"); } erro de construtor estático público (mensagem de string) {construtor construtor = new Builder ("Error"); builder.ResponseResult.Sterror (mensagem); construtor de retorno; } public Builder Anexe (chave da string, dados do objeto) {this.datamap.put (chave, dados); devolver isso; } / *** Definir dados da lista* @param datas dados* @return* / public Builder setListData (list <?> Dados) {this.datamap.put ("resultado", dados); this.datamap.put ("total", datas.size ()); devolver isso; } public Builder setData (dados do objeto) {this.datamap.clear (); this.ResponseResult.SetData (dados); devolver isso; } boolean wrapdata = false; / ** * envolve dados em dados * @param wrapdata * @return */ public construtor wrap (boolean wrapdata) {this.wrapdata = wrapdata; devolver isso; } public string build () {jsonObject jsonObject = new jsonObject (); jsonObject.put ("estado", this.ResponseResult.getState ()); if (this.ResponseResult.getState (). Equals ("error")) {jsonObject.put ("erro", this.ResponseResult.getError ()); } if (this.ResponseResult.getData ()! = null) {jsonObject.put ("dados", json.tojson (this.ResponseResult.getData ())); } else if (datamap.size ()> 0) {if (wrapData) {jsonObject data = new jsonObject (); datamap.foreach ((chave, valor) -> {data.put (chave, value);}); jsonObject.put ("dados", dados); } else {datamap.foreach ((key, value) -> {jsonObject.put (chave, value);}); }} return jsonObject.tojSonstring (); }} Estado de sequência privada; dados de objetos privados; erro privado string; public String getError () {return Error; } public void setError (string error) {this.error = error; } public ResponseResult () {} public ResponseResult (String rc) {this.state = rc; } / ** * Retorne quando bem -sucedido * @param rc * @param resultado * / public Responsult (string rc, resultado do objeto) {this.state = rc; this.data = resultado; } public string getState () {retornar estado; } public void setState (State String) {this.state = state; } public Object getData () {return data; } public void setData (dados do objeto) {this.data = data; }} Seja mais elegante ao ligar
@RequestMapping (valor = {"/user/login", "/pc/user/login"}, produz = "Application/json; charset = utf-8", método = {requestmethod.get, requestMethod.Post}) @ResponseBody public Login (string username, string senha, plataforma integeger) {Platform) {Platform) @ResponseBody if (user! = null) {// efetuar login no token string = authservice.updateteken (usuário, plataforma); RESPONSULTADO DE RESPONSÃO RECORPO. } retornar responseResult.builder.error ("O usuário não existe ou a senha está errada"). build (); } Erro de string protegido (mensagem da string) {return ResponseResult.builder.error (message) .build (); } Protected String success () {return ResponsoSult.Builder .Success () .build (); } String protegida successDatalist (list <?> data) {return ResponseResult.builder .success () .Wrap (true) // Data Package.SetListData (data) .build (); }Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.