后端架构

基于 SpringBoot 框架 Web 应用设计与开发

原创 · 框架入门

初识SpringBoot2.x

本教材由于是企业级框架入门实战,所以使用本教材的人员应具备以下知识: - HTML、CSS、Js前端基础 - HTTP请求Web请求过程 - Java语言基础 - 面向对象编程思想 - 注解、MVC框架请求过程 - 了解SpringMVC框架

快速搭建一个MVC项目

来开头来个Hello World先吧,上官网,https://start.spring.io/,看图:

用IDE工具打开项目

下载解压后得到项目文件,推荐IntelliJ IDEA 开发工具,file-->open-->选择项目的路径,找打pom文件-->以project 形式打开

项目的目录结构说明

打开项目之后,maven 会加载必须的jar包,需要等待一段时间,注意观察底部状态栏,当项目构建完成之后,你会看到典型maven项目目录结构: 这里补充说明的是,HelloSpringbootApplication是整个项目的入口,我们启动项目不再是启动tomcat,而是运行这个类,这个类的main方法就是整个项目的入口。右击该类—Run。

SpringBoot2.x快速入门

Controller类型

Controller使用注解

@Controller注解

代码@Controller
public class HelloController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello() {
        return "Hi";
    }
}

直接使用会报一个错: 原因是缺少了模板的渲染,springboot支持的模板如下: - Thymeleaf - FreeMarker - Velocity - Groovy - Mustache 应当避免使用JSP,不然会丧失很多springboot特性!

Thymeleaf模板的使用

使用官方推荐的这个模板,先引入依赖:

代码<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

模板的默认位置是:src/main/resources/templates,在此位置下新建一个index.html 在代码中返回进行视图渲染:

代码@Controller
public class HelloController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello() {
        return "index";
    }
}

重新访问:

@RestController注解

通常用来返回Json格式数据,@Controller+@ResponseBody=@RestController

代码@RestController
public class HelloController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello() {
        return "index";
    }
}

直接返回了字符串,而不进行视图解析

@RequestMapping注解的使用

多个url映射

代码@RequestMapping(value = {"/hello", "/hi"}, method = RequestMethod.GET)
public String hello() {
    return "index";
}

在类上使用,用于窄化映射

代码@RestController
@RequestMapping(value = "/say")
public class HelloController {
    @RequestMapping(value = {"/hello", "/hi"}, method = RequestMethod.GET)
    public String hello() {
        return "index";
    }
}

Http Request的访问方式

测试POST可以通过postman谷歌插件或者下载独立软件进行。

请求URL参数注解的使用

基本上和SpringMVC是一致的:

@PathVariable注解

代码@RestController
public class HelloController {
    @RequestMapping(value = "/hello/{nm}", method = RequestMethod.GET)
    public String hello(@PathVariable("nm") String name) {
        return "your name is" + name;
    }
}

使用谷歌浏览器输入地址:http://localhost:8080/hello/yourName,查看结果。

@RequestParam注解

这个就是传统的?a=xxx形式的了:

代码@RestController
public class HelloController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello(@RequestParam("nm") String name) {
        return "your name is:" + name;
    }
}

使用谷歌浏览器输入地址:http://localhost:8080/hello?nm=yourName,查看结果。 当然,还可以有一些其他的常用特性,例如是否必须、给出默认值:

代码@RestController
public class HelloController {
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello(@RequestParam(value = "name",
            required = false, defaultValue = "jiangbei") String name) {
        return "your name is:" + name;
    }
}

如果required为true则请求过程中不能没有这个参数,否则将会抛出异常信息。

GetMapping形式的组合注解

其实就是对@RequestMapping进行了简化,省略了method=RequestMethod.GET,相应的还有配套的PostMapping等。

代码@RestController
public class HelloController {
    //@RequestMapping(value = "/hello", method = RequestMethod.GET)
    @GetMapping(value = "/hello")
    public String hello(@RequestParam(value = "name",
            required = false, defaultValue = "jiangbei") String name) {
        return "your name is:" + name;
    }
}

控制器与视图的数据交互

Thymeleaf获取Controller数据

使用内置Model对象的addAttribut方法向视图传递值

代码@RequestMapping(value = "message", method = RequestMethod.GET)
public String messages(Model model) {
    model.addAttribute("messages", messageRepository.findAll());
    return "message/list";
}

在ModelAndView的返回值中添加:

代码@RequestMapping(value = "message", method = RequestMethod.GET)
public ModelAndView messages() {
    ModelAndView mav = new ModelAndView("message/list");
    mav.addObject("messages", messageRepository.findAll());
    return mav;
}

通过@ModelAttribute注解的通知方式:

代码@ModelAttribute("messages")
public List<Message> messages() {
    return messageRepository.findAll();
}

上述的3种传递值方式在Thymeleaf视图中可以用${attributeName}来访问,这是一个SpringEL表达式,和Struts中的OGNL表达式类似。在Thymeleaf中访问model的Attributes方式如下:

代码<tr th:each="message : ${messages}">
    <td th:text="${message.id}">1</td>
    <td><a href="#" th:text="${message.title}">Title ...</a></td>
    <td th:text="${message.text}">Text ...</td>
</tr>

Thymeleaf获取URL中的参数

现在假设有一个@Controller控制器,控制器中重定向的方式发送一个request参数:

代码@Controller
public class SomeController {
    @RequestMapping("/")
    public String redirect() {
        return "redirect:/query?q=Thymeleaf Is Great!";
    }
}

访问参数q可以使用param前缀

代码<p th:text="${param.q[0]}" th:unless="${param.q == null}">Test</p>

例子中有两点需要注意:${param.q!=null}检查set中是否有参数q,参数是一个数组,因为它可以多值比如?q=a&r=b&q=c,因为地址中可能两个参数名一样,所以取值最好用${param.q[0]}代表取第一个q参数的值。还有一种访问方式是使用#httpServletRequest对象,不推荐使用。

Thymeleaf获取Session中的值

为session添加了一个mySessionAttribute属性:

代码@RequestMapping({"/"})
String index(HttpSession session) {
    session.setAttribute("mySessionAttribute", "someValue");
    return "index";
}

和Request参数访问方式类似,这里使用session前缀:

代码<div th:text="${session.mySessionAttribute}">[...]</div>

同样的,还可以使用#httpSession方式访问,不推荐使用。

Thymeleaf获取ServletContext值

访问ServletContext属性,可以用application前缀:

代码<table>
    <tr>
        <td>context中的attribute</td>
        <!-- 检索ServletContext的属性'myContextAttribute' -->
        <td th:text="${application.myContextAttribute}">42</td>
    </tr>
    <tr>
        <td>attributes数量:</td>
        <!-- 返回attributes的数量 -->
        <td th:text="${application.size()}">42</td>
    </tr>
    <tr th:each="attr : ${application.keySet()}">
        <!—遍历的application上下文集合-->
        <td th:text="${attr}">javax.servlet.context.tempdir</td>
        <td th:text="${application.get(attr)}">/tmp</td>
    </tr>
</table>

Thymeleaf访问Spring Beans

Thymeleaf可以<div th:text="${@urlService.getApplicationUrl()}">...</div>:

代码@Configuration
public class MyConfiguration {
    @Bean(name = "urlService")
    public UrlService urlService() {
        return new FixedUrlService("somedomain.com/myapp"); // 一个实现
    }
}

public interface UrlService {
    String getApplicationUrl();
}

注意:FixedUrlService必须是UrlService的实现类,也可以直接使用类本身,相当于<bean id="urlService " class="com.xxx. FixedUrlService "/>

SpringBoot中使用Servlet

启用Servlet

在入口Application类上加入注解@ServletComponentScan

代码@SpringBootApplication
@ServletComponentScan
public class UseServletInSpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(UseServletInSpringbootApplication.class, args);
    }
}

新建Servlet类

继承HttpServlet并且加入注解,代码如下:

代码@WebServlet(name="TestServlet",urlPatterns="/test")
public class TestServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException{
        System.out.println("doGet");
    }
}

测试结果

在地址栏输入 http://localhost:8080/test,若看到控制台打印doGet,则表示Servlet创建成功。

Springboot获取配置文件属性值篇

application.properties文件内容:

代码url.lm=editMessage
url.orgCode=100120171116031838

我们可以通过以下几种方式获取里面的值填充到类的属性上:

使用@ConfigurationProperties注解

代码@ConfigurationProperties(prefix="url")
public class ManyEnvProperties{
    private String lm;
    private String orgCode;

    //省略getter和setter
}

使用@Component和@Value注解

代码@Component
public class ManyEnvProperties {
    @Value("${url.lm}")
    private String lm1;
    @Value("${url.orgCode }")
    private String orgCode1;

    //省略getter和setter
}

此种方式属性名和properties文件中的key可以不一致。

使用Environment运行环境变量

显示注入, 其次是在需要的地方获取值

代码@Autowired
private Environment env;
logger.info("==============="+env.getProperty("url.lm")+"===============");

自定义的properties 文件

代码@Component
@ConfigurationProperties(prefix="url")
@PropertySource("classpath:/platform.properties")
public class PropertiesEnv {
    private String lm;
    private String orgCode;

    //省略getter和setter
}

把Springboot项目部署到tomcat容器

修改打包形式

在pom.xml里设置<packaging>war</packaging>

移除嵌入式tomcat插件

在pom.xml里找到spring-boot-starter-web依赖节点,在其下面添加如下代码:

代码<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 移除嵌入式tomcat插件 -->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

添加servlet-api的依赖

代码<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-servlet-api</artifactId>
    <version>8.0.36</version>
    <scope>provided</scope>
</dependency>

修改启动类,并重写初始化方法

代码@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder builder) {
        // 注意这里要指向原先用main方法执行的Application启动类
        return builder.sources(Application.class);
    }
}

打包部署

在项目根目录下(即包含pom.xml的目录),在命令行里输入:mvn clean package即可, 等待打包完成,出现[INFO] BUILD SUCCESS即为打包成功。然后把target目录下的war包放到tomcat的webapps目录下,启动tomcat,即可自动解压部署。最后在浏览器中输入 http://localhost:[端口号]/[打包项目名]/。

SpringBoot直接使用外置tomcat并配置jsp文件作为视图

使用Intellij Idea 2008向导创建SpringBoot2.x项目

选择构建工具为Gradle打包方式为war包

勾选项目依赖模块并配置本地Gradle路径

自动配置web.xml

创建出的项目默认是没有WEB-INF文件夹,通过菜单栏File找到Project Structure,注意webapp文件夹必须叫这个名字,Web Gradle:xxx.war包中就使用的这个文件夹名称。

配置外置tomcat环境

找到菜单栏Run—>Edit Configurations,点击加号+,找到Tomcat Server下面的Local,按照下图进行配置 切换到Deployment选项卡:

创建jsp视图和Controller

配置application.properties文件启用jsp视图,默认不支持

代码spring.mvc.view.prefix=/WEB-INF/Views/
spring.mvc.view.suffix=.jsp

编译项目打成war包并部署到tomcat

在gradle面板执行build命令,将项目打成war包(项目的build/libs下),然后启动tomcat部署war包,观察tomcat的webapps文件夹是否有app1文件夹,浏览器将自动打开,出现如下页面代表成功。