上一篇文章中我对springboot的前期配置做了一些梳理讲解,本篇文章中将对springboot中的web开发和数据层开发进行讲解。
Web开发
SpringBoot对静态资源的映射规则
springboot的静态资源(如静态页面)一般存放在resources文件夹下的static文件夹下(没有则自己创建)。
想要使用webjar资源时,要先导入依赖,导入后都去 classpath:/META-INF/resources/webjars/ 找资源。
例如想要使用jquery,可以先引入query‐webjar依赖,然后通过路径使用
<!‐‐引入jquery‐webjar‐‐>在访问的时候只需要写webjars下面资源的名称即可
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
引入后就可以在External Libraries中找到jquery.js
使用时假设当前端口为8080,那么使用时就可以使用路径localhost:8080/webjars/jquery/3.3.1/jquery.js来引入资源。
模板引擎
模板引擎有很多,例如JSP、Velocity、Freemarker、Thymeleaf,但是在springboot中推荐使用Thymeleaf,因为语法更简单,功能更强大。
首先引入themeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
从spring父文件中能看到Springboot2.0.1所使用的thymeleaf版本是3.0.9,
springBoot启动的时候会自动配置
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
从ThymeleafAutoConfiguration的源代码中我们可以得知ThymeleafProperties
中配置了Thymeleaf的规则。
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
private boolean cache;
在使用时,我们使用html作为模板,而且默认的前缀是放在classpath:/template/下,后缀是.html
当然这些属性我们都可以通过application.properties来修改。我们采用默认即可。
1.所以在template下创建一个test.html(没有改文件夹就在resources文件夹中创建一个)
2.在html中引入thymeleaf的命名空间
@Controller
public class IndexController {
@RequestMapping("/test")
public String test(Model model){
model.addAttribute("hello","hello world");
return "test";
}
}
4.在thymeleaf模板中取值
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Title</title>
</head>
<body>
<div th:text="${hello}"> </div>
</body>
</html>
thymeleaf基本语法
1.变量表达式
变量表达式即OGNL表达式或Spring EL表达式(在Spring术语中也叫model attributes)。如下所示: ${session.user.name}
它们将以HTML标签的一个属性来表示:如上面代码中所示
2.选择(星号)表达式
选择表达式很像变量表达式,不过它们用一个预先选择的对象来代替上下文变量容器(map)来执行,如下: *{customer.name}
<div th:object="${book}">
...
<span th:text="*{title}">...</span>
...
</div>
3.文字国际化表达式
文字国际化表达式允许我们从一个外部文件获取区域文字信息(.properties),用Key索引Value,还可以提供一组参数(可选).
4.URL表达式
URL表达式指的是把一个有用的上下文或回话信息添加到URL,这个过程经常被叫做URL重写。不需要指定项目名字
@{/order/list}
URL还可以设置参数:
@{/order/details(id=${orderId})}
让我们看这些表达式:
<form th:action="@{/createOrder}">
<a href="main.html" rel="external nofollow" th:href="@{/main}" rel="external">
常用的thymeleaf标签
这里只是列举一些,想要了解更多可以自行区学习thymeleaf
Springboot整合springmvc
学习springmvc和springboot的自动配置我们必须对springmvc的组件足够了解,起码知道怎么用。Springmvc的组件基本都被springboot来做了自动的配置。
Springmvc的自动管理
springboot可以自动管理springmvc中一下模块:
中央转发器
控制器
视图解析器
消息转换器
格式化
静态资源管理
中央转发器
在springboot的管理下web.xml无需配置
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\在该配置类中已经自动装配
控制器
控制器Controller在springboot的注解扫描范围内自动管理。
视图解析器自动管理
曾经的spring中的配置文件无需再配,
<bean id="de" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value="*.jsp"></property>
</bean>
当我们做文件上传的时候我们也会发现multipartResolver是自动被配置好的
例如:
页面:
<form action="/upload" method="post" enctype="multipart/form-data">
<input name="pic" type="file">
<input type="submit">
</form>
Controller
@ResponseBody
@RequestMapping("/upload")
public String upload(@RequestParam("pic")MultipartFile file, HttpServletRequest request){
String contentType = file.getContentType();
String fileName = file.getOriginalFilename();
String filePath = "D:/imgup";
try {
this.uploadFile(file.getBytes(), filePath, fileName);
} catch (Exception e) {
}
return "success";
}
public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {
File targetFile = new File(filePath);
if(!targetFile.exists()){
targetFile.mkdirs();
}
FileOutputStream out = new FileOutputStream(filePath+fileName);
out.write(file);
out.flush();
out.close();
}
文件上传大小可以通过配置来修改
打开application.properties, 默认限制是10MB,我们可以任意修改
消息转换和格式化
Springboot自动配置了消息转换器
格式化转换器的自动注册
时间类型我们可以在这里修改
在配置文件中指定好时间的模式我们就可以输入了
静态资源管理
此信息在上面已经说过
欢迎页面的自动配置
Springboot会自动指定resources下的index.html
Springboot扩展springmvc
在实际开发中springboot并非完全自动化,很多跟业务相关我们需要自己扩展,springboot给我提供了接口。
我们可以来通过实现WebMvcConfigurer接口来扩展
public interface WebMvcConfigurer {
default void configurePathMatch(PathMatchConfigurer configurer) {
}
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
default void addFormatters(FormatterRegistry registry) {
}
default void addInterceptors(InterceptorRegistry registry) {
}
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
default void addCorsMappings(CorsRegistry registry) {
}
default void addViewControllers(ViewControllerRegistry registry) {
}
default void configureViewResolvers(ViewResolverRegistry registry) {
}
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
@Nullable
default Validator getValidator() {
return null;
}
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
在容器中注册视图控制器(请求转发)
例如:
创建一个MyMVCCofnig实现WebMvcConfigurer接口,实现一下addViewControllers方法,我们完成通过/tx访问,转发到success.html的工作
@Configuration
public class MyMVCCofnig implements WebMvcConfigurer{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/tx").setViewName("success");
}
注册格式化器
用来可以对请求过来的日期格式化的字符串来做定制化。当然通过application.properties配置也可以办到。
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new Formatter<Date>() {
@Override
public String print(Date date, Locale locale) {
return null;
}
@Override
public Date parse(String s, Locale locale) throws ParseException {
return new SimpleDateFormat("yyyy-MM-dd").parse(s);
}
});
}
消息转换器扩展fastjson
在pom.xml中引入fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
在配置类中配置消息转换器,添加fastjson
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fc = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fc.setFastJsonConfig(fastJsonConfig);
converters.add(fc);
}
在实体类上可以继续控制
public class User
{
private String username;
private String password;
private int age;
private int score;
private int gender;
@JSONField(format = "yyyy-MM-dd")
private Date date;
}
拦截器注册
1.创建拦截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("前置拦截");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("后置拦截");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("最终拦截");
}
}
2.拦截器注册
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/hello2");
}
配置嵌入式服务器
如何定制和修改Servlet容器的相关配置?
修改和server有关的配置(ServerProperties)
server.port=8081
server.context‐path=/tx
server.tomcat.uri‐encoding=UTF‐8
注册Servlet三大组件【Servlet、Filter、Listener】
由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。
//注册三大组件
//1.servlet
@Bean
public ServletRegistrationBean myServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new
MyServlet(),"/myServlet");
return registrationBean;
}
//2. FilterRegistrationBean
@Bean
public FilterRegistrationBean myFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new MyFilter());
registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet"));
return registrationBean;
}
//3. ServletListenerRegistrationBean
@Bean
public ServletListenerRegistrationBean myListener(){
ServletListenerRegistrationBean<MyListener> registrationBean = new
ServletListenerRegistrationBean<>(new MyListener());
return registrationBean;
}
SpringBoot帮我们自动SpringMVC的时候,自动的注册SpringMVC的前端控制器;DispatcherServlet;
DispatcherServletAutoConfiguration中:
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name =
DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public ServletRegistrationBean dispatcherServletRegistration(
DispatcherServlet dispatcherServlet) {
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet, this.serverProperties.getServletMapping());
//默认拦截: / 所有请求;包静态资源,但是不拦截jsp请求; /*会拦截jsp
//可以通过server.servletPath来修改SpringMVC前端控制器默认拦截的请求路径
registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
registration.setLoadOnStartup(
this.webMvcProperties.getServlet().getLoadOnStartup());
if (this.multipartConfig != null) {
registration.setMultipartConfig(this.multipartConfig);
}
return registration;
}
数据层开发
数据源自动管理
引入jdbc的依赖和springboot的应用场景
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
使用yaml方式配置,创建application.yaml
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/boot_demo
driver-class-name: com.mysql.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
在默认情况下, 数据库连接可以使用DataSource池进行自动配置
我们可以自己指定数据源配置,通过type来选取使用哪种数据源
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/boot_demo
driver-class-name: com.mysql.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
# type: org.apache.commons.dbcp2.BasicDataSource
配置druid数据源
引入druid的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
</dependency>
修改spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
在application.yaml中加入
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/boot_demo
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
创建数据源注册类
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource(){
return new DruidDataSource();
}
}
配置druid运行期监控
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource(){
return new DruidDataSource();
}
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),
"/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","root");
initParams.put("loginPassword","root");
initParams.put("allow","");//默认就是允许所有访问
initParams.put("deny","192.168.15.21");
bean.setInitParameters(initParams);
return bean;
}
//2、配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean;
bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
配置好后可以打开http://localhost:8080/druid查看
springboot整合jdbcTemplate
假设数据库中有一个user表
创建Controller
@Controller
public class TestController {
@Autowired
JdbcTemplate jdbcTemplate;
@ResponseBody
@RequestMapping("/query")
public List<Map<String, Object>> query(){
List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT * FROM user");
return maps;
}
}
启动springboot访问
http://localhost:8080/query
Springboot中提供了JdbcTemplateAutoConfiguration的自动配置
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,
JdbcTemplateAutoConfiguration源码:
Springboot整合mybatis注解版
导入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
步骤:
1)、配置数据源相关属性(见上一节Druid)
2)、给数据库建表
3)、创建JavaBean
public class TxPerson {
private int pid;
private String pname;
private String addr;
private int gender;
private Date birth;
}
4)创建Mapper
@Mapper
public interface TxPersonMapper {
@Select("select * from tx_person")
public List<TxPerson> getPersons();
@Select("select * from tx_person t where t.pid = #{id}")
public TxPerson getPersonById(int id);
@Options(useGeneratedKeys =true, keyProperty = "pid")
@Insert("insert into tx_person(pid, pname, addr,gender, birth)" +
" values(#{pid}, #{pname}, #{addr},#{gender}, #{birth})")
public void insert(TxPerson person);
@Delete("delete from tx_person where pid = #{id}")
public void update(int id);
}
单元测试
解决驼峰模式和数据库中下划线不能映射的问题
如果数据库如下:
编写一下配置类
@Configuration
public class MybatisConfig {
@Bean
public ConfigurationCustomizer getCustomizer(){
return new ConfigurationCustomizer() {
@Override
public void customize(org.apache.ibatis.session.Configuration configuration) {
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
查询结果:
TxPerson{pid=1, pname=‘张三’, pAddr=‘北京’, gender=1, birth=Thu Jun 14 00:00:00 CST 2018}
我们同样可以在mybatis的接口上不加@Mapper注解,通过扫描器注解来扫描
Mapper接口存放在cn.tx.mapper下
Springboot整合mybatis配置文件
在resources文件夹下创建sqlMapConfig.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
</configuration>
创建映射文件PersonMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.tx.mapper.TxPersonMapper">
<select id="getPersons" resultType="TxPerson">
select * from tx_person
</select>
</mapper>
在application.yaml中配置mybatis的信息
mybatis:
config-location: classpath:mybatis/sqlMapConfig.xml
mapper-locations: classpath:mybatis/mapper/*.xml
type-aliases-package: cn.tx.springboot.jdbc_demo1
至此springboot入门所有信息都已经介绍完毕