- 前端可以传递
String
类型,被后端的integer
类型的pojo来接收
@GetMapping("/getByIds")
public ResultUtil<User> getByIds(@RequestParam(required = false) List<String> ids) {
}
- 必须是
multipartResolver
感觉用到了依赖注入。id是固定的
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
- 表单提交成功,转发到新的页面。可是地址栏没有变化。当你刷新页面的时候,又将表单提交了
- Filter是JavaEE中Servlet规范的一个组件,位于包
javax.servlet
中,它可以在HTTP请求到达Servlet之前,被一个或多个Filter处理 - Filter的这个特性在生产环境中有很广泛的应用。eg:修改请求和响应、防止xss攻击、包装二进制流使其可以多次读,等等
- 实际工作中,我们都是使用SpringBoot进行业务开发,本文总结三种Filter用法,SpringBoot版本采用目前最新的
v2.3.1.RELEASE
- 要编写Filter,只需要实现
javax.servlet.Filter
接口就可以
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
}
- Filter接口有三个方法:
init(), doFilter(), destroy()
- 其中
doFilter()
需要自己实现,其余两个是default的,可以不用实现 - 注意:如果Filter要使请求继续被处理,就一定要调用
filterChain.doFilter()
- 让自定义的 Filter 被 Spring 的 IOC 容器管理,有三种实现方式,各有优缺点
@Component
+ @Order
注解,即可被Spring管理。缺点是拦截所有URL,不能通过配置去拦截指定的URL- 有多个Filter时,
@Order(1)
注解会指定执行顺序,数字越小,越优先执行。只写@Order
,默认顺序值是Integer.MAX_VALUE
@Component
@Order(1)
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
}
@WebFilter
注解,启动类@ServletComponentScan("com.listao.filter")
,Filter所在包路径@WebFilter + @ServletComponentScan
支持对Filter匹配指定URL,不支持指定Filter的执行顺序
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("MyFilter");
filterChain.doFilter(servletRequest,servletResponse);
}
}
@SpringBootApplication
@ServletComponentScan("com.listao.filter")
public class FilterDemoApplication {
public static void main(String[] args) {
SpringApplication.run(FilterDemoApplication.class, args);
}
}
- 每个自定义的Filter声明成Bean交给Spring管理即可,还可以设置匹配的URL、指定Filter的先后顺序
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registerMyFilter(){
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setOrder(1);
bean.setFilter(new MyFilter());
bean.addUrlPatterns("/hello/*");
return bean;
}
@Bean
public FilterRegistrationBean registerMyAnotherFilter(){
FilterRegistrationBean<MyAnotherFilter> bean = new FilterRegistrationBean<>();
bean.setOrder(2);
bean.setFilter(new MyAnotherFilter());
bean.addUrlPatterns("/*");
return bean;
}
}
ApplicationPid pid = new ApplicationPid();
System.out.printf("进程ID: %s%n", pid.toString());
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
- 可以通过在
META-INF/spring.factories
中注册监听器,将进程ID写入到一个文件中。通过配置 spring.pid.file
属性,指定文件路径
spring.pid.file=d:/app.pid
ApplicationHome home = new ApplicationHome();
System.out.printf("dir: %s, source: %s%n", home.getDir(), home.getSource());
System.out.printf("Java Version: %s%n", JavaVersion.getJavaVersion());
- 无论是在 IDE 下还是在 Jar 方式运行,Windows 平台下临时目录都位于
Temp
文件夹下
ApplicationTemp temp = new ApplicationTemp();
System.out.printf("临时目录: %s%n", temp.getDir());
SystemProperties
类可以方便地访问系统属性。如果属性不存在,它还会尝试从环境变量中获取get
方法支持可变长参数,可以传递多个 key,获取时遍历遇到非 null 的直接返回
System.out.printf("java.home=%s%n", SystemProperties.get("java.home"));
Instantiator
是一个简单工厂,可以通过注入可用参数来实例化对象- 可以方便地一次性实例化多个同类型的类
public interface DAO {}
public class A implements DAO {}
public class B implements DAO {}
Instantiator<DAO> instant = new Instantiator<>(DAO.class, p -> {});
List<DAO> ret = instant.instantiate(List.of("com.pack.A", "com.pack.B"));
System.out.printf("%s%n", ret);
- 加载后的
List
可以注册到 Environment
中,在系统中直接访问
PropertiesPropertySourceLoader propertyLoader = new PropertiesPropertySourceLoader();
List<PropertySource<?>> list = propertyLoader.load("pack", new ClassPathResource("pack.properties"));
System.out.printf("pack.*: %s%n", list.get(0).getSource());
YamlPropertySourceLoader yamlLoader = new YamlPropertySourceLoader();
List<PropertySource<?>> yamls = yamlLoader.load("pack", new ClassPathResource("pack.yml"));
System.out.printf("pack.*: %s%n", yamls.get(0).getSource());
@Autowired
private ConfigurableApplicationContext context;
System.out.printf("basePackages: %s%n", AutoConfigurationPackages.get(context));