001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.bind; 018 019import javax.servlet.ServletRequest; 020 021/** 022 * Parameter extraction methods, for an approach distinct from data binding, 023 * in which parameters of specific types are required. 024 * 025 * <p>This approach is very useful for simple submissions, where binding 026 * request parameters to a command object would be overkill. 027 * 028 * @author Juergen Hoeller 029 * @author Keith Donald 030 * @since 2.0 031 */ 032public abstract class ServletRequestUtils { 033 034 private static final IntParser INT_PARSER = new IntParser(); 035 036 private static final LongParser LONG_PARSER = new LongParser(); 037 038 private static final FloatParser FLOAT_PARSER = new FloatParser(); 039 040 private static final DoubleParser DOUBLE_PARSER = new DoubleParser(); 041 042 private static final BooleanParser BOOLEAN_PARSER = new BooleanParser(); 043 044 private static final StringParser STRING_PARSER = new StringParser(); 045 046 047 /** 048 * Get an Integer parameter, or {@code null} if not present. 049 * Throws an exception if it the parameter value isn't a number. 050 * @param request current HTTP request 051 * @param name the name of the parameter 052 * @return the Integer value, or {@code null} if not present 053 * @throws ServletRequestBindingException a subclass of ServletException, 054 * so it doesn't need to be caught 055 */ 056 public static Integer getIntParameter(ServletRequest request, String name) 057 throws ServletRequestBindingException { 058 059 if (request.getParameter(name) == null) { 060 return null; 061 } 062 return getRequiredIntParameter(request, name); 063 } 064 065 /** 066 * Get an int parameter, with a fallback value. Never throws an exception. 067 * Can pass a distinguished value as default to enable checks of whether it was supplied. 068 * @param request current HTTP request 069 * @param name the name of the parameter 070 * @param defaultVal the default value to use as fallback 071 */ 072 public static int getIntParameter(ServletRequest request, String name, int defaultVal) { 073 if (request.getParameter(name) == null) { 074 return defaultVal; 075 } 076 try { 077 return getRequiredIntParameter(request, name); 078 } 079 catch (ServletRequestBindingException ex) { 080 return defaultVal; 081 } 082 } 083 084 /** 085 * Get an array of int parameters, return an empty array if not found. 086 * @param request current HTTP request 087 * @param name the name of the parameter with multiple possible values 088 */ 089 public static int[] getIntParameters(ServletRequest request, String name) { 090 try { 091 return getRequiredIntParameters(request, name); 092 } 093 catch (ServletRequestBindingException ex) { 094 return new int[0]; 095 } 096 } 097 098 /** 099 * Get an int parameter, throwing an exception if it isn't found or isn't a number. 100 * @param request current HTTP request 101 * @param name the name of the parameter 102 * @throws ServletRequestBindingException a subclass of ServletException, 103 * so it doesn't need to be caught 104 */ 105 public static int getRequiredIntParameter(ServletRequest request, String name) 106 throws ServletRequestBindingException { 107 108 return INT_PARSER.parseInt(name, request.getParameter(name)); 109 } 110 111 /** 112 * Get an array of int parameters, throwing an exception if not found or one is not a number.. 113 * @param request current HTTP request 114 * @param name the name of the parameter with multiple possible values 115 * @throws ServletRequestBindingException a subclass of ServletException, 116 * so it doesn't need to be caught 117 */ 118 public static int[] getRequiredIntParameters(ServletRequest request, String name) 119 throws ServletRequestBindingException { 120 121 return INT_PARSER.parseInts(name, request.getParameterValues(name)); 122 } 123 124 125 /** 126 * Get a Long parameter, or {@code null} if not present. 127 * Throws an exception if it the parameter value isn't a number. 128 * @param request current HTTP request 129 * @param name the name of the parameter 130 * @return the Long value, or {@code null} if not present 131 * @throws ServletRequestBindingException a subclass of ServletException, 132 * so it doesn't need to be caught 133 */ 134 public static Long getLongParameter(ServletRequest request, String name) 135 throws ServletRequestBindingException { 136 137 if (request.getParameter(name) == null) { 138 return null; 139 } 140 return getRequiredLongParameter(request, name); 141 } 142 143 /** 144 * Get a long parameter, with a fallback value. Never throws an exception. 145 * Can pass a distinguished value as default to enable checks of whether it was supplied. 146 * @param request current HTTP request 147 * @param name the name of the parameter 148 * @param defaultVal the default value to use as fallback 149 */ 150 public static long getLongParameter(ServletRequest request, String name, long defaultVal) { 151 if (request.getParameter(name) == null) { 152 return defaultVal; 153 } 154 try { 155 return getRequiredLongParameter(request, name); 156 } 157 catch (ServletRequestBindingException ex) { 158 return defaultVal; 159 } 160 } 161 162 /** 163 * Get an array of long parameters, return an empty array if not found. 164 * @param request current HTTP request 165 * @param name the name of the parameter with multiple possible values 166 */ 167 public static long[] getLongParameters(ServletRequest request, String name) { 168 try { 169 return getRequiredLongParameters(request, name); 170 } 171 catch (ServletRequestBindingException ex) { 172 return new long[0]; 173 } 174 } 175 176 /** 177 * Get a long parameter, throwing an exception if it isn't found or isn't a number. 178 * @param request current HTTP request 179 * @param name the name of the parameter 180 * @throws ServletRequestBindingException a subclass of ServletException, 181 * so it doesn't need to be caught 182 */ 183 public static long getRequiredLongParameter(ServletRequest request, String name) 184 throws ServletRequestBindingException { 185 186 return LONG_PARSER.parseLong(name, request.getParameter(name)); 187 } 188 189 /** 190 * Get an array of long parameters, throwing an exception if not found or one is not a number. 191 * @param request current HTTP request 192 * @param name the name of the parameter with multiple possible values 193 * @throws ServletRequestBindingException a subclass of ServletException, 194 * so it doesn't need to be caught 195 */ 196 public static long[] getRequiredLongParameters(ServletRequest request, String name) 197 throws ServletRequestBindingException { 198 199 return LONG_PARSER.parseLongs(name, request.getParameterValues(name)); 200 } 201 202 203 /** 204 * Get a Float parameter, or {@code null} if not present. 205 * Throws an exception if it the parameter value isn't a number. 206 * @param request current HTTP request 207 * @param name the name of the parameter 208 * @return the Float value, or {@code null} if not present 209 * @throws ServletRequestBindingException a subclass of ServletException, 210 * so it doesn't need to be caught 211 */ 212 public static Float getFloatParameter(ServletRequest request, String name) 213 throws ServletRequestBindingException { 214 215 if (request.getParameter(name) == null) { 216 return null; 217 } 218 return getRequiredFloatParameter(request, name); 219 } 220 221 /** 222 * Get a float parameter, with a fallback value. Never throws an exception. 223 * Can pass a distinguished value as default to enable checks of whether it was supplied. 224 * @param request current HTTP request 225 * @param name the name of the parameter 226 * @param defaultVal the default value to use as fallback 227 */ 228 public static float getFloatParameter(ServletRequest request, String name, float defaultVal) { 229 if (request.getParameter(name) == null) { 230 return defaultVal; 231 } 232 try { 233 return getRequiredFloatParameter(request, name); 234 } 235 catch (ServletRequestBindingException ex) { 236 return defaultVal; 237 } 238 } 239 240 /** 241 * Get an array of float parameters, return an empty array if not found. 242 * @param request current HTTP request 243 * @param name the name of the parameter with multiple possible values 244 */ 245 public static float[] getFloatParameters(ServletRequest request, String name) { 246 try { 247 return getRequiredFloatParameters(request, name); 248 } 249 catch (ServletRequestBindingException ex) { 250 return new float[0]; 251 } 252 } 253 254 /** 255 * Get a float parameter, throwing an exception if it isn't found or isn't a number. 256 * @param request current HTTP request 257 * @param name the name of the parameter 258 * @throws ServletRequestBindingException a subclass of ServletException, 259 * so it doesn't need to be caught 260 */ 261 public static float getRequiredFloatParameter(ServletRequest request, String name) 262 throws ServletRequestBindingException { 263 264 return FLOAT_PARSER.parseFloat(name, request.getParameter(name)); 265 } 266 267 /** 268 * Get an array of float parameters, throwing an exception if not found or one is not a number. 269 * @param request current HTTP request 270 * @param name the name of the parameter with multiple possible values 271 * @throws ServletRequestBindingException a subclass of ServletException, 272 * so it doesn't need to be caught 273 */ 274 public static float[] getRequiredFloatParameters(ServletRequest request, String name) 275 throws ServletRequestBindingException { 276 277 return FLOAT_PARSER.parseFloats(name, request.getParameterValues(name)); 278 } 279 280 281 /** 282 * Get a Double parameter, or {@code null} if not present. 283 * Throws an exception if it the parameter value isn't a number. 284 * @param request current HTTP request 285 * @param name the name of the parameter 286 * @return the Double value, or {@code null} if not present 287 * @throws ServletRequestBindingException a subclass of ServletException, 288 * so it doesn't need to be caught 289 */ 290 public static Double getDoubleParameter(ServletRequest request, String name) 291 throws ServletRequestBindingException { 292 293 if (request.getParameter(name) == null) { 294 return null; 295 } 296 return getRequiredDoubleParameter(request, name); 297 } 298 299 /** 300 * Get a double parameter, with a fallback value. Never throws an exception. 301 * Can pass a distinguished value as default to enable checks of whether it was supplied. 302 * @param request current HTTP request 303 * @param name the name of the parameter 304 * @param defaultVal the default value to use as fallback 305 */ 306 public static double getDoubleParameter(ServletRequest request, String name, double defaultVal) { 307 if (request.getParameter(name) == null) { 308 return defaultVal; 309 } 310 try { 311 return getRequiredDoubleParameter(request, name); 312 } 313 catch (ServletRequestBindingException ex) { 314 return defaultVal; 315 } 316 } 317 318 /** 319 * Get an array of double parameters, return an empty array if not found. 320 * @param request current HTTP request 321 * @param name the name of the parameter with multiple possible values 322 */ 323 public static double[] getDoubleParameters(ServletRequest request, String name) { 324 try { 325 return getRequiredDoubleParameters(request, name); 326 } 327 catch (ServletRequestBindingException ex) { 328 return new double[0]; 329 } 330 } 331 332 /** 333 * Get a double parameter, throwing an exception if it isn't found or isn't a number. 334 * @param request current HTTP request 335 * @param name the name of the parameter 336 * @throws ServletRequestBindingException a subclass of ServletException, 337 * so it doesn't need to be caught 338 */ 339 public static double getRequiredDoubleParameter(ServletRequest request, String name) 340 throws ServletRequestBindingException { 341 342 return DOUBLE_PARSER.parseDouble(name, request.getParameter(name)); 343 } 344 345 /** 346 * Get an array of double parameters, throwing an exception if not found or one is not a number. 347 * @param request current HTTP request 348 * @param name the name of the parameter with multiple possible values 349 * @throws ServletRequestBindingException a subclass of ServletException, 350 * so it doesn't need to be caught 351 */ 352 public static double[] getRequiredDoubleParameters(ServletRequest request, String name) 353 throws ServletRequestBindingException { 354 355 return DOUBLE_PARSER.parseDoubles(name, request.getParameterValues(name)); 356 } 357 358 359 /** 360 * Get a Boolean parameter, or {@code null} if not present. 361 * Throws an exception if it the parameter value isn't a boolean. 362 * <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; 363 * treats every other non-empty value as false (i.e. parses leniently). 364 * @param request current HTTP request 365 * @param name the name of the parameter 366 * @return the Boolean value, or {@code null} if not present 367 * @throws ServletRequestBindingException a subclass of ServletException, 368 * so it doesn't need to be caught 369 */ 370 public static Boolean getBooleanParameter(ServletRequest request, String name) 371 throws ServletRequestBindingException { 372 373 if (request.getParameter(name) == null) { 374 return null; 375 } 376 return (getRequiredBooleanParameter(request, name)); 377 } 378 379 /** 380 * Get a boolean parameter, with a fallback value. Never throws an exception. 381 * Can pass a distinguished value as default to enable checks of whether it was supplied. 382 * <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; 383 * treats every other non-empty value as false (i.e. parses leniently). 384 * @param request current HTTP request 385 * @param name the name of the parameter 386 * @param defaultVal the default value to use as fallback 387 */ 388 public static boolean getBooleanParameter(ServletRequest request, String name, boolean defaultVal) { 389 if (request.getParameter(name) == null) { 390 return defaultVal; 391 } 392 try { 393 return getRequiredBooleanParameter(request, name); 394 } 395 catch (ServletRequestBindingException ex) { 396 return defaultVal; 397 } 398 } 399 400 /** 401 * Get an array of boolean parameters, return an empty array if not found. 402 * <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; 403 * treats every other non-empty value as false (i.e. parses leniently). 404 * @param request current HTTP request 405 * @param name the name of the parameter with multiple possible values 406 */ 407 public static boolean[] getBooleanParameters(ServletRequest request, String name) { 408 try { 409 return getRequiredBooleanParameters(request, name); 410 } 411 catch (ServletRequestBindingException ex) { 412 return new boolean[0]; 413 } 414 } 415 416 /** 417 * Get a boolean parameter, throwing an exception if it isn't found 418 * or isn't a boolean. 419 * <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; 420 * treats every other non-empty value as false (i.e. parses leniently). 421 * @param request current HTTP request 422 * @param name the name of the parameter 423 * @throws ServletRequestBindingException a subclass of ServletException, 424 * so it doesn't need to be caught 425 */ 426 public static boolean getRequiredBooleanParameter(ServletRequest request, String name) 427 throws ServletRequestBindingException { 428 429 return BOOLEAN_PARSER.parseBoolean(name, request.getParameter(name)); 430 } 431 432 /** 433 * Get an array of boolean parameters, throwing an exception if not found 434 * or one isn't a boolean. 435 * <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; 436 * treats every other non-empty value as false (i.e. parses leniently). 437 * @param request current HTTP request 438 * @param name the name of the parameter 439 * @throws ServletRequestBindingException a subclass of ServletException, 440 * so it doesn't need to be caught 441 */ 442 public static boolean[] getRequiredBooleanParameters(ServletRequest request, String name) 443 throws ServletRequestBindingException { 444 445 return BOOLEAN_PARSER.parseBooleans(name, request.getParameterValues(name)); 446 } 447 448 449 /** 450 * Get a String parameter, or {@code null} if not present. 451 * @param request current HTTP request 452 * @param name the name of the parameter 453 * @return the String value, or {@code null} if not present 454 * @throws ServletRequestBindingException a subclass of ServletException, 455 * so it doesn't need to be caught 456 */ 457 public static String getStringParameter(ServletRequest request, String name) 458 throws ServletRequestBindingException { 459 460 if (request.getParameter(name) == null) { 461 return null; 462 } 463 return getRequiredStringParameter(request, name); 464 } 465 466 /** 467 * Get a String parameter, with a fallback value. Never throws an exception. 468 * Can pass a distinguished value to default to enable checks of whether it was supplied. 469 * @param request current HTTP request 470 * @param name the name of the parameter 471 * @param defaultVal the default value to use as fallback 472 */ 473 public static String getStringParameter(ServletRequest request, String name, String defaultVal) { 474 String val = request.getParameter(name); 475 return (val != null ? val : defaultVal); 476 } 477 478 /** 479 * Get an array of String parameters, return an empty array if not found. 480 * @param request current HTTP request 481 * @param name the name of the parameter with multiple possible values 482 */ 483 public static String[] getStringParameters(ServletRequest request, String name) { 484 try { 485 return getRequiredStringParameters(request, name); 486 } 487 catch (ServletRequestBindingException ex) { 488 return new String[0]; 489 } 490 } 491 492 /** 493 * Get a String parameter, throwing an exception if it isn't found. 494 * @param request current HTTP request 495 * @param name the name of the parameter 496 * @throws ServletRequestBindingException a subclass of ServletException, 497 * so it doesn't need to be caught 498 */ 499 public static String getRequiredStringParameter(ServletRequest request, String name) 500 throws ServletRequestBindingException { 501 502 return STRING_PARSER.validateRequiredString(name, request.getParameter(name)); 503 } 504 505 /** 506 * Get an array of String parameters, throwing an exception if not found. 507 * @param request current HTTP request 508 * @param name the name of the parameter 509 * @throws ServletRequestBindingException a subclass of ServletException, 510 * so it doesn't need to be caught 511 */ 512 public static String[] getRequiredStringParameters(ServletRequest request, String name) 513 throws ServletRequestBindingException { 514 515 return STRING_PARSER.validateRequiredStrings(name, request.getParameterValues(name)); 516 } 517 518 519 private abstract static class ParameterParser<T> { 520 521 protected final T parse(String name, String parameter) throws ServletRequestBindingException { 522 validateRequiredParameter(name, parameter); 523 try { 524 return doParse(parameter); 525 } 526 catch (NumberFormatException ex) { 527 throw new ServletRequestBindingException( 528 "Required " + getType() + " parameter '" + name + "' with value of '" + 529 parameter + "' is not a valid number", ex); 530 } 531 } 532 533 protected final void validateRequiredParameter(String name, Object parameter) 534 throws ServletRequestBindingException { 535 536 if (parameter == null) { 537 throw new MissingServletRequestParameterException(name, getType()); 538 } 539 } 540 541 protected abstract String getType(); 542 543 protected abstract T doParse(String parameter) throws NumberFormatException; 544 } 545 546 547 private static class IntParser extends ParameterParser<Integer> { 548 549 @Override 550 protected String getType() { 551 return "int"; 552 } 553 554 @Override 555 protected Integer doParse(String s) throws NumberFormatException { 556 return Integer.valueOf(s); 557 } 558 559 public int parseInt(String name, String parameter) throws ServletRequestBindingException { 560 return parse(name, parameter); 561 } 562 563 public int[] parseInts(String name, String[] values) throws ServletRequestBindingException { 564 validateRequiredParameter(name, values); 565 int[] parameters = new int[values.length]; 566 for (int i = 0; i < values.length; i++) { 567 parameters[i] = parseInt(name, values[i]); 568 } 569 return parameters; 570 } 571 } 572 573 574 private static class LongParser extends ParameterParser<Long> { 575 576 @Override 577 protected String getType() { 578 return "long"; 579 } 580 581 @Override 582 protected Long doParse(String parameter) throws NumberFormatException { 583 return Long.valueOf(parameter); 584 } 585 586 public long parseLong(String name, String parameter) throws ServletRequestBindingException { 587 return parse(name, parameter); 588 } 589 590 public long[] parseLongs(String name, String[] values) throws ServletRequestBindingException { 591 validateRequiredParameter(name, values); 592 long[] parameters = new long[values.length]; 593 for (int i = 0; i < values.length; i++) { 594 parameters[i] = parseLong(name, values[i]); 595 } 596 return parameters; 597 } 598 } 599 600 601 private static class FloatParser extends ParameterParser<Float> { 602 603 @Override 604 protected String getType() { 605 return "float"; 606 } 607 608 @Override 609 protected Float doParse(String parameter) throws NumberFormatException { 610 return Float.valueOf(parameter); 611 } 612 613 public float parseFloat(String name, String parameter) throws ServletRequestBindingException { 614 return parse(name, parameter); 615 } 616 617 public float[] parseFloats(String name, String[] values) throws ServletRequestBindingException { 618 validateRequiredParameter(name, values); 619 float[] parameters = new float[values.length]; 620 for (int i = 0; i < values.length; i++) { 621 parameters[i] = parseFloat(name, values[i]); 622 } 623 return parameters; 624 } 625 } 626 627 628 private static class DoubleParser extends ParameterParser<Double> { 629 630 @Override 631 protected String getType() { 632 return "double"; 633 } 634 635 @Override 636 protected Double doParse(String parameter) throws NumberFormatException { 637 return Double.valueOf(parameter); 638 } 639 640 public double parseDouble(String name, String parameter) throws ServletRequestBindingException { 641 return parse(name, parameter); 642 } 643 644 public double[] parseDoubles(String name, String[] values) throws ServletRequestBindingException { 645 validateRequiredParameter(name, values); 646 double[] parameters = new double[values.length]; 647 for (int i = 0; i < values.length; i++) { 648 parameters[i] = parseDouble(name, values[i]); 649 } 650 return parameters; 651 } 652 } 653 654 655 private static class BooleanParser extends ParameterParser<Boolean> { 656 657 @Override 658 protected String getType() { 659 return "boolean"; 660 } 661 662 @Override 663 protected Boolean doParse(String parameter) throws NumberFormatException { 664 return (parameter.equalsIgnoreCase("true") || parameter.equalsIgnoreCase("on") || 665 parameter.equalsIgnoreCase("yes") || parameter.equals("1")); 666 } 667 668 public boolean parseBoolean(String name, String parameter) throws ServletRequestBindingException { 669 return parse(name, parameter); 670 } 671 672 public boolean[] parseBooleans(String name, String[] values) throws ServletRequestBindingException { 673 validateRequiredParameter(name, values); 674 boolean[] parameters = new boolean[values.length]; 675 for (int i = 0; i < values.length; i++) { 676 parameters[i] = parseBoolean(name, values[i]); 677 } 678 return parameters; 679 } 680 } 681 682 683 private static class StringParser extends ParameterParser<String> { 684 685 @Override 686 protected String getType() { 687 return "string"; 688 } 689 690 @Override 691 protected String doParse(String parameter) throws NumberFormatException { 692 return parameter; 693 } 694 695 public String validateRequiredString(String name, String value) throws ServletRequestBindingException { 696 validateRequiredParameter(name, value); 697 return value; 698 } 699 700 public String[] validateRequiredStrings(String name, String[] values) throws ServletRequestBindingException { 701 validateRequiredParameter(name, values); 702 for (String value : values) { 703 validateRequiredParameter(name, value); 704 } 705 return values; 706 } 707 } 708 709}