Наличие favicon.*
в Вашем корневом каталоге автоматически обнаруживается большинством браузеров. Можно удостовериться, что это обнаруживается при помощи:
<link rel="icon" type="image/png" href="/path/image.png" />
Лично я использую изображения .png, но большинство форматов должно работать.
Spring можно использовать в качестве замены шины событий, поскольку ApplicationContext
также является ApplicationEventPublisher
Эталонная реализация Spring находится в ] SimpleApplicationEventMulticaster
, который может дополнительно использовать пул потоков для асинхронного распределения событий.
Одним из них является использование прокси классов на основе CGLib для AOP Spring. Это также можно сделать через динамические прокси Java, но по умолчанию это CGLib. Так что не удивляйтесь, если вы увидите CGLib в трассировке стека.
Другой вариант - использование АОП для DI. Да, везде АОП без вашего ведома. Приятно знать, что ваш код основан на АОП, даже если вы используете Spring только для целей DI.
Лучший способ найти любые скрытые функции в Spring - это просто просмотреть исходный код.
Трудно сказать, что такое скрытая функция, хотя, поскольку Spring очень гибок с аннотациями, AspectJ и использованием DI.
Spring имеет мощный встроенный StringUtils класс
Обратите внимание на следующий массив, содержащий набор идентификаторов
String [] idArray = new String [] {"0", "1", "2", "0", "5", "2"}
и вы хотите удалить повторяющиеся ссылки. Просто сделайте это
idArray = StringUtils.removeDuplicateStrings(idArray);
Теперь idArray будет содержать {"0", "1", "2", "5"}.
И многое другое.
Можно ли использовать класс контроллера без объявления их в файле контекста веб-приложения?
Да, просто поместите @Component в его объявление (@Controller не работает должным образом)
package br.com.spring.view.controller
@Component
public class PlayerController extends MultiActionController {
private Service service;
@Autowired
public PlayerController(InternalPathMethodNameResolver ipmnr, Service service) {
this.service = service;
setMethodNameResolver(ipmnr);
}
// mapped to /player/add
public ModelAndView add(...) {}
// mapped to /player/remove
public ModelAndView remove(...) {}
// mapped to /player/list
public ModelAndView list(...) {}
}
Итак, в файле контекста веб-приложения поместите следующее
<beans ...>
<context:component-scan base-package="br.com.spring.view"/>
<context:annotation-config/>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="order" value="0"/>
<property name="caseSensitive" value="true"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver"/>
</beans>
Ничего другого
Проверка в динамических формах?
Используйте следующее
public class Team {
private List<Player> playerList;
}
Значит, в валидаторе Team поместите
@Component
public class TeamValidator implements Validator {
private PlayerValidator playerValidator;
@Autowired
public TeamValidator(PlayerValidator playerValidator) {
this.playerValidator = playerValidator;
}
public boolean supports(Class clazz) {
return clazz.isAssignableFrom(Team.class);
}
public void validate(Object command, Errors errors) {
Team team = (Team) command;
// do Team validation
int index = 0;
for(Player player: team.getPlayerList()) {
// Notice code just bellow
errors.pushNestedPath("playerList[" + index++ + "]");
ValidationUtils.invokeValidator(playerValidator, player, errors);
errors.popNestedPath();
}
}
}
Наследование в веб-формы?
Используйте ServlerRequestDataBinder вместе с флагом скрытой формы
public class Command {
private Parent parent;
}
public class Child extends Parent { ... }
public class AnotherChild extends Parent { ... }
И в вашем контроллере сделайте следующее
public class MyController extends MultiActionController {
public ModelAndView action(HttpServletRequest request, HttpServletResponse response, Object command) {
Command command = (Command) command;
// hidden form flag
String parentChildType = ServletRequestUtils.getRequiredStringParameter(request, "parentChildType");
// getApplicationContext().getBean(parentChildType) retrieves a Parent object from a application context file
ServletRequestDataBinder binder =
new ServletRequestDataBinder(getApplicationContext().getBean(parentChildType));
// populates Parent child object
binder.bind(request);
command.setParent((Parent) binder.getTarget());
}
Spring имеет встроенный класс сканера ClassPathScanningCandidateComponentProvider . Вы можете использовать его, например, для поиска аннотаций.
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFAULT_FILTER>);
scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class));
for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>))
System.out.println(bd.getBeanClassName());
Spring имеет полезный класс org.springframework.util.FileCopyUtils . Вы можете скопировать загруженный файл с помощью
public ModelAndView action(...) throws Exception {
Command command = (Command) command;
MultiPartFile uploadedFile = command.getFile();
FileCopyUtils.copy(uploadedFile.getBytes(), new File("destination"));
. Если вы используете контроллер на основе аннотаций (Spring 2.5+) ИЛИ простой контроллер MVC Spring, вы можете использовать WebBindingInitializer для регистрации редакторов глобальных свойств.