當前位置:
首頁 > 知識 > 如何修改request參數值並應用到springMvc中

如何修改request參數值並應用到springMvc中

就簡潔地說一下吧。大多數crud都是在controller的handler中進行的,一般的思路就是從request里取到當前user,或者userid,然後再通過這個user/userid去資料庫里進行下一步操作。仔細想想的話,是不是做了一些重複的操作?能不能有一種方法可以從handler的參數中直接取到當前user/userid?這樣不僅可以直接根據其進行下一步操作,而且代碼也減少了冗餘。比如這樣:

@RequestMapping("test")

@ResponseBody

public String test(HttpServletRequest request, String userid) {

userService.doService(userid);

.....

我們更希望像這樣直接從參數中拿到當前會話下的user/userid,然後就直接根據其進行其他操作。那麼有沒有辦法實現呢?答案是 有的,請繼續看下面的思路

有關request的參數其實都保存在了一個parameterMap中,一般通過request.getParameterMap()得到,只要我們能在springMvc之前得到user/userid,然後將其添加到request的parameterMap中,那麼在上面的test方法中String userid自然可以直接取到對應的值。但是由於tomcat的開發人員不想我們直接修改request的參數值(做了手腳),所以類似request.getParameterMap().put(xxx,xxx)是行不通的,所以需要另闢蹊徑。https://blog.csdn.net/xieyuooo/article/details/8447301這篇文章講的挺清楚的,這裡就使用其中的一種方法。

繼承HttpServletRequestWrapper包裝一個自己的request

大致代碼都是差不多的,如下

public class HttpRequest extends HttpServletRequestWrapper implements MyHttpRequest {

private Map<String, String[]> params = new HashMap<String, String[]>();

@SuppressWarnings("unchecked")

public HttpRequest(HttpServletRequest request) {

super(request);

params.putAll(request.getParameterMap());

}

@Override

public String getParameter(String name) {

String[] values = params.get(name);

return values == null || values.length == 0 ? null : values[0];

}

@Override

public String[] getParameterValues(String key) {

return params.get(key);

}

@Override

public void setParameter(String key, String value) {

if (value == null)

return;

params.put(key, new String[] { value });

}

@Override

public void setParameter(String key, String[] value) {

if (value == null)

return;

params.put(key, value);

}

@Override

public void setParameter(String key, Object value) {

if (value == null)

return;

params.put(key, new String[] { String.valueOf(value) });

}

@Override

public Map<String, String[]> getParameterMap() {

return params;

}

@Override

public Enumeration<String> getParameterNames() {

Enumeration<String> enumeration = new MyEnumeration<String>(params.keySet().iterator());

return enumeration;

}

}

對應的MyEnumeration重寫下Enumeration的方法(My前綴可能有些人看的不舒服,認為有獨佔別人東西的感覺,但是並沒有這個意思,當初加一個My前綴也沒想那麼多,僅僅是為了方便區分而已⊙﹏⊙)

public class MyEnumeration<E> implements Enumeration<E> {

private Iterator<E> iterator;

public MyEnumeration(Iterator<E> iterator) {

this.iterator = iterator;

}

@Override

public boolean hasMoreElements() {

return iterator.hasNext();

}

@Override

public E nextElement() {

return iterator.next();

}

}

這樣request就可以設置參數了,然後在filter中獲取到當前user/userid,並將其作為參數設置到自定義的request中

//setCondition是自定義filter中的一個流程,可以不用太在意

@Override

protected boolean setCondition(MyHttpRequest req, HttpServletResponse response)

throws IOException, ServletException {

Object id = null;

//獲取到當前用戶的id,本質還是從session中取

if ((id = securityService.checkIdentity_s(req)) == null)

return true;

//paramKey可以自己定義,這裡我定義的就是"userid"

req.setParameter(paramKey, id.toString());

System.err.println("now the request is "+req);

return false;

}

最後只需要在chain.doFilter中傳入自定義的request即可

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {

//自定義request

MyHttpRequest req = null;

if (request instanceof HttpServletRequest) {

req = new HttpRequest((HttpServletRequest) request);

for (int i = 0; i < filters.size(); i++) {

//HttpFilter是自定義的一個抽象類

HttpFilter filter = filters.get(i);

//調用所有的filter,前面的setCondition函數就是裡面的一個小流程

filter.doFilter(req, response, chain);

}

//一定要注意傳進去的是自定義的request

chain.doFilter(req, response);

} else {

for (int i = 0; i < otherFilters.size(); i++) {

OtherFilter filter = otherFilters.get(i);

filter.doOtherRequest(request, response, chain);

}

chain.doFilter(request, response);

}

}

登錄後(用戶登錄後其資料庫里的userid會被保存到session中)再進行測試,直接在瀏覽器輸入路徑

後台列印,兩種方式都可以取出

這樣,就實現了直接從參數中拿到當前的user/userid,然後就可以直接根據其進行其他操作了,代碼也不再那麼冗餘

說一些額外的(上面沒問題了下面就可以忽略)

1> 為什麼要使用filter,使用攔截器不更方便嗎?

其實最開始我也是使用的Interceptor,但是後面發現不行,看了下dispatcher的源碼,找到了原因所在

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

HttpServletRequest processedRequest = request;

......

try {

ModelAndView mv = null;

......

// interceptor前置攔截

if (!mappedHandler.applyPreHandle(processedRequest, response)) {

return;

}

try {

// 真正執行handler的方法,返回ModelAndView

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

}

......

}

可以看到,真正傳進去的參數都是processedRequest,所以說,即使你在interceptor的前置攔截中將processedRequest的引用指向了自定義的request,在真正處理handler的時候,傳進去的仍然是processedRequest,而不是你自己的request。所以只能在調用doDispatch之前將HttpServletRequest的引用指向自定義的request,而filter恰好可以做到

2> 有關filter的配置,當然是使用spring的代理filter:DelegatingFilterProxy,web.xml如下

<filter>

<filter-name>DelegatingFilterProxy</filter-name>

<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

<init-param>

<param-name>targetBeanName</param-name>

<param-value>filterManager</param-value>

</init-param>

<init-param>

<param-name>targetFilterLifecycle</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>DelegatingFilterProxy</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

然後在spring的配置中聲明filter,如下

<bean id="convinientFilter" name="convinientFilter"

class="com.mine.support.web.filter.ConvinientFilter">

<property name="excludeMappingPath" value="/,/*.log,/*log,*.css,*.js,*.png,*.jpg,*.jpeg"></property>

</bean>

<bean id="filterManager" class="com.mine.support.web.filter.FilterManager">

<property name="filters">

<list>

<ref bean="convinientFilter"/>

</list>

</property>

</bean>

---------------------------------------------------------------------------------------------------------------------------------------------------------------

然後說一下自己的一些事,由於十月打了一整月比賽,所以十月沒時間寫博客,然後我的話基本上有問題我都會回復的,只是有些奇怪我記得11月1號我回復了一個問題了的(確信的眼神),但是今天發現我的回復莫名奇妙不見了,所以也不知道真實情況是什麼,不過既然已經過了這麼久,相信問題也已經自己解決了吧,就不再重複回復了( ̄▽ ̄)

如何修改request參數值並應用到springMvc中

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

內核態(Kernel Mode)與用戶態(User Mode)
springmvc里使用註解進行攔截器配置

TAG:程序員小新人學習 |