servlet仿struts参数注入

在struts中可以在action中声明一个成员变量如Game game和Date date,接口访问时可以通过http://xxx.com/xxx/addGameScore?game.gameID=xx&&game.score=10&&date=xxx的方式

直接将参数注入。用servlet模拟struts的参数注入,可以使用一个servlet对应一个接口集,如只创建一个servlet就可以处理所有关于玩家Player相关的接口

代码如下:

创建一个PlayerServlet

 1 /**
 2  * 玩家相关入口
 3  *
 4  */
 5 public class PlayerServlet extends HttpServlet {
 6     private static final long serialVersionUID = -5269133950459049991L;
 7 
 8     public PlayerServlet() {
 9         super();
10     }
11 
12     public void destroy() {
13         super.destroy(); 
14     }
15 
16     public void doGet(HttpServletRequest request, HttpServletResponse response)
17             throws ServletException, IOException {
18         handleService(request,response);
19     }
20 
21     public void doPost(HttpServletRequest request, HttpServletResponse response)
22             throws ServletException, IOException {
23         handleService(request,response);
24     }
25     //提交给servlet的参数中必须包含target参数,值为对应action的public方法
26     //处理业务逻辑
27     private void handleService(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
28         PlayerAction playerAction = new PlayerAction();
29         ServletUtil.handleServletRequest(playerAction, request, response);
30         playerAction = null;
31     }
32     
33     public void init() throws ServletException {
34         
35     }
36 }

如struts一样,需要一个PlayerAction,里面的成员变量为注入的参数,公共方法为对应的逻辑方法 

创建PlayerAction

 1 /**
 2  * 玩家相关Action
 3  */
 4 public class PlayerAction extends BaseAction{
 5 
 6     private Integer playerID;
 7     
 8     private String playerNickName;
 9     
10     private Player player;
11     
12     private IPlayerService playerService;
13     
14     public PlayerAction(){
15         this.playerService = new PlayerServiceImpl();
16     }
17     /**玩家登陆*/
18     public void playerLogin(){
19         System.out.println("playerAccount:"+player.getPlayerAccount());
20         System.out.println("playerPassword:"+player.getPlayerPassword());
21     }
22     /**查询玩家信息*/
23     public void findPlayer(){
24         try {
25             response.getWriter().write("玩家ID:"+playerID+",昵称:"+playerNickName);
26         } catch (Exception e) {
27             e.printStackTrace();
28         }
29     }
30     
31 //===========相关get和set方法======================================
32     public void setPlayerID(Integer playerID) {
33         this.playerID = playerID;
34     }
35 
36     public void setPlayerNickName(String playerNickName) {
37         this.playerNickName = playerNickName;
38     }
39 
40     public void setPlayer(Player player) {
41         this.player = player;
42     }
43     public Player getPlayer() {
44         return player;
45     }
46 }

核心servletUtil,使用java反射注入参数

  1 /**
  2  * servlet工具类,提供servlet向action自动注入参数的相关工具
  3  *
  4  */
  5 public class ServletUtil {
  6     /**
  7      * 处理servlet请求,完成request、response和其它参数注入
  8      * @param baseAction
  9      * @param request
 10      * @param response
 11      */
 12     @SuppressWarnings({ "unchecked", "rawtypes" })
 13     public static void handleServletRequest(BaseAction baseAction,
 14             HttpServletRequest request,HttpServletResponse response){
 15         try {
 16             //注入request和response
 17             requestAndResponseInject(baseAction, request, response);
 18             Map<String, String[]> argsMap  = request.getParameterMap();//获取提交参数
 19             String targetMethod = request.getParameter("target");//获取调用目标方法名
 20             Iterator<Entry<String, String[]>> iterator= argsMap.entrySet().iterator();
 21             while(iterator.hasNext()){
 22                 Entry<String, String[]> entry = iterator.next();
 23                 String key = entry.getKey();
 24                 if(!key.equals("target")){
 25                     ServletUtil.propertyInject(key,entry.getValue(),baseAction);//注入参数
 26                 }
 27             }
 28             Class actionClass = baseAction.getClass();
 29             Method method = actionClass.getDeclaredMethod(targetMethod);
 30             method.invoke(baseAction);//调用目标方法
 31         } catch (Exception e) {
 32             e.printStackTrace();
 33         }
 34     }
 35     
 36     /**
 37      * 向目标action注入request和response对象
 38      * @param target 目标action
 39      * @param request
 40      * @param response
 41      * @throws Exception
 42      */
 43     @SuppressWarnings("rawtypes")
 44     private static void requestAndResponseInject(Object target,
 45             HttpServletRequest request,HttpServletResponse response) throws Exception{
 46         Class actionClass = target.getClass();
 47         Field[] fields = actionClass.getFields();
 48         for(Field f:fields){
 49             if(HttpServletRequest.class.isAssignableFrom(f.getType())){
 50                 f.setAccessible(true);
 51                 f.set(target, request);
 52             }else if(HttpServletResponse.class.isAssignableFrom(f.getType())){
 53                 f.setAccessible(true);
 54                 f.set(target, response);
 55             }
 56         }
 57     }
 58     /**
 59      * 属性注入,支持基本类型、时间和对象,List和Set泛型只支持基本类型
 60      * @param key 属性键
 61      * @param value 值
 62      * @param target 注入目标
 63      * @throws Exception
 64      */
 65     @SuppressWarnings({ "rawtypes", "unchecked" })
 66     public static void propertyInject(String key,String[] value,Object target)throws Exception{
 67         Class actionType = target.getClass();
 68         //非自定义复合对象
 69         if(!key.contains(".")){
 70             Field field = actionType.getDeclaredField(key);
 71             Class fieldType = field.getType();
 72             //获取setXXX方法
 73             Method method=actionType.getDeclaredMethod("set"+key.substring(0, 1).toUpperCase()+key.substring(1),fieldType);
 74             if(List.class.isAssignableFrom(fieldType)){//List泛型
 75                 List<Object> list = new ArrayList<Object>();
 76                 //获取泛型类型
 77                 Type[] argType = ((ParameterizedType)field.getGenericType()).getActualTypeArguments();
 78                 for(int i=0;i<value.length;i++){
 79                     list.add(generateNormalValue((Class)argType[0],value[i]));//填入List
 80                 }
 81                 method.invoke(target,list);//注入List
 82             }else if(Set.class.isAssignableFrom(fieldType)){
 83                 Set<Object> set = new HashSet<Object>();
 84                 Type[] argType = ((ParameterizedType)field.getGenericType()).getActualTypeArguments();
 85                 for(int i=0;i<value.length;i++){
 86                     set.add(generateNormalValue((Class)argType[0],value[i]));
 87                 }
 88                 method.invoke(target,set);
 89             }else{
 90                 method.invoke(target,generateNormalValue(fieldType,value[0]));//基本类型
 91             }
 92         }else{//自定义复合对象属性
 93             generateObjectValue(key,value[0],target);
 94         }
 95     }    
 96     
 97     /**
 98      * 生成基本类型值
 99      * @param fieldType 字段类型
100      * @param value 值
101      * @return
102      * @throws Exception
103      */
104     @SuppressWarnings({ "rawtypes", "unchecked" })
105     private static Object generateNormalValue(Class fieldType,Object value)throws Exception{
106         //如果为时间类型,转换时间
107         if(Date.class.isAssignableFrom(fieldType)){
108             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
109             Date date = sdf.parse(value.toString());
110             return date;
111         }else{//Integer、String、Long等封装类型
112             //获取单参构造函数
113             Constructor<String> ctor = fieldType.getConstructor(String.class);
114             return ctor.newInstance(value);
115         }
116     }
117     
118     /**
119      * 生成自定义对象值
120      * @param key 属性键
121      * @param value 值
122      * @param target 注入目标
123      * @throws Exception
124      */
125     @SuppressWarnings({ "rawtypes", "unchecked" })
126     private static void generateObjectValue(String key,Object value,Object target)throws Exception{
127         String subKey = key;
128         Class targetType = target.getClass();
129         String[] keys = key.split("\.");//分割键
130         subKey = keys[0];
131         Field field = targetType.getDeclaredField(subKey);
132         Class fieldType = field.getType();
133         //获取setXXX方法
134         Method setMethod=targetType.getDeclaredMethod("set"+subKey.substring(0, 1).toUpperCase()+subKey.substring(1),fieldType);
135         if(keys.length>1){
136             Constructor<String> ctor = fieldType.getConstructor();//获取默认构造函数
137             //获取getXXX方法
138             Method getMethod=targetType.getDeclaredMethod("get"+subKey.substring(0, 1).toUpperCase()+subKey.substring(1));
139             Object subTarget = getMethod.invoke(target);
140             if(null==subTarget){
141                 subTarget = ctor.newInstance();//调用无参构造函数
142             }
143             setMethod.invoke(target, subTarget);//对象注入
144             generateObjectValue((key.split("\.", 2))[1],value,subTarget);//子属性还是对象,递归注入
145         }else{
146             setMethod.invoke(target,generateNormalValue(fieldType,value));//子属性为基本类型
147         }
148     }
149 }

代码中的BaseAction就是一个普通的类,包含了request和response成员变量和相关的数据输出方法

 1 /**
 2  * action基类,包含request和response信息及数据输出方法
 3  *
 4  */
 5 public class BaseAction {
 6 
 7     public HttpServletRequest request;
 8 
 9     public HttpServletResponse response;
10 //==数据输出方法==
11 //....
12 }

web.xml

1   <!-- 玩家相关请求入口 -->
2     <servlet-name>PlayerServlet</servlet-name>
3     <servlet-class>com.xxx.servlet.PlayerServlet</servlet-class>
4   </servlet>
5   <servlet-mapping>
6     <servlet-name>PlayerServlet</servlet-name>
7     <url-pattern>/player</url-pattern>
8   </servlet-mapping>

调用方式:

调用登陆方法:http://www.xxx.com/项目根/player?target=playerLogin&player.playerAccount=xx&player.playerPassword=xxx

调用查询方法:http://www.xxx.com/项目根/player?target=findPlayer&player.playerID=xx

本文地址:http://www.cnblogs.com/wangjiajun/p/4788308.html 

原文地址:https://www.cnblogs.com/wangjiajun/p/4788308.html