很久没有开坑了 这次记录一下使用idea工具来搭建一个最简单但是可运行的Spring Web应用程序,这个应用程序不使用web.xml进行配置~
MAVEN
首先,看下maven需要用到哪些包 :
4.0.0
groupId
第六章 渲染视图
1.0-SNAPSHOT
war
org.springframework
spring-context
5.0.8.RELEASE
org.springframework
spring-web
5.0.8.RELEASE
org.springframework
spring-webmvc
5.0.8.RELEASE
javax.servlet
javax.servlet-api
4.0.1
org.springframework
spring-test
4.3.12.RELEASE
org.springframework
spring-jdbc
4.3.12.RELEASE
com.alibaba
druid
1.1.10
mysql
mysql-connector-java
8.0.12
com.fasterxml.jackson.core
jackson-databind
2.9.6
javax.validation
validation-api
2.0.1.Final
org.hibernate.validator
hibernate-validator
6.0.12.Final
目录结构
然后我们通过maven的目录结构,在src/main目录下创建一个webapp包:
然后在webapp下再建立两个目录,resources和views。resources用来保存js、css信息,views保存页面信息……java目录下,建立以下目录 :config、controller、dao、pojo(是的,service省略了,因为重点不在业务处理,而是构建一个简单的Spring Web应用程序)。
建了这么多的目录,看一下现在的目录结构 :
创建完之后,你还需要在idea中进行如下设置 :
add -> Web -> 删除①中idea为我们打算生成的web.xml->改变②中的web路径
配置DispathcerServlet
配置DispatcherServlet
需要继承Spring的类 :AbstractAnnotationConfigDispatcherServletInitializer
:
package config;
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// 加载驱动应用后端的中间层和数据层组件
protected Class>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
// 加载Web组件的bean 如控制器、视图解析器以及处理器映射
protected Class>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
// 将DispatcherServlet映射到"/"
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
}
@Configuration
@EnableWebMvc
@ComponentScan(value = "controller")
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/views/");
resolver.setSuffix(".html");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
// 配置静态资源的处理
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/")
.addResourceLocations("/resources/**");
}
}
@Configuration
@ComponentScan(basePackages = {"dao"})
public class RootConfig {
}
编写控制器和视图
package controller;
@Controller
@RequestMapping(value = "/")
public class HomeController {
@GetMapping
public String home(){
return "home";
}
}
视图存放在下面的位置 :
我使用了semantic-ui来美化界面
微博
运行
运行效果如图所示 :
数据库连接
现在,运行效果图出现在了上面,我们要为这个程序加上数据库方面的配置 :
首先,需要在数据库中创建表
CREATE TABLE `spittle` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`message` varchar(100) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`latitude` double DEFAULT NULL,
`longitude` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8
然后,为这张表加几个数据 :
INSERT INTO graduate.spittle (message,created_at,latitude,longitude) VALUES
('hello world','2018-08-23 22:27:02.000',NULL,NULL)
,('第二条推特','2018-08-23 22:30:51.000',NULL,NULL)
,('天气不错','2018-08-23 22:37:40.000',NULL,NULL)
,('吃饭了吗','2018-08-24 05:17:17.000',NULL,NULL)
,('老古董怎么样','2018-08-24 05:17:42.000',NULL,NULL)
,('老许发表全新专辑','2018-08-24 05:17:59.000',NULL,NULL)
,('大千世界观后感','2018-08-24 05:18:15.000',NULL,NULL)
,('风居住的街道','2018-08-24 05:18:15.000',NULL,NULL)
,('寻宝游戏','2018-08-24 05:18:15.000',NULL,NULL)
,('动物世界','2018-08-24 05:18:15.000',NULL,NULL)
;
INSERT INTO graduate.spittle (message,created_at,latitude,longitude) VALUES
('燕归巢','2018-08-24 05:18:15.000',NULL,NULL)
,('艺术家们','2018-08-24 05:18:15.000',NULL,NULL)
,('九月清晨','2018-08-24 05:18:15.000',NULL,NULL)
,('重复重复','2018-08-24 05:33:05.000',NULL,NULL)
,('明智之举','2018-08-24 05:33:05.000',NULL,NULL)
,('柳成荫','2018-08-24 05:33:05.000',NULL,NULL)
;
配置数据源
我们在config包下面新建DataConfig类来配置数据源
package config;
@Configuration
public class DataConfig {
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDbType("mysql");
dataSource.setUrl("jdbc:mysql://127.0.0.1/graduate?serverTimezone=GMT&useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("root");
// 配置WallFilter
dataSource.setFilters("wall");
// PsCache
dataSource.setPoolPreparedStatements(false);
return dataSource;
}
@Bean
public JdbcOperations jdbcOperations(DataSource dataSource){
return new JdbcTemplate( dataSource);
}
}
当然,你还可以把数据库连接参数信息放到配置文件中 :
@Configuration
@PropertySource(value = "classpath:/application.properties")
public class DataConfig {
private final Environment environment;
@Autowired
public DataConfig(Environment environment) {
this.environment = environment;
}
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDbType(environment.getProperty("datasource.dbtype"));
dataSource.setUrl(environment.getProperty("datasource.url"));
dataSource.setUsername(environment.getProperty("datasource.username"));
dataSource.setPassword(environment.getProperty("datasource.password"));
// 配置WallFilter
dataSource.setFilters("wall");
// PsCache
dataSource.setPoolPreparedStatements(false);
return dataSource;
}
@Bean
public JdbcOperations jdbcOperations(DataSource dataSource){
return new JdbcTemplate( dataSource);
}
}
之后,我们修改RootConfig类:
@Configuration
@Import(value = {DataConfig.class})
@ComponentScan(basePackages = {"dao"})
public class RootConfig {
}
POJO
public class Spittle {
private final Long id;
private final String message;
private final Timestamp time;
private Double latitude;
private Double longitude;
// 省略set和get方法
}
编写dao层
package dao;
import pojo.Spittle;
import java.util.List;
public interface SpittleRepository {
/**
*
* @param max Spittle中ID的最大个数
* @param count 最多返回的Spittle个数
* @return
*/
List findSpittles(long max,int count);
Spittle findSpittle(Long spittleId);
}
@Repository
public class JdbcSpittleRepository implements SpittleRepository {
private final JdbcOperations jdbcOperations;
@Autowired
public JdbcSpittleRepository(JdbcOperations jdbcOperations) {
this.jdbcOperations = jdbcOperations;
}
@Override
public List findSpittles(long max , int count) {
return jdbcOperations.query("SELECT * FROM spittle WHERE ID < ? ORDER BY created_at desc LIMIT ?" ,
new SpittleRowMapper() , max , count);
}
@Override
public Spittle findSpittle(Long spittleId) {
return jdbcOperations.queryForObject("SELECT * FROM spittle WHERE id = ?",
new SpittleRowMapper(),spittleId);
}
private class SpittleRowMapper implements RowMapper{
@Override
public Spittle mapRow(ResultSet resultSet , int i) throws SQLException {
return new Spittle(resultSet.getLong("id"),
resultSet.getString("message"),
resultSet.getTimestamp("created_at"),
resultSet.getDouble("latitude"),
resultSet.getDouble("longitude")
);
}
}
}
编写controller层
@Controller
@RequestMapping(value = "/spittles")
public class SpittleController {
private final JdbcSpittleRepository spittleRepository;
private final String MAX_LONG_AS_STRING = "2147483647";
@Autowired
public SpittleController(JdbcSpittleRepository spittleRepository) {
this.spittleRepository = spittleRepository;
}
@GetMapping
public String showSpittle(){
return "/spittles";
}
@PostMapping
@ResponseBody
public Object spittleList(
@RequestParam(value = "max" , defaultValue = MAX_LONG_AS_STRING) long max,
@RequestParam(value = "count" , defaultValue = "10") int count){
return spittleRepository.findSpittles(max,count);
}
}
spittles.html
当前列表
{{ spittle.message }}
{{ spittle.time | formateDate }}