欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot請(qǐng)求參數(shù)加密、響應(yīng)參數(shù)解密的實(shí)現(xiàn)

 更新時(shí)間:2024年01月08日 11:37:13   作者:llp1110  
在項(xiàng)目開發(fā)工程中,有的項(xiàng)目可能對(duì)參數(shù)安全要求比較高,在整個(gè)http數(shù)據(jù)傳輸?shù)倪^程中都需要對(duì)請(qǐng)求參數(shù)、響應(yīng)參數(shù)進(jìn)行加密,本文主要介紹了SpringBoot請(qǐng)求參數(shù)加密、響應(yīng)參數(shù)解密的實(shí)現(xiàn),感興趣的可以了解一下

1.說明

在項(xiàng)目開發(fā)工程中,有的項(xiàng)目可能對(duì)參數(shù)安全要求比較高,在整個(gè)http數(shù)據(jù)傳輸?shù)倪^程中都需要對(duì)請(qǐng)求參數(shù)、響應(yīng)參數(shù)進(jìn)行加密,也就是說整個(gè)請(qǐng)求響應(yīng)的過程都是加密處理的,不在瀏覽器上暴露請(qǐng)求參數(shù)、響應(yīng)參數(shù)的真實(shí)數(shù)據(jù)。

補(bǔ)充:也可以用于單點(diǎn)登錄,在請(qǐng)求參數(shù)中添加時(shí)間戳,后臺(tái)解析請(qǐng)求參數(shù)對(duì)時(shí)間戳進(jìn)行校驗(yàn),比如當(dāng)前時(shí)間和請(qǐng)求參數(shù)中的時(shí)間戳相差多少秒、分鐘才能進(jìn)行放行,返回token。這樣做的好處在于請(qǐng)求端每次加密之后的密文都是變化的,也能夠避免攜帶相同的報(bào)文可以重復(fù)的登錄。

2.準(zhǔn)備工作

1.引入依賴, 創(chuàng)建SpringBoot工程

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.11.0</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>

		<!--swagger-->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>3.0.0</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>3.0.0</version>
		</dependency>
		<dependency>
			<groupId>io.swagger</groupId>
			<artifactId>swagger-annotations</artifactId>
			<version>1.5.22</version>
		</dependency>
		<dependency>
			<groupId>com.github.xiaoymin</groupId>
			<artifactId>swagger-bootstrap-ui</artifactId>
			<version>1.8.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
	</dependencies>

3.代碼實(shí)現(xiàn)

1.定義兩個(gè)注解

/**
 * @description: : 請(qǐng)求參數(shù)解密
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DecryptionAnnotation {
}

/**
 * @description: 響應(yīng)參數(shù)加密
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EncryptionAnnotation {
}

2.加密解密實(shí)現(xiàn)核心代碼

DecryptRequestBodyAdvice:請(qǐng)求參數(shù)解密,針對(duì)post請(qǐng)求

package com.llp.crypto.advice;

import cn.hutool.json.JSONUtil;
import com.llp.crypto.annotation.DecryptionAnnotation;
import com.llp.crypto.utils.AESUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;

/**
 * @description: 請(qǐng)求參數(shù)解密,針對(duì)post請(qǐng)求
 */

@Slf4j
@ControllerAdvice
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {

    /**
     * 方法上有DecryptionAnnotation注解的,進(jìn)入此攔截器
     *
     * @param methodParameter 方法參數(shù)對(duì)象
     * @param targetType      參數(shù)的類型
     * @param converterType   消息轉(zhuǎn)換器
     * @return true,進(jìn)入,false,跳過
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.hasMethodAnnotation(DecryptionAnnotation.class);
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        try {
            return new MyHttpInputMessage(inputMessage, parameter);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 轉(zhuǎn)換之后,執(zhí)行此方法,解密,賦值
     *
     * @param body          spring解析完的參數(shù)
     * @param inputMessage  輸入?yún)?shù)
     * @param parameter     參數(shù)對(duì)象
     * @param targetType    參數(shù)類型
     * @param converterType 消息轉(zhuǎn)換類型
     * @return 真實(shí)的參數(shù)
     */
    @SneakyThrows
    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        log.info("解密后的請(qǐng)求報(bào)文:{}", body);
        return body;
    }


    /**
     * 如果body為空,轉(zhuǎn)為空對(duì)象
     *
     * @param body          spring解析完的參數(shù)
     * @param inputMessage  輸入?yún)?shù)
     * @param parameter     參數(shù)對(duì)象
     * @param targetType    參數(shù)類型
     * @param converterType 消息轉(zhuǎn)換類型
     * @return 真實(shí)的參數(shù)
     */
    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    class MyHttpInputMessage implements HttpInputMessage {
        private HttpHeaders headers;

        private InputStream body;

        private MethodParameter parameter;

        public MyHttpInputMessage(HttpInputMessage inputMessage, MethodParameter parameter) throws Exception {
            this.headers = inputMessage.getHeaders();
            //只對(duì)post請(qǐng)求進(jìn)行加密
            if (parameter.hasMethodAnnotation(PostMapping.class)) {
                /*
                 *請(qǐng)求報(bào)文示例:
                 *  {
                 *  "requestData":"JF7kvl9Wd/vgdmAS8JijsQ=="
                 *  }
                 */
                String decrypt = AESUtil.decrypt(easpData(IOUtils.toString(inputMessage.getBody(), "UTF-8")));
                log.info("解密后的請(qǐng)求參數(shù):{}", decrypt);
                this.body = IOUtils.toInputStream(decrypt, "UTF-8");
            } else {
                this.body = inputMessage.getBody();
            }
        }

        @Override
        public InputStream getBody() throws IOException {
            return body;
        }

        @Override
        public HttpHeaders getHeaders() {
            return headers;
        }

    }

    public String easpData(String requestData) {
        if (requestData != null && !requestData.equals("")) {
            String start = "requestData";
            if (requestData.contains(start)) {
                return JSONUtil.parseObj(requestData).getStr(start);
            } else {
                throw new RuntimeException("參數(shù)【requestData】缺失異常!");
            }
        }
        return "";
    }
}

GetDeleteDecryptAspect:針對(duì)get、delete請(qǐng)求參數(shù)進(jìn)行解密

@Aspect
//值越小優(yōu)先級(jí)越高
@Order(-1)
@Component
@Slf4j
public class GetDeleteDecryptAspect {

    /**
     * 對(duì)get、delete方法進(jìn)行解密
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("@annotation(com.llp.crypto.annotation.DecryptionAnnotation) && " + "(@annotation(org.springframework.web.bind.annotation.GetMapping) || @annotation(org.springframework.web.bind.annotation.DeleteMapping))")
    public Object aroundMethod(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        // 獲取到請(qǐng)求的參數(shù)列表
        Object[] args = point.getArgs();
        // 判斷方法請(qǐng)求參數(shù)是否需要解密
        if (method.isAnnotationPresent(DecryptionAnnotation.class)) {
            try {
                this.decrypt(args, point);
                log.info("返回解密結(jié)果=" + args);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("對(duì)方法method :【" + method.getName() + "】入?yún)?shù)據(jù)進(jìn)行解密出現(xiàn)異常:" + e.getMessage());
            }
        }
        // 執(zhí)行將解密的結(jié)果交給控制器進(jìn)行處理,并返回處理結(jié)果
        return point.proceed(args);
    }

    /**
     * 前端對(duì)請(qǐng)求參數(shù)進(jìn)行加密,最終將這個(gè)加密的字符串已 localhost:48080?data=xxx這樣的方式進(jìn)行傳遞
     * 后端后去到 data的數(shù)據(jù)進(jìn)行解密最終得到解密后的數(shù)據(jù)
     * @param args
     * @param point
     * @throws Exception
     */
    // 解密方法
    @SuppressWarnings("unchecked")
    public void decrypt(Object[] args, ProceedingJoinPoint point) throws Exception {
        ServletRequestAttributes sc = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sc.getRequest();
        String data = request.getParameter("data");
        log.info("data: " + data);
        // 將密文解密為JSON字符串
        Class<?> aClass = args[0].getClass();
        log.info("數(shù)據(jù)類型:{}",aClass.getClass());
        if (StringUtils.isNotEmpty(data)) {
            // 將JSON字符串轉(zhuǎn)換為Map集合,并替換原本的參數(shù)
            args[0] = JSONUtil.toBean(AESUtil.decrypt(data), args[0].getClass());
        }
    }
}

EncryptResponseBodyAdvice:響應(yīng)參數(shù)解密,針對(duì)統(tǒng)一返回結(jié)果類的裝配

/**
 * @description: 響應(yīng)加密
 */

@Slf4j
@ControllerAdvice
public class EncryptResponseBodyAdvice implements ResponseBodyAdvice {


    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return methodParameter.hasMethodAnnotation(EncryptionAnnotation.class);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        log.info("對(duì)方法method :【" + methodParameter.getMethod().getName() + "】返回?cái)?shù)據(jù)進(jìn)行加密");
        // 只針對(duì)回參類型為CommonResult的對(duì)象,進(jìn)行加密
        if (body instanceof CommonResult) {
            CommonResult commonResult = (CommonResult) body;
            Object data = commonResult.getData();
            if (Objects.nonNull(data)) {
                // 將響應(yīng)結(jié)果轉(zhuǎn)換為json格式
                String result = JSONUtil.toJsonStr(data);
                log.info("返回結(jié)果:{}", result);
                try {
                    String encrypt = AESUtil.encrypt(result);
                    commonResult.setData(encrypt);
                    log.info("返回結(jié)果加密=" + commonResult);
                } catch (Exception e) {
                    log.error("對(duì)方法method :【" + methodParameter.getMethod().getName() + "】返回?cái)?shù)據(jù)進(jìn)行解密出現(xiàn)異常:" + e.getMessage());
                }
                return commonResult;
            }
        }
        return body;
    }

}

3.統(tǒng)一返回結(jié)果

@Data
public class CommonResult<T> {
    private String code;
    private String msg;
    private T data;

    public CommonResult() {
    }

    public CommonResult(T data) {
        this.data = data;
    }

    /**
     * 表示成功的Result,不攜帶返回?cái)?shù)據(jù)
     *
     * @return
     */
    public static CommonResult success() {
        CommonResult result = new CommonResult();
        result.setCode("200");
        result.setMsg("success");
        return result;
    }

    /**
     * 便是成功的Result,攜帶返回?cái)?shù)據(jù)
     * 如果需要在static方法使用泛型,需要在static后指定泛型表示 static<T>
     *
     * @param data
     * @return
     */
    public static <T> CommonResult<T> success(T data) {
        CommonResult<T> result = new CommonResult<>(data);
        result.setCode("200");
        result.setMsg("success");
        return result;
    }

    /**
     * 失敗不攜帶數(shù)據(jù)
     * 將錯(cuò)誤的code、msg作為形參,靈活傳入
     *
     * @param code
     * @param msg
     * @return
     */
    public static CommonResult error(String code, String msg) {
        CommonResult result = new CommonResult();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }

    /**
     * 失敗攜帶數(shù)據(jù)
     * 將錯(cuò)誤的code、msg、data作為形參,靈活傳入
     * @param code
     * @param msg
     * @param data
     * @param <T>
     * @return
     */
    public static <T> CommonResult<T> error(String code, String msg, T data) {
        CommonResult<T> result = new CommonResult<>(data);
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }

}

4.加密工具類

public class AESUtil {
    // 加解密方式
    private static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";

    // 與前端統(tǒng)一好KEY
    private static final String KEY = "abcdsxyzhkj12345";

    // 獲取 cipher
    private static Cipher getCipher(byte[] key, int model) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
        cipher.init(model, secretKeySpec);
        return cipher;
    }

    // AES加密
    public static String encrypt(String data) throws Exception {
        Cipher cipher = getCipher(KEY.getBytes(), Cipher.ENCRYPT_MODE);
        return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes("UTF-8")));
    }

    // AES解密
    public static String decrypt(String data) throws Exception {
        Cipher cipher = getCipher(KEY.getBytes(), Cipher.DECRYPT_MODE);
        return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes("UTF-8"))),"UTF-8");
    }

    public static byte[] decryptUrl(String url) throws Exception {
        Cipher cipher = getCipher(KEY.getBytes(), Cipher.DECRYPT_MODE);
        return cipher.doFinal(Base64.getDecoder().decode(url.replaceAll(" +", "+")));
    }

    // AES解密MySQL AES_ENCRYPT函數(shù)加密密文
    public static String aesDecryptMySQL(String key, String content){
        try {
            SecretKey secretKey = generateMySQLAESKey(key,"ASCII");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] cleartext = Hex.decodeHex(content.toCharArray());
            byte[] ciphertextBytes = cipher.doFinal(cleartext);
            return new String(ciphertextBytes, StandardCharsets.UTF_8);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    //加密
    public static String aesEncryptMySQL(String key2, String content) {
        try {
            SecretKey key = generateMySQLAESKey(key2,"ASCII");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] cleartext = content.getBytes("UTF-8");
            byte[] ciphertextBytes = cipher.doFinal(cleartext);
            return new String(Hex.encodeHex(ciphertextBytes));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static SecretKeySpec generateMySQLAESKey(final String key, final String encoding) {
        try {
            final byte[] finalKey = new byte[16];
            int i = 0;
            for(byte b : key.getBytes(encoding)) {
                finalKey[i++%16] ^= b;
            }
            return new SecretKeySpec(finalKey, "AES");
        } catch(UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
    @Test
    public void decodeTest() {
        try {
            String a = "{\"username\":\"admin\",\"deptId\":\"1250500000\",\"userId\":\"1\",\"phone\":\"15195928695\"}";
            String encrypt = AESUtil.encrypt(a);
            System.out.println("加密后的字符串: "+encrypt);
            System.out.println("解密后的字符串:" +AESUtil.decrypt(encrypt));

            String str = "5tAayXF5ZcPC9yoNvBIT0fw2Li2uoxUhGyMq4JKUvCttOFnU7iKovyB9pm/ZV+2qU8h2htdk5s6ht9kCpTGG9WZAGTdMUgIJkD/Tf6IQ3gw=";

            String decrypt = AESUtil.decrypt(IOUtils.toString(str.getBytes(), "UTF-8"));
            System.out.println(decrypt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.請(qǐng)求流支持多次獲取

/**
 * 請(qǐng)求流支持多次獲取
 */
public class InputStreamHttpServletRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 用于緩存輸入流
     */
    private ByteArrayOutputStream cachedBytes;

    public InputStreamHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (cachedBytes == null) {
            // 首次獲取流時(shí),將流放入 緩存輸入流 中
            cacheInputStream();
        }

        // 從 緩存輸入流 中獲取流并返回
        return new CachedServletInputStream(cachedBytes.toByteArray());
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    /**
     * 首次獲取流時(shí),將流放入 緩存輸入流 中
     */
    private void cacheInputStream() throws IOException {
        // 緩存輸入流以便多次讀取。為了方便, 我使用 org.apache.commons IOUtils
        cachedBytes = new ByteArrayOutputStream();
        IOUtils.copy(super.getInputStream(), cachedBytes);
    }

    /**
     * 讀取緩存的請(qǐng)求正文的輸入流
     * <p>
     * 用于根據(jù) 緩存輸入流 創(chuàng)建一個(gè)可返回的
     */
    public static class CachedServletInputStream extends ServletInputStream {

        private final ByteArrayInputStream input;

        public CachedServletInputStream(byte[] buf) {
            // 從緩存的請(qǐng)求正文創(chuàng)建一個(gè)新的輸入流
            input = new ByteArrayInputStream(buf);
        }

        @Override
        public boolean isFinished() {
            return false;
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setReadListener(ReadListener listener) {

        }

        @Override
        public int read() throws IOException {
            return input.read();
        }
    }

}

4.測試

1.測試類

@Slf4j
@RestController
@Api(tags = "測試加密解密")
public class TestController {

    /**
     * 請(qǐng)求示例:
     * {
     * "requestData":"5tAayXF5ZcPC9yoNvBIT0fw2Li2uoxUhGyMq4JKUvCttOFnU7iKovyB9pm/ZV+2qU8h2htdk5s6ht9kCpTGG9WZAGTdMUgIJkD/Tf6IQ3gw="
     * }
     *
     * @return
     */
    @PostMapping(value = "/postEncrypt")
    @ApiOperation("測試post加密")
    @EncryptionAnnotation
    @DecryptionAnnotation
    public CommonResult<String> postEncrypt(@RequestBody UserReqVO userReqVO) {
        System.out.println("userReqVO: ============>" + userReqVO);
        return CommonResult.success("成功");
    }


    @GetMapping(value = "/getEncrypt")
    @ApiOperation("測試get加密")
    @DecryptionAnnotation // requestBody 自動(dòng)解密
    public CommonResult<UserReqVO> getEncrypt(String data) {
        log.info("解密后的數(shù)據(jù):{}",data);
        UserReqVO userReqVO = JSONUtil.toBean(data, UserReqVO.class);
        //UserReqVO(username=admin, deptId=1250500000, userId=1, phone=15195928695)
        log.info("用戶信息:{}",userReqVO);
        return CommonResult.success(userReqVO);
    }
}
@ApiModel(description = "用戶請(qǐng)求vo")
@Data
public class UserReqVO {

    @ApiModelProperty(value = "用戶名", required = true)
    private String username;

    @ApiModelProperty(value = "部門id",required = true)
    private Long deptId;

    @ApiModelProperty(value = "用戶id",required = true)
    private Long userId;

    @ApiModelProperty(value = "電話號(hào)碼",required = true)
    private String phone;

}

測試結(jié)果

image-20240108110033110

image-20240108110124687

到此這篇關(guān)于SpringBoot請(qǐng)求參數(shù)加密、響應(yīng)參數(shù)解密的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot請(qǐng)求參數(shù)加密、響應(yīng)參數(shù)解密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • SpringBoot添加Email發(fā)送功能及常見異常詳解

    SpringBoot添加Email發(fā)送功能及常見異常詳解

    本篇文章主要介紹了SpringBoot添加Email發(fā)送功能及常見異常詳解,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-04-04
  • SpringMVC的自定義攔截器詳解

    SpringMVC的自定義攔截器詳解

    這篇文章主要介紹了SpringMVC的自定義攔截器詳解,攔截器只會(huì)攔截訪問的控制器方法, 如果訪問的是jsp/html/css/image/js是不會(huì)進(jìn)行攔截的,需要的朋友可以參考下
    2023-07-07
  • Spring Data JPA實(shí)現(xiàn)分頁P(yáng)ageable的實(shí)例代碼

    Spring Data JPA實(shí)現(xiàn)分頁P(yáng)ageable的實(shí)例代碼

    本篇文章主要介紹了Spring Data JPA實(shí)現(xiàn)分頁P(yáng)ageable的實(shí)例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-07-07
  • Java中使用HashMap時(shí)指定初始化容量性能解析

    Java中使用HashMap時(shí)指定初始化容量性能解析

    這篇文章主要為大家介紹了Java中使用HashMap時(shí)指定初始化容量性能解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • JavaWeb.servlet的基本使用方法詳解

    JavaWeb.servlet的基本使用方法詳解

    Servlet指在服務(wù)器端執(zhí)行的一段Java代碼,可以接收用戶的請(qǐng)求和返回給用戶響應(yīng)結(jié)果,下面這篇文章主要給大家介紹了關(guān)于JavaWeb.servlet基本使用的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • MyBatis Mapper XML中比較操作符轉(zhuǎn)義問題解決

    MyBatis Mapper XML中比較操作符轉(zhuǎn)義問題解決

    在使用MyBatis編寫Mapper XML時(shí),有時(shí)會(huì)遇到比較操作符需要進(jìn)行轉(zhuǎn)義的情況,本文主要介紹了MyBatis Mapper XML中比較操作符轉(zhuǎn)義問題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Shiro+Cas微服務(wù)化及前后端完全分離

    Shiro+Cas微服務(wù)化及前后端完全分離

    這篇文章主要為大家詳細(xì)介紹了Shiro+Cas微服務(wù)化及前后端完全分離,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Spring如何消除代碼中的if-else/switch-case

    Spring如何消除代碼中的if-else/switch-case

    這篇文章主要給大家介紹了關(guān)于Spring如何消除代碼中if-else/switch-case的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • SpringMVC中的SimpleUrlHandlerMapping用法詳解

    SpringMVC中的SimpleUrlHandlerMapping用法詳解

    這篇文章主要介紹了SpringMVC中的SimpleUrlHandlerMapping用法詳解,SimpleUrlHandlerMapping是Spring MVC中適用性最強(qiáng)的Handler Mapping類,允許明確指定URL模式和Handler的映射關(guān)系,有兩種方式聲明SimpleUrlHandlerMapping,需要的朋友可以參考下
    2023-10-10
  • 基于Java語言MD5加密Base64轉(zhuǎn)換方法

    基于Java語言MD5加密Base64轉(zhuǎn)換方法

    這篇文章主要為大家詳細(xì)介紹了基于Java語言的MD5加密Base64轉(zhuǎn)換方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09

最新評(píng)論