以一個常見的場景舉例。前端
使用Spring MVC構建這個簡單的接口。java
使用@Controller
註解聲明控制器。@RequestMapping
註解映射地址。@Autowired
註解自動注入UserService
對象,執行業務邏輯。@RequestParam
註解綁定參數。web
@Controller @RequestMapping(value = "/user") public class UserController { @Autowired @Qualifier("userService") private UserService userService; @RequestMapping(value="/message",method=RequestMethod.GET) public @ResponseBody UserModel message(@RequestParam("id") String id,@RequestParam("token") String token){ return userService.message(id,token); } }
@Service
註解聲明服務類。從UserDao
中查到用戶信息並返回。spring
@Service("userService") public class UserService { @Autowired @Qualifier("userDao") private UserDao userDao; public UserModel message(String id,String token){ /*驗證token......*/ return userDao.getUserById(id); } }
@Repository
註解聲明倉庫類。此處模擬一個數據返回。(Spring MVC 提供的JDBC工具類仍是不錯的)sql
@Repository("userDao") public class UserDao { public UserModel getUserById(String id){ UserModel user=new UserModel(); user.setUserName("MagicWolf"); user.setEmail("dai.dongliang@foxmail.com"); return user; } }
一個簡單的POJO對象數據庫
public class UserModel{ private String userName; private String email; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
配置Spring MVC。此處簡化了些配置,沒有使用模塊化配置。編程
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <!--字符過濾器--> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring 前端控制器 --> <servlet> <servlet-name>WebTest</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>WebTest</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Spring配置json
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 註冊註解驅動特性 --> <mvc:annotation-driven /> <!-- 開啓註解裝配 --> <context:annotation-config /> <!-- 掃描註解 --> <context:component-scan base-package="com.magicwolf" /> <!-- 內容視圖解析器 --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> </map> </property> <property name="defaultContentType" value="application/json" /> </bean> <!-- 視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
在瀏覽器輸入http://localhost:8080/WebTest/user/message?id=123&token=123
能夠看到返回了用戶信息,基本功能完成。瀏覽器
{ userName: "MagicWolf", email: "dai.dongliang@foxmail.com" }
在doFilter
方法中,使用本身的包裝類替換HttpServletRequest
spring-mvc
public class HttpRequestWapperFilter implements Filter{ @Override public void destroy() {} @Override public void init(FilterConfig arg0) throws ServletException {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request=new HttpRequestWapper((HttpServletRequest)request); chain.doFilter(request, response); } }
getParameterValues
方法,因此咱們重寫這個方法。request
中獲得ID參數,而後寫JDBC操做查到用戶密鑰進行解密。可是我想在Spring中使用以前寫好的數據庫操做類UserDao
,因此把查密鑰這一步放到了攔截器中。class HttpRequestWapper extends HttpServletRequestWrapper{ private String key; public HttpRequestWapper(HttpServletRequest request) { super(request); } @Override public String[] getParameterValues(String name) { String[] strs=super.getParameterValues(name); if(name.equals("id")){ for(int i=0;i<strs.length;i++) strs[i]=AESCodec.decrypt(strs[i], key);//AES解密 } return strs; } public void setKey(String key) { this.key = key; } }
在攔截器裏能夠方便的使用SPring注入UserDao
。在preHandle
方法中設置key的值
public class UserMessageInterceptor extends HandlerInterceptorAdapter{ @Autowired @Qualifier("userDao") private UserDao userDao; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String key=userDao.getAESKeyByUserId(request.getParameter("id")); ((HttpRequestWapper)request).setKey(key); return true; } }
在配置文件中加入包裝類的過濾器
<filter> <filter-name>HttpWapperFilter</filter-name> <filter-class>com.magicwolf.HttpRequestWapperFilter</filter-class> </filter> <filter-mapping> <filter-name>HttpWapperFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
加入攔截器配置
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/user/**" /> <bean class="com.magicwolf.UserMessageInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
http://localhost:8080/WebTest/user/message?id=123&token=0lCQPVTc8WCNP2FxocbC7Q==
返回信息的加密原理上跟解密同樣,並且本文重點也不在這,因此這裏就簡單說一下思路。
HttpServletResponse
對象,添加一個toByteArray()
方法返回輸出緩衝區的內容doFilter
執行請求,以後使用toByteArray()
方法獲得緩衝區字節,在進行加密。使用了Spring的AOP後,解決這個問題就變的輕鬆加愉快了。關於AOP這裏就不作詳細描述了。
聲明切面。
@Component
註解用於聲明組件。@Aspect
註解用於聲明切面。@Pointcut
註解聲明切點,括號裏是切點表達式,這裏定位到UserService類的message方法@Around
聲明是環繞通知方法@Component("AESAspect") @Aspect public class AESAspect { @Autowired @Qualifier("userDao") private UserDao userDao; @Pointcut("execution(* com.magicwolf.UserService.message(..))") public void messagePointcut() {} @Around("messagePointcut()") public UserModel messagePointcut(ProceedingJoinPoint point) throws Throwable { Object[] args = point.getArgs(); String id = (String) args[0]; String key = userDao.getAESKeyByUserId(id); AESCodec.decrypt((String) args[1], key); // 執行 UserModel result = (UserModel) point.proceed(args); // 返回值加密 result.encrypt(key); // 返回結果 return result; } }
在UserModel中添加一個加密成員變量的方法
public void encrypt(String key){ this.userName=AESCodec.encrypt(userName, key); this.email=AESCodec.encrypt(email, key); }
更改代理方式,使用cglib代理來替換JDK代理。
<aop:aspectj-autoproxy proxy-target-class="true" />
在瀏覽器中輸入http://localhost:8080/WebTest/user/message?id=123&token=0lCQPVTc8WCNP2FxocbC7Q==
返回值
此時返回值已經加密
{ userName: "U/6CJMzF1IRV/HpEjDJPEQ==", email: "kQAV7t4611RYADmDC69odyQmES+MXv+p4OmYMC8fSoU=" }
request
對象進行包裝的,但是我在攔截器裏進行包裝卻沒有效果,多是此處的request
對象只是一個拷貝吧。歡迎工做一到五年的Java工程師朋友們加入Java架構開發:855801563
羣內提供免費的Java架構學習資料(裏面有高可用、高併發、高性能及分佈式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用本身每一分每一秒的時間來學習提高本身,不要再用"沒有時間「來掩飾本身思想上的懶惰!趁年輕,使勁拼,給將來的本身一個交代